mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-04-11 00:44:33 +00:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
e081eb2c34
@ -40,8 +40,8 @@ script:
|
|||||||
- cd ./build
|
- cd ./build
|
||||||
- if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then ${ANALYZE}make -j2; fi
|
- if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then ${ANALYZE}make -j2; fi
|
||||||
- if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi
|
- if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi
|
||||||
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi
|
- if [ "$COVERITY_SCAN_BRANCH" != 1 ] && ["${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi
|
||||||
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then cd .. && ./CI/check_tabs.sh; fi
|
- if [ "$COVERITY_SCAN_BRANCH" != 1 ] && ["${TRAVIS_OS_NAME}" = "linux" ]; then cd .. && ./CI/check_tabs.sh; fi
|
||||||
notifications:
|
notifications:
|
||||||
recipients:
|
recipients:
|
||||||
- corrmage+travis-ci@gmail.com
|
- corrmage+travis-ci@gmail.com
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
OUTPUT=$(grep -nRP '\t' --include=\*.{cpp,hpp,c,h} apps components)
|
OUTPUT=$(grep -nRP '\t' --include=\*.{cpp,hpp,c,h} --exclude=ui_\* apps components)
|
||||||
|
|
||||||
if [[ $OUTPUT ]] ; then
|
if [[ $OUTPUT ]] ; then
|
||||||
echo "Error: Tab characters found!"
|
echo "Error: Tab characters found!"
|
||||||
|
@ -504,8 +504,6 @@ void CharacterController::refreshCurrentAnims(CharacterState idle, CharacterStat
|
|||||||
mAnimation->play(mCurrentIdle, idlePriority, MWRender::Animation::BlendMask_All, false,
|
mAnimation->play(mCurrentIdle, idlePriority, MWRender::Animation::BlendMask_All, false,
|
||||||
1.0f, "start", "stop", 0.0f, ~0ul, true);
|
1.0f, "start", "stop", 0.0f, ~0ul, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateIdleStormState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -656,6 +654,7 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim
|
|||||||
, mAnimation(anim)
|
, mAnimation(anim)
|
||||||
, mIdleState(CharState_None)
|
, mIdleState(CharState_None)
|
||||||
, mMovementState(CharState_None)
|
, mMovementState(CharState_None)
|
||||||
|
, mAdjustMovementAnimSpeed(false)
|
||||||
, mHasMovedInXY(false)
|
, mHasMovedInXY(false)
|
||||||
, mMovementAnimationControlled(true)
|
, mMovementAnimationControlled(true)
|
||||||
, mDeathState(CharState_None)
|
, mDeathState(CharState_None)
|
||||||
@ -867,7 +866,7 @@ void CharacterController::updatePtr(const MWWorld::Ptr &ptr)
|
|||||||
mPtr = ptr;
|
mPtr = ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterController::updateIdleStormState()
|
void CharacterController::updateIdleStormState(bool inwater)
|
||||||
{
|
{
|
||||||
bool inStormDirection = false;
|
bool inStormDirection = false;
|
||||||
if (MWBase::Environment::get().getWorld()->isInStorm())
|
if (MWBase::Environment::get().getWorld()->isInStorm())
|
||||||
@ -877,7 +876,7 @@ void CharacterController::updateIdleStormState()
|
|||||||
inStormDirection = std::acos(stormDirection * characterDirection / (stormDirection.length() * characterDirection.length()))
|
inStormDirection = std::acos(stormDirection * characterDirection / (stormDirection.length() * characterDirection.length()))
|
||||||
> osg::DegreesToRadians(120.f);
|
> osg::DegreesToRadians(120.f);
|
||||||
}
|
}
|
||||||
if (inStormDirection && mUpperBodyState == UpperCharState_Nothing && mAnimation->hasAnimation("idlestorm"))
|
if (inStormDirection && !inwater && mUpperBodyState == UpperCharState_Nothing && mAnimation->hasAnimation("idlestorm"))
|
||||||
{
|
{
|
||||||
float complete = 0;
|
float complete = 0;
|
||||||
mAnimation->getInfo("idlestorm", &complete);
|
mAnimation->getInfo("idlestorm", &complete);
|
||||||
@ -1796,6 +1795,7 @@ void CharacterController::update(float duration)
|
|||||||
forcestateupdate = updateCreatureState() || forcestateupdate;
|
forcestateupdate = updateCreatureState() || forcestateupdate;
|
||||||
|
|
||||||
refreshCurrentAnims(idlestate, movestate, jumpstate, forcestateupdate);
|
refreshCurrentAnims(idlestate, movestate, jumpstate, forcestateupdate);
|
||||||
|
updateIdleStormState(inwater);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inJump)
|
if (inJump)
|
||||||
@ -2122,7 +2122,7 @@ void CharacterController::updateHeadTracking(float duration)
|
|||||||
osg::Matrixf mat = mats[0];
|
osg::Matrixf mat = mats[0];
|
||||||
osg::Vec3f headPos = mat.getTrans();
|
osg::Vec3f headPos = mat.getTrans();
|
||||||
|
|
||||||
osg::Vec3f targetPos (mHeadTrackTarget.getRefData().getPosition().asVec3());
|
osg::Vec3f direction;
|
||||||
if (MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(mHeadTrackTarget))
|
if (MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(mHeadTrackTarget))
|
||||||
{
|
{
|
||||||
const osg::Node* node = anim->getNode("Head");
|
const osg::Node* node = anim->getNode("Head");
|
||||||
@ -2132,11 +2132,12 @@ void CharacterController::updateHeadTracking(float duration)
|
|||||||
{
|
{
|
||||||
osg::MatrixList mats = node->getWorldMatrices();
|
osg::MatrixList mats = node->getWorldMatrices();
|
||||||
if (mats.size())
|
if (mats.size())
|
||||||
targetPos = mats[0].getTrans();
|
direction = mats[0].getTrans() - headPos;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
// no head node to look at, fall back to look at center of collision box
|
||||||
|
direction = MWBase::Environment::get().getWorld()->aimToTarget(mPtr, mHeadTrackTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::Vec3f direction = targetPos - headPos;
|
|
||||||
direction.normalize();
|
direction.normalize();
|
||||||
|
|
||||||
if (!mPtr.getRefData().getBaseNode())
|
if (!mPtr.getRefData().getBaseNode())
|
||||||
|
@ -196,7 +196,7 @@ class CharacterController : public MWRender::Animation::TextKeyListener
|
|||||||
|
|
||||||
bool updateWeaponState();
|
bool updateWeaponState();
|
||||||
bool updateCreatureState();
|
bool updateCreatureState();
|
||||||
void updateIdleStormState();
|
void updateIdleStormState(bool inwater);
|
||||||
|
|
||||||
void updateHeadTracking(float duration);
|
void updateHeadTracking(float duration);
|
||||||
|
|
||||||
|
@ -95,6 +95,11 @@ void Actor::updatePosition()
|
|||||||
mCollisionObject->setWorldTransform(tr);
|
mCollisionObject->setWorldTransform(tr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
osg::Vec3f Actor::getPosition() const
|
||||||
|
{
|
||||||
|
return toOsg(mCollisionObject->getWorldTransform().getOrigin());
|
||||||
|
}
|
||||||
|
|
||||||
void Actor::updateRotation ()
|
void Actor::updateRotation ()
|
||||||
{
|
{
|
||||||
btTransform tr = mCollisionObject->getWorldTransform();
|
btTransform tr = mCollisionObject->getWorldTransform();
|
||||||
|
@ -70,6 +70,12 @@ namespace MWPhysics
|
|||||||
*/
|
*/
|
||||||
osg::Vec3f getHalfExtents() const;
|
osg::Vec3f getHalfExtents() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the position of the collision body
|
||||||
|
* @note The collision shape's origin is in its center, so the position returned can be described as center of the actor collision box in world space.
|
||||||
|
*/
|
||||||
|
osg::Vec3f getPosition() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the half extents of the collision body (scaled according to rendering scale)
|
* Returns the half extents of the collision body (scaled according to rendering scale)
|
||||||
* @note The reason we need this extra method is because of an inconsistency in MW - NPC race scales aren't applied to the collision shape,
|
* @note The reason we need this extra method is because of an inconsistency in MW - NPC race scales aren't applied to the collision shape,
|
||||||
|
@ -240,6 +240,8 @@ namespace MWPhysics
|
|||||||
const ESM::Position& refpos = ptr.getRefData().getPosition();
|
const ESM::Position& refpos = ptr.getRefData().getPosition();
|
||||||
osg::Vec3f position(refpos.asVec3());
|
osg::Vec3f position(refpos.asVec3());
|
||||||
|
|
||||||
|
float collisionShapeOffset = physicActor->getPosition().z() - position.z();
|
||||||
|
|
||||||
// Early-out for totally static creatures
|
// Early-out for totally static creatures
|
||||||
// (Not sure if gravity should still apply?)
|
// (Not sure if gravity should still apply?)
|
||||||
if (!ptr.getClass().isMobile(ptr))
|
if (!ptr.getClass().isMobile(ptr))
|
||||||
@ -256,12 +258,11 @@ namespace MWPhysics
|
|||||||
}
|
}
|
||||||
|
|
||||||
btCollisionObject *colobj = physicActor->getCollisionObject();
|
btCollisionObject *colobj = physicActor->getCollisionObject();
|
||||||
osg::Vec3f halfExtents = physicActor->getHalfExtents();
|
position.z() += collisionShapeOffset;
|
||||||
position.z() += halfExtents.z();
|
|
||||||
|
|
||||||
static const float fSwimHeightScale = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
|
static const float fSwimHeightScale = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
|
||||||
.find("fSwimHeightScale")->getFloat();
|
.find("fSwimHeightScale")->getFloat();
|
||||||
float swimlevel = waterlevel + halfExtents.z() - (physicActor->getRenderingHalfExtents().z() * 2 * fSwimHeightScale);
|
float swimlevel = waterlevel + collisionShapeOffset - (physicActor->getRenderingHalfExtents().z() * 2 * fSwimHeightScale);
|
||||||
|
|
||||||
ActorTracer tracer;
|
ActorTracer tracer;
|
||||||
osg::Vec3f inertia = physicActor->getInertialForce();
|
osg::Vec3f inertia = physicActor->getInertialForce();
|
||||||
@ -369,7 +370,7 @@ namespace MWPhysics
|
|||||||
{
|
{
|
||||||
// don't let pure water creatures move out of water after stepMove
|
// don't let pure water creatures move out of water after stepMove
|
||||||
if (ptr.getClass().isPureWaterCreature(ptr)
|
if (ptr.getClass().isPureWaterCreature(ptr)
|
||||||
&& newPosition.z() + halfExtents.z() > waterlevel)
|
&& newPosition.z() + physicActor->getHalfExtents().z() > waterlevel)
|
||||||
newPosition = oldPosition;
|
newPosition = oldPosition;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -450,7 +451,7 @@ namespace MWPhysics
|
|||||||
}
|
}
|
||||||
physicActor->setOnGround(isOnGround);
|
physicActor->setOnGround(isOnGround);
|
||||||
|
|
||||||
newPosition.z() -= halfExtents.z(); // remove what was added at the beginning
|
newPosition.z() -= collisionShapeOffset; // remove what was added at the beginning
|
||||||
return newPosition;
|
return newPosition;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -820,12 +821,8 @@ namespace MWPhysics
|
|||||||
if (!physactor1 || !physactor2)
|
if (!physactor1 || !physactor2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
osg::Vec3f halfExt1 = physactor1->getHalfExtents();
|
osg::Vec3f pos1 (physactor1->getPosition() + osg::Vec3f(0,0,physactor1->getHalfExtents().z() * 0.8)); // eye level
|
||||||
osg::Vec3f pos1 (actor1.getRefData().getPosition().asVec3());
|
osg::Vec3f pos2 (physactor2->getPosition() + osg::Vec3f(0,0,physactor2->getHalfExtents().z() * 0.8));
|
||||||
pos1.z() += halfExt1.z()*2*0.9f; // eye level
|
|
||||||
osg::Vec3f halfExt2 = physactor2->getHalfExtents();
|
|
||||||
osg::Vec3f pos2 (actor2.getRefData().getPosition().asVec3());
|
|
||||||
pos2.z() += halfExt2.z()*2*0.9f;
|
|
||||||
|
|
||||||
RayResult result = castRay(pos1, pos2, MWWorld::Ptr(), CollisionType_World|CollisionType_HeightMap);
|
RayResult result = castRay(pos1, pos2, MWWorld::Ptr(), CollisionType_World|CollisionType_HeightMap);
|
||||||
|
|
||||||
@ -869,24 +866,33 @@ namespace MWPhysics
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::Vec3f PhysicsSystem::getHalfExtents(const MWWorld::Ptr &actor)
|
osg::Vec3f PhysicsSystem::getHalfExtents(const MWWorld::Ptr &actor) const
|
||||||
{
|
{
|
||||||
Actor* physactor = getActor(actor);
|
const Actor* physactor = getActor(actor);
|
||||||
if (physactor)
|
if (physactor)
|
||||||
return physactor->getHalfExtents();
|
return physactor->getHalfExtents();
|
||||||
else
|
else
|
||||||
return osg::Vec3f();
|
return osg::Vec3f();
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::Vec3f PhysicsSystem::getRenderingHalfExtents(const MWWorld::Ptr &actor)
|
osg::Vec3f PhysicsSystem::getRenderingHalfExtents(const MWWorld::Ptr &actor) const
|
||||||
{
|
{
|
||||||
Actor* physactor = getActor(actor);
|
const Actor* physactor = getActor(actor);
|
||||||
if (physactor)
|
if (physactor)
|
||||||
return physactor->getRenderingHalfExtents();
|
return physactor->getRenderingHalfExtents();
|
||||||
else
|
else
|
||||||
return osg::Vec3f();
|
return osg::Vec3f();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
osg::Vec3f PhysicsSystem::getPosition(const MWWorld::Ptr &actor) const
|
||||||
|
{
|
||||||
|
const Actor* physactor = getActor(actor);
|
||||||
|
if (physactor)
|
||||||
|
return physactor->getPosition();
|
||||||
|
else
|
||||||
|
return osg::Vec3f();
|
||||||
|
}
|
||||||
|
|
||||||
class ContactTestResultCallback : public btCollisionWorld::ContactResultCallback
|
class ContactTestResultCallback : public btCollisionWorld::ContactResultCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -1036,6 +1042,14 @@ namespace MWPhysics
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Actor *PhysicsSystem::getActor(const MWWorld::Ptr &ptr) const
|
||||||
|
{
|
||||||
|
ActorMap::const_iterator found = mActors.find(ptr);
|
||||||
|
if (found != mActors.end())
|
||||||
|
return found->second;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void PhysicsSystem::updateScale(const MWWorld::Ptr &ptr)
|
void PhysicsSystem::updateScale(const MWWorld::Ptr &ptr)
|
||||||
{
|
{
|
||||||
ObjectMap::iterator found = mObjects.find(ptr);
|
ObjectMap::iterator found = mObjects.find(ptr);
|
||||||
|
@ -62,6 +62,7 @@ namespace MWPhysics
|
|||||||
void updatePtr (const MWWorld::Ptr& old, const MWWorld::Ptr& updated);
|
void updatePtr (const MWWorld::Ptr& old, const MWWorld::Ptr& updated);
|
||||||
|
|
||||||
Actor* getActor(const MWWorld::Ptr& ptr);
|
Actor* getActor(const MWWorld::Ptr& ptr);
|
||||||
|
const Actor* getActor(const MWWorld::Ptr& ptr) const;
|
||||||
|
|
||||||
// Object or Actor
|
// Object or Actor
|
||||||
void remove (const MWWorld::Ptr& ptr);
|
void remove (const MWWorld::Ptr& ptr);
|
||||||
@ -108,10 +109,14 @@ namespace MWPhysics
|
|||||||
bool isOnGround (const MWWorld::Ptr& actor);
|
bool isOnGround (const MWWorld::Ptr& actor);
|
||||||
|
|
||||||
/// Get physical half extents (scaled) of the given actor.
|
/// Get physical half extents (scaled) of the given actor.
|
||||||
osg::Vec3f getHalfExtents(const MWWorld::Ptr& actor);
|
osg::Vec3f getHalfExtents(const MWWorld::Ptr& actor) const;
|
||||||
|
|
||||||
/// @see MWPhysics::Actor::getRenderingHalfExtents
|
/// @see MWPhysics::Actor::getRenderingHalfExtents
|
||||||
osg::Vec3f getRenderingHalfExtents(const MWWorld::Ptr& actor);
|
osg::Vec3f getRenderingHalfExtents(const MWWorld::Ptr& actor) const;
|
||||||
|
|
||||||
|
/// Get the position of the collision shape for the actor. Use together with getHalfExtents() to get the collision bounds in world space.
|
||||||
|
/// @note The collision shape's origin is in its center, so the position returned can be described as center of the actor collision box in world space.
|
||||||
|
osg::Vec3f getPosition(const MWWorld::Ptr& actor) const;
|
||||||
|
|
||||||
/// Queues velocity movement for a Ptr. If a Ptr is already queued, its velocity will
|
/// Queues velocity movement for a Ptr. If a Ptr is already queued, its velocity will
|
||||||
/// be overwritten. Valid until the next call to applyQueuedMovement.
|
/// be overwritten. Valid until the next call to applyQueuedMovement.
|
||||||
|
@ -1111,25 +1111,6 @@ namespace MWRender
|
|||||||
attachTo->addChild(lightSource);
|
attachTo->addChild(lightSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
class DisableFreezeOnCullVisitor : public osg::NodeVisitor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DisableFreezeOnCullVisitor()
|
|
||||||
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void apply(osg::Geode &geode)
|
|
||||||
{
|
|
||||||
for (unsigned int i=0; i<geode.getNumDrawables(); ++i)
|
|
||||||
{
|
|
||||||
osg::Drawable* drw = geode.getDrawable(i);
|
|
||||||
if (osgParticle::ParticleSystem* partsys = dynamic_cast<osgParticle::ParticleSystem*>(drw))
|
|
||||||
partsys->setFreezeOnCull(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void Animation::addEffect (const std::string& model, int effectId, bool loop, const std::string& bonename, std::string texture)
|
void Animation::addEffect (const std::string& model, int effectId, bool loop, const std::string& bonename, std::string texture)
|
||||||
{
|
{
|
||||||
if (!mObjectRoot.get())
|
if (!mObjectRoot.get())
|
||||||
@ -1163,7 +1144,7 @@ namespace MWRender
|
|||||||
node->accept(findMaxLengthVisitor);
|
node->accept(findMaxLengthVisitor);
|
||||||
|
|
||||||
// FreezeOnCull doesn't work so well with effect particles, that tend to have moving emitters
|
// FreezeOnCull doesn't work so well with effect particles, that tend to have moving emitters
|
||||||
DisableFreezeOnCullVisitor disableFreezeOnCullVisitor;
|
SceneUtil::DisableFreezeOnCullVisitor disableFreezeOnCullVisitor;
|
||||||
node->accept(disableFreezeOnCullVisitor);
|
node->accept(disableFreezeOnCullVisitor);
|
||||||
|
|
||||||
params.mMaxControllerLength = findMaxLengthVisitor.getMaxLength();
|
params.mMaxControllerLength = findMaxLengthVisitor.getMaxLength();
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include <components/esm/loadcell.hpp>
|
#include <components/esm/loadcell.hpp>
|
||||||
|
|
||||||
#include "../mwworld/fallback.hpp"
|
#include "../mwworld/fallback.hpp"
|
||||||
|
#include "../mwworld/cellstore.hpp"
|
||||||
|
|
||||||
#include "sky.hpp"
|
#include "sky.hpp"
|
||||||
#include "effectmanager.hpp"
|
#include "effectmanager.hpp"
|
||||||
@ -130,6 +131,10 @@ namespace MWRender
|
|||||||
, mRootNode(rootNode)
|
, mRootNode(rootNode)
|
||||||
, mResourceSystem(resourceSystem)
|
, mResourceSystem(resourceSystem)
|
||||||
, mFogDepth(0.f)
|
, mFogDepth(0.f)
|
||||||
|
, mUnderwaterColor(fallback->getFallbackColour("Water_UnderwaterColor"))
|
||||||
|
, mUnderwaterWeight(fallback->getFallbackFloat("Water_UnderwaterColorWeight"))
|
||||||
|
, mUnderwaterFog(0.f)
|
||||||
|
, mUnderwaterIndoorFog(fallback->getFallbackFloat("Water_UnderwaterIndoorFog"))
|
||||||
, mNightEyeFactor(0.f)
|
, mNightEyeFactor(0.f)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<SceneUtil::LightManager> lightRoot = new SceneUtil::LightManager;
|
osg::ref_ptr<SceneUtil::LightManager> lightRoot = new SceneUtil::LightManager;
|
||||||
@ -201,10 +206,6 @@ namespace MWRender
|
|||||||
updateProjectionMatrix();
|
updateProjectionMatrix();
|
||||||
mStateUpdater->setFogEnd(mViewDistance);
|
mStateUpdater->setFogEnd(mViewDistance);
|
||||||
|
|
||||||
mUnderwaterColor = fallback->getFallbackColour("Water_UnderwaterColor");
|
|
||||||
mUnderwaterWeight = fallback->getFallbackFloat("Water_UnderwaterColorWeight");
|
|
||||||
mUnderwaterIndoorFog = fallback->getFallbackFloat("Water_UnderwaterIndoorFog");
|
|
||||||
|
|
||||||
mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("near", mNearClip));
|
mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("near", mNearClip));
|
||||||
mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("far", mViewDistance));
|
mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("far", mViewDistance));
|
||||||
}
|
}
|
||||||
@ -449,11 +450,13 @@ namespace MWRender
|
|||||||
void RenderingManager::setWaterEnabled(bool enabled)
|
void RenderingManager::setWaterEnabled(bool enabled)
|
||||||
{
|
{
|
||||||
mWater->setEnabled(enabled);
|
mWater->setEnabled(enabled);
|
||||||
|
mSky->setWaterEnabled(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingManager::setWaterHeight(float height)
|
void RenderingManager::setWaterHeight(float height)
|
||||||
{
|
{
|
||||||
mWater->setHeight(height);
|
mWater->setHeight(height);
|
||||||
|
mSky->setWaterHeight(height);
|
||||||
}
|
}
|
||||||
|
|
||||||
class NotifyDrawCompletedCallback : public osg::Camera::DrawCallback
|
class NotifyDrawCompletedCallback : public osg::Camera::DrawCallback
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include <components/sceneutil/util.hpp>
|
#include <components/sceneutil/util.hpp>
|
||||||
#include <components/sceneutil/statesetupdater.hpp>
|
#include <components/sceneutil/statesetupdater.hpp>
|
||||||
#include <components/sceneutil/controller.hpp>
|
#include <components/sceneutil/controller.hpp>
|
||||||
|
#include <components/sceneutil/visitor.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
@ -261,8 +262,18 @@ public:
|
|||||||
|
|
||||||
META_Node(MWRender, CameraRelativeTransform)
|
META_Node(MWRender, CameraRelativeTransform)
|
||||||
|
|
||||||
virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix, osg::NodeVisitor*) const
|
const osg::Vec3f& getLastEyePoint() const
|
||||||
{
|
{
|
||||||
|
return mEyePoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix, osg::NodeVisitor* nv) const
|
||||||
|
{
|
||||||
|
if (nv->getVisitorType() == osg::NodeVisitor::CULL_VISITOR)
|
||||||
|
{
|
||||||
|
mEyePoint = static_cast<osgUtil::CullVisitor*>(nv)->getEyePoint();
|
||||||
|
}
|
||||||
|
|
||||||
if (_referenceFrame==RELATIVE_RF)
|
if (_referenceFrame==RELATIVE_RF)
|
||||||
{
|
{
|
||||||
matrix.setTrans(osg::Vec3f(0.f,0.f,0.f));
|
matrix.setTrans(osg::Vec3f(0.f,0.f,0.f));
|
||||||
@ -321,6 +332,9 @@ public:
|
|||||||
cv->getCurrentCullingSet().popCurrentMask();
|
cv->getCurrentCullingSet().popCurrentMask();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
private:
|
||||||
|
// eyePoint for the current frame
|
||||||
|
mutable osg::Vec3f mEyePoint;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ModVertexAlphaVisitor : public osg::NodeVisitor
|
class ModVertexAlphaVisitor : public osg::NodeVisitor
|
||||||
@ -370,6 +384,45 @@ private:
|
|||||||
int mMeshType;
|
int mMeshType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// @brief Hides the node subgraph if the eye point is below water.
|
||||||
|
/// @note Must be added as cull callback.
|
||||||
|
/// @note Meant to be used on a node that is child of a CameraRelativeTransform.
|
||||||
|
/// The current eye point must be retrieved by the CameraRelativeTransform since we can't get it anymore once we are in camera-relative space.
|
||||||
|
class UnderwaterSwitchCallback : public osg::NodeCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UnderwaterSwitchCallback(CameraRelativeTransform* cameraRelativeTransform)
|
||||||
|
: mCameraRelativeTransform(cameraRelativeTransform)
|
||||||
|
, mEnabled(true)
|
||||||
|
, mWaterLevel(0.f)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||||
|
{
|
||||||
|
osg::Vec3f eyePoint = mCameraRelativeTransform->getLastEyePoint();
|
||||||
|
|
||||||
|
if (mEnabled && eyePoint.z() < mWaterLevel)
|
||||||
|
return;
|
||||||
|
|
||||||
|
traverse(node, nv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
mEnabled = enabled;
|
||||||
|
}
|
||||||
|
void setWaterLevel(float waterLevel)
|
||||||
|
{
|
||||||
|
mWaterLevel = waterLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
osg::ref_ptr<CameraRelativeTransform> mCameraRelativeTransform;
|
||||||
|
bool mEnabled;
|
||||||
|
float mWaterLevel;
|
||||||
|
};
|
||||||
|
|
||||||
/// A base class for the sun and moons.
|
/// A base class for the sun and moons.
|
||||||
class CelestialBody
|
class CelestialBody
|
||||||
{
|
{
|
||||||
@ -1065,18 +1118,21 @@ SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneMana
|
|||||||
|
|
||||||
mRootNode = skyroot;
|
mRootNode = skyroot;
|
||||||
|
|
||||||
// By default render before the world is rendered
|
mEarlyRenderBinRoot = new osg::Group;
|
||||||
mRootNode->getOrCreateStateSet()->setRenderBinDetails(RenderBin_Sky, "RenderBin");
|
// render before the world is rendered
|
||||||
|
mEarlyRenderBinRoot->getOrCreateStateSet()->setRenderBinDetails(RenderBin_Sky, "RenderBin");
|
||||||
// Prevent unwanted clipping by water reflection camera's clipping plane
|
// Prevent unwanted clipping by water reflection camera's clipping plane
|
||||||
mRootNode->getOrCreateStateSet()->setMode(GL_CLIP_PLANE0, osg::StateAttribute::OFF);
|
mEarlyRenderBinRoot->getOrCreateStateSet()->setMode(GL_CLIP_PLANE0, osg::StateAttribute::OFF);
|
||||||
|
mRootNode->addChild(mEarlyRenderBinRoot);
|
||||||
|
|
||||||
|
mUnderwaterSwitch = new UnderwaterSwitchCallback(skyroot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkyManager::create()
|
void SkyManager::create()
|
||||||
{
|
{
|
||||||
assert(!mCreated);
|
assert(!mCreated);
|
||||||
|
|
||||||
mAtmosphereDay = mSceneManager->createInstance("meshes/sky_atmosphere.nif", mRootNode);
|
mAtmosphereDay = mSceneManager->createInstance("meshes/sky_atmosphere.nif", mEarlyRenderBinRoot);
|
||||||
ModVertexAlphaVisitor modAtmosphere(0);
|
ModVertexAlphaVisitor modAtmosphere(0);
|
||||||
mAtmosphereDay->accept(modAtmosphere);
|
mAtmosphereDay->accept(modAtmosphere);
|
||||||
|
|
||||||
@ -1085,7 +1141,7 @@ void SkyManager::create()
|
|||||||
|
|
||||||
mAtmosphereNightNode = new osg::PositionAttitudeTransform;
|
mAtmosphereNightNode = new osg::PositionAttitudeTransform;
|
||||||
mAtmosphereNightNode->setNodeMask(0);
|
mAtmosphereNightNode->setNodeMask(0);
|
||||||
mRootNode->addChild(mAtmosphereNightNode);
|
mEarlyRenderBinRoot->addChild(mAtmosphereNightNode);
|
||||||
|
|
||||||
osg::ref_ptr<osg::Node> atmosphereNight;
|
osg::ref_ptr<osg::Node> atmosphereNight;
|
||||||
if (mSceneManager->getVFS()->exists("meshes/sky_night_02.nif"))
|
if (mSceneManager->getVFS()->exists("meshes/sky_night_02.nif"))
|
||||||
@ -1098,14 +1154,14 @@ void SkyManager::create()
|
|||||||
mAtmosphereNightUpdater = new AtmosphereNightUpdater(mSceneManager->getTextureManager());
|
mAtmosphereNightUpdater = new AtmosphereNightUpdater(mSceneManager->getTextureManager());
|
||||||
atmosphereNight->addUpdateCallback(mAtmosphereNightUpdater);
|
atmosphereNight->addUpdateCallback(mAtmosphereNightUpdater);
|
||||||
|
|
||||||
mSun.reset(new Sun(mRootNode, *mSceneManager->getTextureManager()));
|
mSun.reset(new Sun(mEarlyRenderBinRoot, *mSceneManager->getTextureManager()));
|
||||||
|
|
||||||
const MWWorld::Fallback* fallback=MWBase::Environment::get().getWorld()->getFallback();
|
const MWWorld::Fallback* fallback=MWBase::Environment::get().getWorld()->getFallback();
|
||||||
mMasser.reset(new Moon(mRootNode, *mSceneManager->getTextureManager(), fallback->getFallbackFloat("Moons_Masser_Size")/125, Moon::Type_Masser));
|
mMasser.reset(new Moon(mEarlyRenderBinRoot, *mSceneManager->getTextureManager(), fallback->getFallbackFloat("Moons_Masser_Size")/125, Moon::Type_Masser));
|
||||||
mSecunda.reset(new Moon(mRootNode, *mSceneManager->getTextureManager(), fallback->getFallbackFloat("Moons_Secunda_Size")/125, Moon::Type_Secunda));
|
mSecunda.reset(new Moon(mEarlyRenderBinRoot, *mSceneManager->getTextureManager(), fallback->getFallbackFloat("Moons_Secunda_Size")/125, Moon::Type_Secunda));
|
||||||
|
|
||||||
mCloudNode = new osg::PositionAttitudeTransform;
|
mCloudNode = new osg::PositionAttitudeTransform;
|
||||||
mRootNode->addChild(mCloudNode);
|
mEarlyRenderBinRoot->addChild(mCloudNode);
|
||||||
mCloudMesh = mSceneManager->createInstance("meshes/sky_clouds_01.nif", mCloudNode);
|
mCloudMesh = mSceneManager->createInstance("meshes/sky_clouds_01.nif", mCloudNode);
|
||||||
ModVertexAlphaVisitor modClouds(1);
|
ModVertexAlphaVisitor modClouds(1);
|
||||||
mCloudMesh->accept(modClouds);
|
mCloudMesh->accept(modClouds);
|
||||||
@ -1122,9 +1178,9 @@ void SkyManager::create()
|
|||||||
|
|
||||||
osg::ref_ptr<osg::Depth> depth = new osg::Depth;
|
osg::ref_ptr<osg::Depth> depth = new osg::Depth;
|
||||||
depth->setWriteMask(false);
|
depth->setWriteMask(false);
|
||||||
mRootNode->getOrCreateStateSet()->setAttributeAndModes(depth, osg::StateAttribute::ON);
|
mEarlyRenderBinRoot->getOrCreateStateSet()->setAttributeAndModes(depth, osg::StateAttribute::ON);
|
||||||
mRootNode->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
|
mEarlyRenderBinRoot->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
|
||||||
mRootNode->getOrCreateStateSet()->setMode(GL_FOG, osg::StateAttribute::OFF);
|
mEarlyRenderBinRoot->getOrCreateStateSet()->setMode(GL_FOG, osg::StateAttribute::OFF);
|
||||||
|
|
||||||
mMoonScriptColor = fallback->getFallbackColour("Moons_Script_Color");
|
mMoonScriptColor = fallback->getFallbackColour("Moons_Script_Color");
|
||||||
|
|
||||||
@ -1196,14 +1252,13 @@ public:
|
|||||||
mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(0,0,0,mAlpha));
|
mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(0,0,0,mAlpha));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper for adding AlphaFader to a subgraph
|
// Helper for adding AlphaFaders to a subgraph
|
||||||
class SetupVisitor : public osg::NodeVisitor
|
class SetupVisitor : public osg::NodeVisitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SetupVisitor()
|
SetupVisitor()
|
||||||
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||||
{
|
{
|
||||||
mAlphaFader = new AlphaFader;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void apply(osg::Node &node)
|
virtual void apply(osg::Node &node)
|
||||||
@ -1225,22 +1280,26 @@ public:
|
|||||||
callback = callback->getNestedCallback();
|
callback = callback->getNestedCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
osg::ref_ptr<AlphaFader> alphaFader (new AlphaFader);
|
||||||
|
|
||||||
if (composite)
|
if (composite)
|
||||||
composite->addController(mAlphaFader);
|
composite->addController(alphaFader);
|
||||||
else
|
else
|
||||||
node.addUpdateCallback(mAlphaFader);
|
node.addUpdateCallback(alphaFader);
|
||||||
|
|
||||||
|
mAlphaFaders.push_back(alphaFader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
traverse(node);
|
traverse(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::ref_ptr<AlphaFader> getAlphaFader()
|
std::vector<osg::ref_ptr<AlphaFader> > getAlphaFaders()
|
||||||
{
|
{
|
||||||
return mAlphaFader;
|
return mAlphaFaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
osg::ref_ptr<AlphaFader> mAlphaFader;
|
std::vector<osg::ref_ptr<AlphaFader> > mAlphaFaders;
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -1278,6 +1337,7 @@ void SkyManager::createRain()
|
|||||||
stateset->setNestRenderBins(false);
|
stateset->setNestRenderBins(false);
|
||||||
stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||||
stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
|
stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
|
||||||
|
stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
|
||||||
|
|
||||||
osgParticle::Particle& particleTemplate = mRainParticleSystem->getDefaultParticleTemplate();
|
osgParticle::Particle& particleTemplate = mRainParticleSystem->getDefaultParticleTemplate();
|
||||||
particleTemplate.setSizeRange(osgParticle::rangef(5.f, 15.f));
|
particleTemplate.setSizeRange(osgParticle::rangef(5.f, 15.f));
|
||||||
@ -1313,6 +1373,8 @@ void SkyManager::createRain()
|
|||||||
|
|
||||||
mRainFader = new RainFader;
|
mRainFader = new RainFader;
|
||||||
mRainNode->addUpdateCallback(mRainFader);
|
mRainNode->addUpdateCallback(mRainFader);
|
||||||
|
mRainNode->addCullCallback(mUnderwaterSwitch);
|
||||||
|
mRainNode->setNodeMask(Mask_WeatherParticles);
|
||||||
|
|
||||||
mRootNode->addChild(mRainNode);
|
mRootNode->addChild(mRainNode);
|
||||||
}
|
}
|
||||||
@ -1432,6 +1494,14 @@ void SkyManager::setWeather(const WeatherResult& weather)
|
|||||||
{
|
{
|
||||||
mCurrentParticleEffect = weather.mParticleEffect;
|
mCurrentParticleEffect = weather.mParticleEffect;
|
||||||
|
|
||||||
|
// cleanup old particles
|
||||||
|
if (mParticleEffect)
|
||||||
|
{
|
||||||
|
mParticleNode->removeChild(mParticleEffect);
|
||||||
|
mParticleEffect = NULL;
|
||||||
|
mParticleFaders.clear();
|
||||||
|
}
|
||||||
|
|
||||||
if (mCurrentParticleEffect.empty())
|
if (mCurrentParticleEffect.empty())
|
||||||
{
|
{
|
||||||
if (mParticleNode)
|
if (mParticleNode)
|
||||||
@ -1439,14 +1509,14 @@ void SkyManager::setWeather(const WeatherResult& weather)
|
|||||||
mRootNode->removeChild(mParticleNode);
|
mRootNode->removeChild(mParticleNode);
|
||||||
mParticleNode = NULL;
|
mParticleNode = NULL;
|
||||||
}
|
}
|
||||||
mParticleEffect = NULL;
|
|
||||||
mParticleFader = NULL;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!mParticleNode)
|
if (!mParticleNode)
|
||||||
{
|
{
|
||||||
mParticleNode = new osg::PositionAttitudeTransform;
|
mParticleNode = new osg::PositionAttitudeTransform;
|
||||||
|
mParticleNode->addCullCallback(mUnderwaterSwitch);
|
||||||
|
mParticleNode->setNodeMask(Mask_WeatherParticles);
|
||||||
mRootNode->addChild(mParticleNode);
|
mRootNode->addChild(mParticleNode);
|
||||||
}
|
}
|
||||||
mParticleEffect = mSceneManager->createInstance(mCurrentParticleEffect, mParticleNode);
|
mParticleEffect = mSceneManager->createInstance(mCurrentParticleEffect, mParticleNode);
|
||||||
@ -1456,7 +1526,10 @@ void SkyManager::setWeather(const WeatherResult& weather)
|
|||||||
|
|
||||||
AlphaFader::SetupVisitor alphaFaderSetupVisitor;
|
AlphaFader::SetupVisitor alphaFaderSetupVisitor;
|
||||||
mParticleEffect->accept(alphaFaderSetupVisitor);
|
mParticleEffect->accept(alphaFaderSetupVisitor);
|
||||||
mParticleFader = alphaFaderSetupVisitor.getAlphaFader();
|
mParticleFaders = alphaFaderSetupVisitor.getAlphaFaders();
|
||||||
|
|
||||||
|
SceneUtil::DisableFreezeOnCullVisitor disableFreezeOnCullVisitor;
|
||||||
|
mParticleEffect->accept(disableFreezeOnCullVisitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1537,8 +1610,8 @@ void SkyManager::setWeather(const WeatherResult& weather)
|
|||||||
|
|
||||||
if (mRainFader)
|
if (mRainFader)
|
||||||
mRainFader->setAlpha(weather.mEffectFade * 0.6); // * Rain_Threshold?
|
mRainFader->setAlpha(weather.mEffectFade * 0.6); // * Rain_Threshold?
|
||||||
if (mParticleFader)
|
for (std::vector<osg::ref_ptr<AlphaFader> >::const_iterator it = mParticleFaders.begin(); it != mParticleFaders.end(); ++it)
|
||||||
mParticleFader->setAlpha(weather.mEffectFade);
|
(*it)->setAlpha(weather.mEffectFade);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkyManager::sunEnable()
|
void SkyManager::sunEnable()
|
||||||
@ -1592,4 +1665,14 @@ void SkyManager::setGlareTimeOfDayFade(float val)
|
|||||||
mSun->setGlareTimeOfDayFade(val);
|
mSun->setGlareTimeOfDayFade(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkyManager::setWaterHeight(float height)
|
||||||
|
{
|
||||||
|
mUnderwaterSwitch->setWaterLevel(height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkyManager::setWaterEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
mUnderwaterSwitch->setEnabled(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ namespace MWRender
|
|||||||
class RainShooter;
|
class RainShooter;
|
||||||
class RainFader;
|
class RainFader;
|
||||||
class AlphaFader;
|
class AlphaFader;
|
||||||
|
class UnderwaterSwitchCallback;
|
||||||
|
|
||||||
struct WeatherResult
|
struct WeatherResult
|
||||||
{
|
{
|
||||||
@ -100,6 +101,8 @@ namespace MWRender
|
|||||||
float mMoonAlpha;
|
float mMoonAlpha;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///@brief The SkyManager handles rendering of the sky domes, celestial bodies as well as other objects that need to be rendered
|
||||||
|
/// relative to the camera (e.g. weather particle effects)
|
||||||
class SkyManager
|
class SkyManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -144,6 +147,12 @@ namespace MWRender
|
|||||||
|
|
||||||
void setGlareTimeOfDayFade(float val);
|
void setGlareTimeOfDayFade(float val);
|
||||||
|
|
||||||
|
/// Enable or disable the water plane (used to remove underwater weather particles)
|
||||||
|
void setWaterEnabled(bool enabled);
|
||||||
|
|
||||||
|
/// Set height of water plane (used to remove underwater weather particles)
|
||||||
|
void setWaterHeight(float height);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void create();
|
void create();
|
||||||
///< no need to call this, automatically done on first enable()
|
///< no need to call this, automatically done on first enable()
|
||||||
@ -155,10 +164,12 @@ namespace MWRender
|
|||||||
Resource::SceneManager* mSceneManager;
|
Resource::SceneManager* mSceneManager;
|
||||||
|
|
||||||
osg::ref_ptr<osg::Group> mRootNode;
|
osg::ref_ptr<osg::Group> mRootNode;
|
||||||
|
osg::ref_ptr<osg::Group> mEarlyRenderBinRoot;
|
||||||
|
|
||||||
osg::ref_ptr<osg::PositionAttitudeTransform> mParticleNode;
|
osg::ref_ptr<osg::PositionAttitudeTransform> mParticleNode;
|
||||||
osg::ref_ptr<osg::Node> mParticleEffect;
|
osg::ref_ptr<osg::Node> mParticleEffect;
|
||||||
osg::ref_ptr<AlphaFader> mParticleFader;
|
std::vector<osg::ref_ptr<AlphaFader> > mParticleFaders;
|
||||||
|
osg::ref_ptr<UnderwaterSwitchCallback> mUnderwaterSwitch;
|
||||||
|
|
||||||
osg::ref_ptr<osg::PositionAttitudeTransform> mCloudNode;
|
osg::ref_ptr<osg::PositionAttitudeTransform> mCloudNode;
|
||||||
|
|
||||||
|
@ -15,21 +15,26 @@ namespace MWRender
|
|||||||
Mask_Actor = (1<<3),
|
Mask_Actor = (1<<3),
|
||||||
Mask_Player = (1<<4),
|
Mask_Player = (1<<4),
|
||||||
Mask_Sky = (1<<5),
|
Mask_Sky = (1<<5),
|
||||||
Mask_Sun = (1<<6),
|
Mask_Water = (1<<6),
|
||||||
Mask_Water = (1<<7),
|
Mask_Terrain = (1<<7),
|
||||||
Mask_SimpleWater = (1<<8),
|
Mask_FirstPerson = (1<<8),
|
||||||
Mask_Terrain = (1<<9),
|
|
||||||
Mask_FirstPerson = (1<<10),
|
// child of Sky
|
||||||
|
Mask_Sun = (1<<9),
|
||||||
|
Mask_WeatherParticles = (1<<10),
|
||||||
|
|
||||||
|
// child of Water
|
||||||
|
Mask_SimpleWater = (1<<11),
|
||||||
|
|
||||||
// top level masks
|
// top level masks
|
||||||
Mask_Scene = (1<<11),
|
Mask_Scene = (1<<12),
|
||||||
Mask_GUI = (1<<12),
|
Mask_GUI = (1<<13),
|
||||||
|
|
||||||
// Set on a Geode
|
// Set on a Geode
|
||||||
Mask_ParticleSystem = (1<<13),
|
Mask_ParticleSystem = (1<<14),
|
||||||
|
|
||||||
// Set on cameras within the main scene graph
|
// Set on cameras within the main scene graph
|
||||||
Mask_RenderToTexture = (1<<14)
|
Mask_RenderToTexture = (1<<15)
|
||||||
|
|
||||||
// reserved: (1<<16) for SceneUtil::Mask_Lit
|
// reserved: (1<<16) for SceneUtil::Mask_Lit
|
||||||
};
|
};
|
||||||
|
@ -33,6 +33,9 @@
|
|||||||
|
|
||||||
#include <components/esm/loadcell.hpp>
|
#include <components/esm/loadcell.hpp>
|
||||||
|
|
||||||
|
#include "../mwworld/cellstore.hpp"
|
||||||
|
#include "../mwworld/fallback.hpp"
|
||||||
|
|
||||||
#include "vismask.hpp"
|
#include "vismask.hpp"
|
||||||
#include "ripplesimulation.hpp"
|
#include "ripplesimulation.hpp"
|
||||||
#include "renderbin.hpp"
|
#include "renderbin.hpp"
|
||||||
@ -79,6 +82,10 @@ namespace
|
|||||||
waterGeom->setVertexArray(verts);
|
waterGeom->setVertexArray(verts);
|
||||||
waterGeom->setTexCoordArray(0, texcoords);
|
waterGeom->setTexCoordArray(0, texcoords);
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Vec3Array> normal (new osg::Vec3Array);
|
||||||
|
normal->push_back(osg::Vec3f(0,0,1));
|
||||||
|
waterGeom->setNormalArray(normal, osg::Array::BIND_OVERALL);
|
||||||
|
|
||||||
waterGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,verts->size()));
|
waterGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,verts->size()));
|
||||||
return waterGeom;
|
return waterGeom;
|
||||||
}
|
}
|
||||||
@ -145,12 +152,9 @@ class ClipCullNode : public osg::Group
|
|||||||
|
|
||||||
osg::RefMatrix* modelViewMatrix = new osg::RefMatrix(*cv->getModelViewMatrix());
|
osg::RefMatrix* modelViewMatrix = new osg::RefMatrix(*cv->getModelViewMatrix());
|
||||||
|
|
||||||
// move the plane back along its normal a little bit to prevent bleeding at the water shore
|
// apply the height of the plane
|
||||||
const float clipFudge = -5;
|
|
||||||
// now apply the height of the plane
|
|
||||||
// we can't apply this height in the addClipPlane() since the "flip the below graph" function would otherwise flip the height as well
|
// we can't apply this height in the addClipPlane() since the "flip the below graph" function would otherwise flip the height as well
|
||||||
float translate = clipFudge + ((*mCullPlane)[3] * -1);
|
modelViewMatrix->preMultTranslate(mCullPlane->getNormal() * ((*mCullPlane)[3] * -1));
|
||||||
modelViewMatrix->preMultTranslate(mCullPlane->getNormal() * translate);
|
|
||||||
|
|
||||||
// flip the below graph if the eye point is above the plane
|
// flip the below graph if the eye point is above the plane
|
||||||
if (mCullPlane->intersect(osg::BoundingSphere(osg::Vec3d(0,0,eyePoint.z()), 0)) > 0)
|
if (mCullPlane->intersect(osg::BoundingSphere(osg::Vec3d(0,0,eyePoint.z()), 0)) > 0)
|
||||||
@ -158,6 +162,10 @@ class ClipCullNode : public osg::Group
|
|||||||
modelViewMatrix->preMultScale(osg::Vec3(1,1,-1));
|
modelViewMatrix->preMultScale(osg::Vec3(1,1,-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// move the plane back along its normal a little bit to prevent bleeding at the water shore
|
||||||
|
const float clipFudge = -5;
|
||||||
|
modelViewMatrix->preMultTranslate(mCullPlane->getNormal() * clipFudge);
|
||||||
|
|
||||||
cv->pushModelViewMatrix(modelViewMatrix, osg::Transform::RELATIVE_RF);
|
cv->pushModelViewMatrix(modelViewMatrix, osg::Transform::RELATIVE_RF);
|
||||||
traverse(node, nv);
|
traverse(node, nv);
|
||||||
cv->popModelViewMatrix();
|
cv->popModelViewMatrix();
|
||||||
@ -451,6 +459,7 @@ Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem
|
|||||||
: mParent(parent)
|
: mParent(parent)
|
||||||
, mSceneRoot(sceneRoot)
|
, mSceneRoot(sceneRoot)
|
||||||
, mResourceSystem(resourceSystem)
|
, mResourceSystem(resourceSystem)
|
||||||
|
, mFallback(fallback)
|
||||||
, mResourcePath(resourcePath)
|
, mResourcePath(resourcePath)
|
||||||
, mEnabled(true)
|
, mEnabled(true)
|
||||||
, mToggled(true)
|
, mToggled(true)
|
||||||
@ -474,7 +483,7 @@ Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem
|
|||||||
|
|
||||||
// simple water fallback for the local map
|
// simple water fallback for the local map
|
||||||
osg::ref_ptr<osg::Geode> geode2 (osg::clone(mWaterGeode.get(), osg::CopyOp::DEEP_COPY_NODES));
|
osg::ref_ptr<osg::Geode> geode2 (osg::clone(mWaterGeode.get(), osg::CopyOp::DEEP_COPY_NODES));
|
||||||
createSimpleWaterStateSet(geode2);
|
createSimpleWaterStateSet(geode2, mFallback->getFallbackFloat("Water_Map_Alpha"));
|
||||||
geode2->setNodeMask(Mask_SimpleWater);
|
geode2->setNodeMask(Mask_SimpleWater);
|
||||||
mWaterNode->addChild(geode2);
|
mWaterNode->addChild(geode2);
|
||||||
|
|
||||||
@ -516,19 +525,19 @@ void Water::updateWaterMaterial()
|
|||||||
createShaderWaterStateSet(mWaterGeode, mReflection, mRefraction);
|
createShaderWaterStateSet(mWaterGeode, mReflection, mRefraction);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
createSimpleWaterStateSet(mWaterGeode);
|
createSimpleWaterStateSet(mWaterGeode, mFallback->getFallbackFloat("Water_World_Alpha"));
|
||||||
|
|
||||||
updateVisible();
|
updateVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Water::createSimpleWaterStateSet(osg::Node* node)
|
void Water::createSimpleWaterStateSet(osg::Node* node, float alpha)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::StateSet> stateset (new osg::StateSet);
|
osg::ref_ptr<osg::StateSet> stateset (new osg::StateSet);
|
||||||
|
|
||||||
osg::ref_ptr<osg::Material> material (new osg::Material);
|
osg::ref_ptr<osg::Material> material (new osg::Material);
|
||||||
material->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4f(1.f, 1.f, 1.f, 1.f));
|
material->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 1.f));
|
||||||
material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 0.7f));
|
material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(1.f, 1.f, 1.f, alpha));
|
||||||
material->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 1.f));
|
material->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(1.f, 1.f, 1.f, 1.f));
|
||||||
material->setColorMode(osg::Material::OFF);
|
material->setColorMode(osg::Material::OFF);
|
||||||
stateset->setAttributeAndModes(material, osg::StateAttribute::ON);
|
stateset->setAttributeAndModes(material, osg::StateAttribute::ON);
|
||||||
|
|
||||||
@ -542,14 +551,18 @@ void Water::createSimpleWaterStateSet(osg::Node* node)
|
|||||||
stateset->setRenderBinDetails(MWRender::RenderBin_Water, "RenderBin");
|
stateset->setRenderBinDetails(MWRender::RenderBin_Water, "RenderBin");
|
||||||
|
|
||||||
std::vector<osg::ref_ptr<osg::Texture2D> > textures;
|
std::vector<osg::ref_ptr<osg::Texture2D> > textures;
|
||||||
for (int i=0; i<32; ++i)
|
int frameCount = mFallback->getFallbackInt("Water_SurfaceFrameCount");
|
||||||
|
std::string texture = mFallback->getFallbackString("Water_SurfaceTexture");
|
||||||
|
for (int i=0; i<frameCount; ++i)
|
||||||
{
|
{
|
||||||
std::ostringstream texname;
|
std::ostringstream texname;
|
||||||
texname << "textures/water/water" << std::setw(2) << std::setfill('0') << i << ".dds";
|
texname << "textures/water/" << texture << std::setw(2) << std::setfill('0') << i << ".dds";
|
||||||
textures.push_back(mResourceSystem->getTextureManager()->getTexture2D(texname.str(), osg::Texture::REPEAT, osg::Texture::REPEAT));
|
textures.push_back(mResourceSystem->getTextureManager()->getTexture2D(texname.str(), osg::Texture::REPEAT, osg::Texture::REPEAT));
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::ref_ptr<NifOsg::FlipController> controller (new NifOsg::FlipController(0, 2/32.f, textures));
|
float fps = mFallback->getFallbackFloat("Water_SurfaceFPS");
|
||||||
|
|
||||||
|
osg::ref_ptr<NifOsg::FlipController> controller (new NifOsg::FlipController(0, 1.f/fps, textures));
|
||||||
controller->setSource(boost::shared_ptr<SceneUtil::ControllerSource>(new SceneUtil::FrameTimeSource));
|
controller->setSource(boost::shared_ptr<SceneUtil::ControllerSource>(new SceneUtil::FrameTimeSource));
|
||||||
node->setUpdateCallback(controller);
|
node->setUpdateCallback(controller);
|
||||||
node->setStateSet(stateset);
|
node->setStateSet(stateset);
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
#ifndef OPENMW_MWRENDER_WATER_H
|
#ifndef OPENMW_MWRENDER_WATER_H
|
||||||
#define OPENMW_MWRENDER_WATER_H
|
#define OPENMW_MWRENDER_WATER_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include <osg/ref_ptr>
|
#include <osg/ref_ptr>
|
||||||
|
#include <osg/Vec3f>
|
||||||
|
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
#include "../mwworld/cellstore.hpp"
|
|
||||||
|
|
||||||
namespace osg
|
namespace osg
|
||||||
{
|
{
|
||||||
class Group;
|
class Group;
|
||||||
@ -28,6 +29,8 @@ namespace Resource
|
|||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
class Fallback;
|
class Fallback;
|
||||||
|
class CellStore;
|
||||||
|
class Ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
@ -47,6 +50,7 @@ namespace MWRender
|
|||||||
osg::ref_ptr<osg::PositionAttitudeTransform> mWaterNode;
|
osg::ref_ptr<osg::PositionAttitudeTransform> mWaterNode;
|
||||||
osg::ref_ptr<osg::Geode> mWaterGeode;
|
osg::ref_ptr<osg::Geode> mWaterGeode;
|
||||||
Resource::ResourceSystem* mResourceSystem;
|
Resource::ResourceSystem* mResourceSystem;
|
||||||
|
const MWWorld::Fallback* mFallback;
|
||||||
osg::ref_ptr<osgUtil::IncrementalCompileOperation> mIncrementalCompileOperation;
|
osg::ref_ptr<osgUtil::IncrementalCompileOperation> mIncrementalCompileOperation;
|
||||||
|
|
||||||
std::auto_ptr<RippleSimulation> mSimulation;
|
std::auto_ptr<RippleSimulation> mSimulation;
|
||||||
@ -63,7 +67,7 @@ namespace MWRender
|
|||||||
osg::Vec3f getSceneNodeCoordinates(int gridX, int gridY);
|
osg::Vec3f getSceneNodeCoordinates(int gridX, int gridY);
|
||||||
void updateVisible();
|
void updateVisible();
|
||||||
|
|
||||||
void createSimpleWaterStateSet(osg::Node* node);
|
void createSimpleWaterStateSet(osg::Node* node, float alpha);
|
||||||
|
|
||||||
/// @param reflection the reflection camera (required)
|
/// @param reflection the reflection camera (required)
|
||||||
/// @param refraction the refraction camera (optional)
|
/// @param refraction the refraction camera (optional)
|
||||||
|
@ -37,7 +37,7 @@ namespace
|
|||||||
|
|
||||||
void addToLevList(ESM::LevelledListBase* list, const std::string& itemId, int level)
|
void addToLevList(ESM::LevelledListBase* list, const std::string& itemId, int level)
|
||||||
{
|
{
|
||||||
for (std::vector<ESM::LevelledListBase::LevelItem>::iterator it = list->mList.begin(); it != list->mList.end();)
|
for (std::vector<ESM::LevelledListBase::LevelItem>::iterator it = list->mList.begin(); it != list->mList.end(); ++it)
|
||||||
{
|
{
|
||||||
if (it->mLevel == level && itemId == it->mId)
|
if (it->mLevel == level && itemId == it->mId)
|
||||||
return;
|
return;
|
||||||
|
@ -68,12 +68,7 @@ namespace MWWorld
|
|||||||
const ESM::EffectList &effects, const Ptr &caster, const std::string &sourceName,
|
const ESM::EffectList &effects, const Ptr &caster, const std::string &sourceName,
|
||||||
const osg::Vec3f& fallbackDirection)
|
const osg::Vec3f& fallbackDirection)
|
||||||
{
|
{
|
||||||
float height = 0;
|
osg::Vec3f pos = mPhysics->getPosition(caster) + osg::Vec3f(0,0,mPhysics->getHalfExtents(caster).z() * 0.5); // Spawn at 0.75 * ActorHeight
|
||||||
|
|
||||||
height += mPhysics->getHalfExtents(caster).z() * 2.f * 0.75f; // Spawn at 0.75 * ActorHeight
|
|
||||||
|
|
||||||
osg::Vec3f pos(caster.getRefData().getPosition().asVec3());
|
|
||||||
pos.z() += height;
|
|
||||||
|
|
||||||
if (MWBase::Environment::get().getWorld()->isUnderwater(caster.getCell(), pos)) // Underwater casting not possible
|
if (MWBase::Environment::get().getWorld()->isUnderwater(caster.getCell(), pos)) // Underwater casting not possible
|
||||||
return;
|
return;
|
||||||
|
@ -781,6 +781,9 @@ namespace MWWorld
|
|||||||
|
|
||||||
if (reference.getRefData().isEnabled())
|
if (reference.getRefData().isEnabled())
|
||||||
{
|
{
|
||||||
|
if (reference == getPlayerPtr())
|
||||||
|
throw std::runtime_error("can not disable player object");
|
||||||
|
|
||||||
reference.getRefData().disable();
|
reference.getRefData().disable();
|
||||||
|
|
||||||
if(mWorldScene->getActiveCells().find (reference.getCell())!=mWorldScene->getActiveCells().end() && reference.getRefData().getCount())
|
if(mWorldScene->getActiveCells().find (reference.getCell())!=mWorldScene->getActiveCells().end() && reference.getRefData().getCount())
|
||||||
@ -3256,8 +3259,7 @@ namespace MWWorld
|
|||||||
osg::Vec3f World::aimToTarget(const Ptr &actor, const MWWorld::Ptr& target)
|
osg::Vec3f World::aimToTarget(const Ptr &actor, const MWWorld::Ptr& target)
|
||||||
{
|
{
|
||||||
osg::Vec3f weaponPos = getActorHeadPosition(actor, mRendering);
|
osg::Vec3f weaponPos = getActorHeadPosition(actor, mRendering);
|
||||||
osg::Vec3f targetPos = target.getRefData().getPosition().asVec3();
|
osg::Vec3f targetPos = mPhysics->getPosition(target);
|
||||||
targetPos.z() += mPhysics->getHalfExtents(target).z();
|
|
||||||
return (targetPos - weaponPos);
|
return (targetPos - weaponPos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -280,37 +280,40 @@ namespace SceneUtil
|
|||||||
// - cull list of lights by the camera frustum
|
// - cull list of lights by the camera frustum
|
||||||
// - organize lights in a quad tree
|
// - organize lights in a quad tree
|
||||||
|
|
||||||
// Don't use Camera::getViewMatrix, that one might be relative to another camera!
|
|
||||||
const osg::RefMatrix* viewMatrix = cv->getCurrentRenderStage()->getInitialViewMatrix();
|
|
||||||
|
|
||||||
const std::vector<LightManager::LightSourceViewBound>& lights = mLightManager->getLightsInViewSpace(cv->getCurrentCamera(), viewMatrix);
|
// update light list if necessary
|
||||||
|
// makes sure we don't update it more than once per frame when rendering with multiple cameras
|
||||||
if (lights.size())
|
if (mLastFrameNumber != nv->getFrameStamp()->getFrameNumber())
|
||||||
{
|
{
|
||||||
|
mLastFrameNumber = nv->getFrameStamp()->getFrameNumber();
|
||||||
|
|
||||||
|
// Don't use Camera::getViewMatrix, that one might be relative to another camera!
|
||||||
|
const osg::RefMatrix* viewMatrix = cv->getCurrentRenderStage()->getInitialViewMatrix();
|
||||||
|
const std::vector<LightManager::LightSourceViewBound>& lights = mLightManager->getLightsInViewSpace(cv->getCurrentCamera(), viewMatrix);
|
||||||
|
|
||||||
// we do the intersections in view space
|
// we do the intersections in view space
|
||||||
osg::BoundingSphere nodeBound = node->getBound();
|
osg::BoundingSphere nodeBound = node->getBound();
|
||||||
osg::Matrixf mat = *cv->getModelViewMatrix();
|
osg::Matrixf mat = *cv->getModelViewMatrix();
|
||||||
transformBoundingSphere(mat, nodeBound);
|
transformBoundingSphere(mat, nodeBound);
|
||||||
|
|
||||||
LightManager::LightList lightList;
|
mLightList.clear();
|
||||||
for (unsigned int i=0; i<lights.size(); ++i)
|
for (unsigned int i=0; i<lights.size(); ++i)
|
||||||
{
|
{
|
||||||
const LightManager::LightSourceViewBound& l = lights[i];
|
const LightManager::LightSourceViewBound& l = lights[i];
|
||||||
if (l.mViewBound.intersects(nodeBound))
|
if (l.mViewBound.intersects(nodeBound))
|
||||||
lightList.push_back(&l);
|
mLightList.push_back(&l);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (lightList.empty())
|
if (mLightList.size())
|
||||||
{
|
{
|
||||||
traverse(node, nv);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int maxLights = static_cast<unsigned int> (8 - mLightManager->getStartLight());
|
unsigned int maxLights = static_cast<unsigned int> (8 - mLightManager->getStartLight());
|
||||||
|
|
||||||
if (lightList.size() > maxLights)
|
osg::StateSet* stateset = NULL;
|
||||||
|
|
||||||
|
if (mLightList.size() > maxLights)
|
||||||
{
|
{
|
||||||
// remove lights culled by this camera
|
// remove lights culled by this camera
|
||||||
|
LightManager::LightList lightList = mLightList;
|
||||||
for (LightManager::LightList::iterator it = lightList.begin(); it != lightList.end() && lightList.size() > maxLights; )
|
for (LightManager::LightList::iterator it = lightList.begin(); it != lightList.end() && lightList.size() > maxLights; )
|
||||||
{
|
{
|
||||||
osg::CullStack::CullingStack& stack = cv->getModelViewCullingStack();
|
osg::CullStack::CullingStack& stack = cv->getModelViewCullingStack();
|
||||||
@ -334,9 +337,11 @@ namespace SceneUtil
|
|||||||
while (lightList.size() > maxLights)
|
while (lightList.size() > maxLights)
|
||||||
lightList.pop_back();
|
lightList.pop_back();
|
||||||
}
|
}
|
||||||
|
stateset = mLightManager->getLightListStateSet(lightList);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
stateset = mLightManager->getLightListStateSet(mLightList);
|
||||||
|
|
||||||
osg::StateSet* stateset = mLightManager->getLightListStateSet(lightList);
|
|
||||||
|
|
||||||
cv->pushStateSet(stateset);
|
cv->pushStateSet(stateset);
|
||||||
|
|
||||||
|
@ -113,14 +113,18 @@ namespace SceneUtil
|
|||||||
int mStartLight;
|
int mStartLight;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// @note Not thread safe for CullThreadPerCamera threading mode.
|
||||||
class LightListCallback : public osg::NodeCallback
|
class LightListCallback : public osg::NodeCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LightListCallback()
|
LightListCallback()
|
||||||
: mLightManager(NULL)
|
: mLightManager(NULL)
|
||||||
|
, mLastFrameNumber(0)
|
||||||
{}
|
{}
|
||||||
LightListCallback(const LightListCallback& copy, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY)
|
LightListCallback(const LightListCallback& copy, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY)
|
||||||
: osg::Object(copy, copyop), osg::NodeCallback(copy, copyop), mLightManager(copy.mLightManager)
|
: osg::Object(copy, copyop), osg::NodeCallback(copy, copyop)
|
||||||
|
, mLightManager(copy.mLightManager)
|
||||||
|
, mLastFrameNumber(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
META_Object(NifOsg, LightListCallback)
|
META_Object(NifOsg, LightListCallback)
|
||||||
@ -129,6 +133,8 @@ namespace SceneUtil
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
LightManager* mLightManager;
|
LightManager* mLightManager;
|
||||||
|
unsigned int mLastFrameNumber;
|
||||||
|
LightManager::LightList mLightList;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief Configures a light's attenuation according to vanilla Morrowind attenuation settings.
|
/// @brief Configures a light's attenuation according to vanilla Morrowind attenuation settings.
|
||||||
|
@ -15,6 +15,7 @@ namespace SceneUtil
|
|||||||
/// the first StateSet is the one we can write to, the second is the one currently in use by the draw traversal of the last frame.
|
/// the first StateSet is the one we can write to, the second is the one currently in use by the draw traversal of the last frame.
|
||||||
/// After a frame is completed the places are swapped.
|
/// After a frame is completed the places are swapped.
|
||||||
/// @par Must be set as UpdateCallback on a Node.
|
/// @par Must be set as UpdateCallback on a Node.
|
||||||
|
/// @note Do not add the same StateSetUpdater to multiple nodes.
|
||||||
/// @note Do not add multiple StateSetControllers on the same Node as they will conflict - instead use the CompositeStateSetUpdater.
|
/// @note Do not add multiple StateSetControllers on the same Node as they will conflict - instead use the CompositeStateSetUpdater.
|
||||||
class StateSetUpdater : public osg::NodeCallback
|
class StateSetUpdater : public osg::NodeCallback
|
||||||
{
|
{
|
||||||
|
32
components/sceneutil/visitor.cpp
Normal file
32
components/sceneutil/visitor.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#include "visitor.hpp"
|
||||||
|
|
||||||
|
#include <osg/Geode>
|
||||||
|
|
||||||
|
#include <osgParticle/ParticleSystem>
|
||||||
|
|
||||||
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
|
namespace SceneUtil
|
||||||
|
{
|
||||||
|
|
||||||
|
void FindByNameVisitor::apply(osg::Group &group)
|
||||||
|
{
|
||||||
|
if (Misc::StringUtils::ciEqual(group.getName(), mNameToFind))
|
||||||
|
{
|
||||||
|
mFoundNode = &group;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
traverse(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisableFreezeOnCullVisitor::apply(osg::Geode &geode)
|
||||||
|
{
|
||||||
|
for (unsigned int i=0; i<geode.getNumDrawables(); ++i)
|
||||||
|
{
|
||||||
|
osg::Drawable* drw = geode.getDrawable(i);
|
||||||
|
if (osgParticle::ParticleSystem* partsys = dynamic_cast<osgParticle::ParticleSystem*>(drw))
|
||||||
|
partsys->setFreezeOnCull(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -3,12 +3,12 @@
|
|||||||
|
|
||||||
#include <osg/NodeVisitor>
|
#include <osg/NodeVisitor>
|
||||||
|
|
||||||
#include <components/misc/stringops.hpp>
|
|
||||||
|
|
||||||
// Commonly used scene graph visitors
|
// Commonly used scene graph visitors
|
||||||
namespace SceneUtil
|
namespace SceneUtil
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Find a Group by name, case-insensitive
|
||||||
|
// If not found, mFoundNode will be NULL
|
||||||
class FindByNameVisitor : public osg::NodeVisitor
|
class FindByNameVisitor : public osg::NodeVisitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -19,20 +19,24 @@ namespace SceneUtil
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void apply(osg::Group& group)
|
virtual void apply(osg::Group& group);
|
||||||
{
|
|
||||||
if (Misc::StringUtils::ciEqual(group.getName(), mNameToFind))
|
|
||||||
{
|
|
||||||
mFoundNode = &group;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
traverse(group);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string mNameToFind;
|
std::string mNameToFind;
|
||||||
osg::Group* mFoundNode;
|
osg::Group* mFoundNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Disable freezeOnCull for all visited particlesystems
|
||||||
|
class DisableFreezeOnCullVisitor : public osg::NodeVisitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DisableFreezeOnCullVisitor()
|
||||||
|
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void apply(osg::Geode &geode);
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user