forked from teamnwah/openmw-tes3coop
Merge remote-tracking branch 'scrawl/master' into openmw-37
This commit is contained in:
commit
77b325a1db
33 changed files with 397 additions and 220 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -5,7 +5,7 @@ CMakeCache.txt
|
||||||
cmake_install.cmake
|
cmake_install.cmake
|
||||||
Makefile
|
Makefile
|
||||||
makefile
|
makefile
|
||||||
build
|
build*
|
||||||
prebuilt
|
prebuilt
|
||||||
|
|
||||||
## doxygen
|
## doxygen
|
||||||
|
|
|
@ -1479,6 +1479,8 @@ bool CharacterController::updateWeaponState()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mAnimation->setAccurateAiming(mUpperBodyState > UpperCharState_WeapEquiped);
|
||||||
|
|
||||||
return forcestateupdate;
|
return forcestateupdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,8 @@
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
// NOTE: determined empirically but probably need further tweaking
|
// NOTE: determined empirically but probably need further tweaking
|
||||||
static const float DIST_SAME_SPOT = 1.8f;
|
static const float DIST_SAME_SPOT = 0.5f;
|
||||||
static const float DURATION_SAME_SPOT = 1.0f;
|
static const float DURATION_SAME_SPOT = 1.5f;
|
||||||
static const float DURATION_TO_EVADE = 0.4f;
|
static const float DURATION_TO_EVADE = 0.4f;
|
||||||
|
|
||||||
const float ObstacleCheck::evadeDirections[NUM_EVADE_DIRECTIONS][2] =
|
const float ObstacleCheck::evadeDirections[NUM_EVADE_DIRECTIONS][2] =
|
||||||
|
@ -114,20 +114,23 @@ namespace MWMechanics
|
||||||
* t = how long before considered stuck
|
* t = how long before considered stuck
|
||||||
* u = how long to move sideways
|
* u = how long to move sideways
|
||||||
*
|
*
|
||||||
* DIST_SAME_SPOT is calibrated for movement speed of around 150.
|
|
||||||
* A rat has walking speed of around 30, so we need to adjust for
|
|
||||||
* that.
|
|
||||||
*/
|
*/
|
||||||
bool ObstacleCheck::check(const MWWorld::Ptr& actor, float duration)
|
bool ObstacleCheck::check(const MWWorld::Ptr& actor, float duration)
|
||||||
{
|
{
|
||||||
const MWWorld::Class& cls = actor.getClass();
|
const MWWorld::Class& cls = actor.getClass();
|
||||||
ESM::Position pos = actor.getRefData().getPosition();
|
ESM::Position pos = actor.getRefData().getPosition();
|
||||||
|
|
||||||
if(mDistSameSpot == -1)
|
// actors can move at most 60 fps (the physics framerate).
|
||||||
mDistSameSpot = DIST_SAME_SPOT * (cls.getSpeed(actor) / 150);
|
// the max() can be removed if we implement physics interpolation.
|
||||||
|
float movementDuration = std::max(1/60.f, duration);
|
||||||
|
|
||||||
|
if(mDistSameSpot == -1)
|
||||||
|
mDistSameSpot = DIST_SAME_SPOT * cls.getSpeed(actor);
|
||||||
|
|
||||||
|
float distSameSpot = mDistSameSpot * movementDuration;
|
||||||
|
|
||||||
|
bool samePosition = (osg::Vec2f(pos.pos[0], pos.pos[1]) - osg::Vec2f(mPrevX, mPrevY)).length2() < distSameSpot * distSameSpot;
|
||||||
|
|
||||||
bool samePosition = (std::abs(pos.pos[0] - mPrevX) < mDistSameSpot) &&
|
|
||||||
(std::abs(pos.pos[1] - mPrevY) < mDistSameSpot);
|
|
||||||
// update position
|
// update position
|
||||||
mPrevX = pos.pos[0];
|
mPrevX = pos.pos[0];
|
||||||
mPrevY = pos.pos[1];
|
mPrevY = pos.pos[1];
|
||||||
|
@ -160,13 +163,13 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
mStuckDuration = 0;
|
mStuckDuration = 0;
|
||||||
mWalkState = State_Evade;
|
mWalkState = State_Evade;
|
||||||
|
chooseEvasionDirection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* FALL THROUGH */
|
/* FALL THROUGH */
|
||||||
case State_Evade:
|
case State_Evade:
|
||||||
{
|
{
|
||||||
chooseEvasionDirection(samePosition);
|
|
||||||
mEvadeDuration += duration;
|
mEvadeDuration += duration;
|
||||||
if(mEvadeDuration < DURATION_TO_EVADE)
|
if(mEvadeDuration < DURATION_TO_EVADE)
|
||||||
return true;
|
return true;
|
||||||
|
@ -188,17 +191,14 @@ namespace MWMechanics
|
||||||
actorMovement.mPosition[1] = evadeDirections[mEvadeDirectionIndex][1];
|
actorMovement.mPosition[1] = evadeDirections[mEvadeDirectionIndex][1];
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObstacleCheck::chooseEvasionDirection(bool samePosition)
|
void ObstacleCheck::chooseEvasionDirection()
|
||||||
{
|
{
|
||||||
// change direction if attempt didn't work
|
// change direction if attempt didn't work
|
||||||
if (samePosition && (0 < mEvadeDuration))
|
|
||||||
{
|
|
||||||
++mEvadeDirectionIndex;
|
++mEvadeDirectionIndex;
|
||||||
if (mEvadeDirectionIndex == NUM_EVADE_DIRECTIONS)
|
if (mEvadeDirectionIndex == NUM_EVADE_DIRECTIONS)
|
||||||
{
|
{
|
||||||
mEvadeDirectionIndex = 0;
|
mEvadeDirectionIndex = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ namespace MWMechanics
|
||||||
float mDistSameSpot; // take account of actor's speed
|
float mDistSameSpot; // take account of actor's speed
|
||||||
int mEvadeDirectionIndex;
|
int mEvadeDirectionIndex;
|
||||||
|
|
||||||
void chooseEvasionDirection(bool samePosition);
|
void chooseEvasionDirection();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <osg/Geode>
|
#include <osg/Geode>
|
||||||
#include <osg/BlendFunc>
|
#include <osg/BlendFunc>
|
||||||
#include <osg/Material>
|
#include <osg/Material>
|
||||||
|
#include <osg/Version>
|
||||||
|
|
||||||
#include <osgParticle/ParticleSystem>
|
#include <osgParticle/ParticleSystem>
|
||||||
|
|
||||||
|
@ -174,72 +175,93 @@ namespace
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Base class for visitors that remove nodes from a scene graph.
|
||||||
// Removes all drawables from a graph.
|
/// Subclasses need to fill the mToRemove vector.
|
||||||
class RemoveDrawableVisitor : public osg::NodeVisitor
|
/// To use, node->accept(removeVisitor); removeVisitor.remove();
|
||||||
|
class RemoveVisitor : public osg::NodeVisitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RemoveDrawableVisitor()
|
RemoveVisitor()
|
||||||
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void apply(osg::Geode &node)
|
|
||||||
{
|
|
||||||
// Not safe to remove in apply(), since the visitor is still iterating the child list
|
|
||||||
osg::Group* parent = node.getParent(0);
|
|
||||||
// prune nodes that would be empty after the removal
|
|
||||||
if (parent->getNumChildren() == 1 && parent->getDataVariance() == osg::Object::STATIC)
|
|
||||||
mToRemove.push_back(parent);
|
|
||||||
else
|
|
||||||
mToRemove.push_back(&node);
|
|
||||||
traverse(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
void remove()
|
void remove()
|
||||||
{
|
{
|
||||||
for (std::vector<osg::Node*>::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it)
|
for (RemoveVec::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it)
|
||||||
{
|
it->second->removeChild(it->first);
|
||||||
osg::Node* node = *it;
|
|
||||||
if (node->getNumParents())
|
|
||||||
node->getParent(0)->removeChild(node);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
std::vector<osg::Node*> mToRemove;
|
// <node to remove, parent node to remove it from>
|
||||||
|
typedef std::vector<std::pair<osg::Node*, osg::Group*> > RemoveVec;
|
||||||
|
std::vector<std::pair<osg::Node*, osg::Group*> > mToRemove;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RemoveTriBipVisitor : public osg::NodeVisitor
|
// Removes all drawables from a graph.
|
||||||
|
class RemoveDrawableVisitor : public RemoveVisitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RemoveTriBipVisitor()
|
virtual void apply(osg::Geode &geode)
|
||||||
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
|
||||||
{
|
{
|
||||||
|
applyImpl(geode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3)
|
||||||
|
virtual void apply(osg::Drawable& drw)
|
||||||
|
{
|
||||||
|
applyImpl(drw);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void applyImpl(osg::Node& node)
|
||||||
|
{
|
||||||
|
osg::NodePath::iterator parent = getNodePath().end()-2;
|
||||||
|
// We know that the parent is a Group because only Groups can have children.
|
||||||
|
osg::Group* parentGroup = static_cast<osg::Group*>(*parent);
|
||||||
|
|
||||||
|
// Try to prune nodes that would be empty after the removal
|
||||||
|
if (parent != getNodePath().begin())
|
||||||
|
{
|
||||||
|
// This could be extended to remove the parent's parent, and so on if they are empty as well.
|
||||||
|
// But for NIF files, there won't be a benefit since only TriShapes can be set to STATIC dataVariance.
|
||||||
|
osg::Group* parentParent = static_cast<osg::Group*>(*(parent - 1));
|
||||||
|
if (parentGroup->getNumChildren() == 1 && parentGroup->getDataVariance() == osg::Object::STATIC)
|
||||||
|
{
|
||||||
|
mToRemove.push_back(std::make_pair(parentGroup, parentParent));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mToRemove.push_back(std::make_pair(&node, parentGroup));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class RemoveTriBipVisitor : public RemoveVisitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
virtual void apply(osg::Geode &node)
|
virtual void apply(osg::Geode &node)
|
||||||
|
{
|
||||||
|
applyImpl(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3)
|
||||||
|
virtual void apply(osg::Drawable& drw)
|
||||||
|
{
|
||||||
|
applyImpl(drw);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void applyImpl(osg::Node& node)
|
||||||
{
|
{
|
||||||
const std::string toFind = "tri bip";
|
const std::string toFind = "tri bip";
|
||||||
if (Misc::StringUtils::ciCompareLen(node.getName(), toFind, toFind.size()) == 0)
|
if (Misc::StringUtils::ciCompareLen(node.getName(), toFind, toFind.size()) == 0)
|
||||||
{
|
{
|
||||||
|
osg::Group* parent = static_cast<osg::Group*>(*(getNodePath().end()-2));
|
||||||
// Not safe to remove in apply(), since the visitor is still iterating the child list
|
// Not safe to remove in apply(), since the visitor is still iterating the child list
|
||||||
mToRemove.push_back(&node);
|
mToRemove.push_back(std::make_pair(&node, parent));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove()
|
|
||||||
{
|
|
||||||
for (std::vector<osg::Node*>::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it)
|
|
||||||
{
|
|
||||||
osg::Node* node = *it;
|
|
||||||
if (node->getNumParents())
|
|
||||||
node->getParent(0)->removeChild(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<osg::Node*> mToRemove;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1066,6 +1088,7 @@ namespace MWRender
|
||||||
osg::ref_ptr<SceneUtil::LightSource> lightSource = new SceneUtil::LightSource;
|
osg::ref_ptr<SceneUtil::LightSource> lightSource = new SceneUtil::LightSource;
|
||||||
osg::Light* light = new osg::Light;
|
osg::Light* light = new osg::Light;
|
||||||
lightSource->setLight(light);
|
lightSource->setLight(light);
|
||||||
|
lightSource->setNodeMask(Mask_Lighting);
|
||||||
|
|
||||||
const MWWorld::Fallback* fallback = MWBase::Environment::get().getWorld()->getFallback();
|
const MWWorld::Fallback* fallback = MWBase::Environment::get().getWorld()->getFallback();
|
||||||
|
|
||||||
|
@ -1294,6 +1317,7 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
mGlowLight = new SceneUtil::LightSource;
|
mGlowLight = new SceneUtil::LightSource;
|
||||||
mGlowLight->setLight(new osg::Light);
|
mGlowLight->setLight(new osg::Light);
|
||||||
|
mGlowLight->setNodeMask(Mask_Lighting);
|
||||||
osg::Light* light = mGlowLight->getLight();
|
osg::Light* light = mGlowLight->getLight();
|
||||||
light->setDiffuse(osg::Vec4f(0,0,0,0));
|
light->setDiffuse(osg::Vec4f(0,0,0,0));
|
||||||
light->setSpecular(osg::Vec4f(0,0,0,0));
|
light->setSpecular(osg::Vec4f(0,0,0,0));
|
||||||
|
|
|
@ -61,6 +61,9 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
osg::ref_ptr<osg::Node> mNode;
|
osg::ref_ptr<osg::Node> mNode;
|
||||||
|
|
||||||
|
void operator= (const PartHolder&);
|
||||||
|
PartHolder(const PartHolder&);
|
||||||
};
|
};
|
||||||
typedef boost::shared_ptr<PartHolder> PartHolderPtr;
|
typedef boost::shared_ptr<PartHolder> PartHolderPtr;
|
||||||
|
|
||||||
|
@ -439,6 +442,7 @@ public:
|
||||||
virtual void setHeadYaw(float yawRadians);
|
virtual void setHeadYaw(float yawRadians);
|
||||||
virtual float getHeadPitch() const;
|
virtual float getHeadPitch() const;
|
||||||
virtual float getHeadYaw() const;
|
virtual float getHeadYaw() const;
|
||||||
|
virtual void setAccurateAiming(bool enabled) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Animation(const Animation&);
|
Animation(const Animation&);
|
||||||
|
|
|
@ -42,7 +42,8 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
|
|
||||||
Camera::Camera (osg::Camera* camera)
|
Camera::Camera (osg::Camera* camera)
|
||||||
: mCamera(camera),
|
: mHeightScale(1.f),
|
||||||
|
mCamera(camera),
|
||||||
mAnimation(NULL),
|
mAnimation(NULL),
|
||||||
mFirstPersonView(true),
|
mFirstPersonView(true),
|
||||||
mPreviewMode(false),
|
mPreviewMode(false),
|
||||||
|
@ -93,7 +94,7 @@ namespace MWRender
|
||||||
|
|
||||||
osg::Vec3d position = worldMat.getTrans();
|
osg::Vec3d position = worldMat.getTrans();
|
||||||
if (!isFirstPerson())
|
if (!isFirstPerson())
|
||||||
position.z() += mHeight;
|
position.z() += mHeight * mHeightScale;
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,11 +373,17 @@ namespace MWRender
|
||||||
mTrackingNode = mAnimation->getNode("Camera");
|
mTrackingNode = mAnimation->getNode("Camera");
|
||||||
if (!mTrackingNode)
|
if (!mTrackingNode)
|
||||||
mTrackingNode = mAnimation->getNode("Head");
|
mTrackingNode = mAnimation->getNode("Head");
|
||||||
|
mHeightScale = 1.f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mAnimation->setViewMode(NpcAnimation::VM_Normal);
|
mAnimation->setViewMode(NpcAnimation::VM_Normal);
|
||||||
mTrackingNode = mTrackingPtr.getRefData().getBaseNode();
|
osg::PositionAttitudeTransform* transform = mTrackingPtr.getRefData().getBaseNode();
|
||||||
|
mTrackingNode = transform;
|
||||||
|
if (transform)
|
||||||
|
mHeightScale = transform->getScale().z();
|
||||||
|
else
|
||||||
|
mHeightScale = 1.f;
|
||||||
}
|
}
|
||||||
rotateCamera(getPitch(), getYaw(), false);
|
rotateCamera(getPitch(), getYaw(), false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ namespace MWRender
|
||||||
|
|
||||||
MWWorld::Ptr mTrackingPtr;
|
MWWorld::Ptr mTrackingPtr;
|
||||||
osg::ref_ptr<const osg::Node> mTrackingNode;
|
osg::ref_ptr<const osg::Node> mTrackingNode;
|
||||||
|
float mHeightScale;
|
||||||
|
|
||||||
osg::ref_ptr<osg::Camera> mCamera;
|
osg::ref_ptr<osg::Camera> mCamera;
|
||||||
|
|
||||||
|
|
|
@ -157,11 +157,10 @@ namespace MWRender
|
||||||
|
|
||||||
void CharacterPreview::rebuild()
|
void CharacterPreview::rebuild()
|
||||||
{
|
{
|
||||||
delete mAnimation;
|
mAnimation.reset(NULL);
|
||||||
mAnimation = NULL;
|
|
||||||
|
|
||||||
mAnimation = new NpcAnimation(mCharacter, mNode, mResourceSystem, true, true,
|
mAnimation.reset(new NpcAnimation(mCharacter, mNode, mResourceSystem, true, true,
|
||||||
(renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal));
|
(renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal)));
|
||||||
|
|
||||||
onSetup();
|
onSetup();
|
||||||
|
|
||||||
|
@ -194,7 +193,7 @@ namespace MWRender
|
||||||
|
|
||||||
void InventoryPreview::update()
|
void InventoryPreview::update()
|
||||||
{
|
{
|
||||||
if (!mAnimation)
|
if (!mAnimation.get())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mAnimation->showWeapons(true);
|
mAnimation->showWeapons(true);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define MWRENDER_CHARACTERPREVIEW_H
|
#define MWRENDER_CHARACTERPREVIEW_H
|
||||||
|
|
||||||
#include <osg/ref_ptr>
|
#include <osg/ref_ptr>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include <components/esm/loadnpc.hpp>
|
#include <components/esm/loadnpc.hpp>
|
||||||
|
|
||||||
|
@ -61,7 +62,7 @@ namespace MWRender
|
||||||
|
|
||||||
MWWorld::Ptr mCharacter;
|
MWWorld::Ptr mCharacter;
|
||||||
|
|
||||||
MWRender::NpcAnimation* mAnimation;
|
std::auto_ptr<MWRender::NpcAnimation> mAnimation;
|
||||||
osg::ref_ptr<osg::PositionAttitudeTransform> mNode;
|
osg::ref_ptr<osg::PositionAttitudeTransform> mNode;
|
||||||
std::string mCurrentAnimGroup;
|
std::string mCurrentAnimGroup;
|
||||||
|
|
||||||
|
|
|
@ -62,9 +62,8 @@ namespace
|
||||||
class CameraUpdateGlobalCallback : public osg::NodeCallback
|
class CameraUpdateGlobalCallback : public osg::NodeCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CameraUpdateGlobalCallback(osg::Camera* cam, MWRender::GlobalMap* parent)
|
CameraUpdateGlobalCallback(MWRender::GlobalMap* parent)
|
||||||
: mRendered(false)
|
: mRendered(false)
|
||||||
, mCamera(cam)
|
|
||||||
, mParent(parent)
|
, mParent(parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -73,7 +72,7 @@ namespace
|
||||||
{
|
{
|
||||||
if (mRendered)
|
if (mRendered)
|
||||||
{
|
{
|
||||||
mCamera->setNodeMask(0);
|
node->setNodeMask(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,13 +81,12 @@ namespace
|
||||||
if (!mRendered)
|
if (!mRendered)
|
||||||
{
|
{
|
||||||
mRendered = true;
|
mRendered = true;
|
||||||
mParent->markForRemoval(mCamera);
|
mParent->markForRemoval(static_cast<osg::Camera*>(node));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mRendered;
|
bool mRendered;
|
||||||
osg::ref_ptr<osg::Camera> mCamera;
|
|
||||||
MWRender::GlobalMap* mParent;
|
MWRender::GlobalMap* mParent;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -263,11 +261,14 @@ namespace MWRender
|
||||||
else
|
else
|
||||||
camera->setClearMask(GL_NONE);
|
camera->setClearMask(GL_NONE);
|
||||||
|
|
||||||
camera->setUpdateCallback(new CameraUpdateGlobalCallback(camera, this));
|
camera->setUpdateCallback(new CameraUpdateGlobalCallback(this));
|
||||||
|
|
||||||
camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT, osg::Camera::PIXEL_BUFFER_RTT);
|
camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT, osg::Camera::PIXEL_BUFFER_RTT);
|
||||||
camera->attach(osg::Camera::COLOR_BUFFER, mOverlayTexture);
|
camera->attach(osg::Camera::COLOR_BUFFER, mOverlayTexture);
|
||||||
|
|
||||||
|
// no need for a depth buffer
|
||||||
|
camera->setImplicitBufferAttachmentMask(osg::DisplaySettings::IMPLICIT_COLOR_BUFFER_ATTACHMENT);
|
||||||
|
|
||||||
if (cpuCopy)
|
if (cpuCopy)
|
||||||
{
|
{
|
||||||
// Attach an image to copy the render back to the CPU when finished
|
// Attach an image to copy the render back to the CPU when finished
|
||||||
|
@ -288,10 +289,12 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Geometry> geom = createTexturedQuad(srcLeft, srcTop, srcRight, srcBottom);
|
osg::ref_ptr<osg::Geometry> geom = createTexturedQuad(srcLeft, srcTop, srcRight, srcBottom);
|
||||||
osg::ref_ptr<osg::Depth> depth = new osg::Depth;
|
osg::ref_ptr<osg::Depth> depth = new osg::Depth;
|
||||||
depth->setFunction(osg::Depth::ALWAYS);
|
depth->setWriteMask(0);
|
||||||
geom->getOrCreateStateSet()->setAttributeAndModes(depth, osg::StateAttribute::ON);
|
osg::StateSet* stateset = geom->getOrCreateStateSet();
|
||||||
geom->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
|
stateset->setAttribute(depth);
|
||||||
geom->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
|
||||||
|
stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||||
|
stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
|
||||||
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
|
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
|
||||||
geode->addDrawable(geom);
|
geode->addDrawable(geom);
|
||||||
camera->addChild(geode);
|
camera->addChild(geode);
|
||||||
|
|
|
@ -30,22 +30,21 @@ namespace
|
||||||
class CameraLocalUpdateCallback : public osg::NodeCallback
|
class CameraLocalUpdateCallback : public osg::NodeCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CameraLocalUpdateCallback(osg::Camera* cam, MWRender::LocalMap* parent)
|
CameraLocalUpdateCallback(MWRender::LocalMap* parent)
|
||||||
: mRendered(false)
|
: mRendered(false)
|
||||||
, mCamera(cam)
|
|
||||||
, mParent(parent)
|
, mParent(parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void operator()(osg::Node*, osg::NodeVisitor*)
|
virtual void operator()(osg::Node* node, osg::NodeVisitor*)
|
||||||
{
|
{
|
||||||
if (mRendered)
|
if (mRendered)
|
||||||
mCamera->setNodeMask(0);
|
node->setNodeMask(0);
|
||||||
|
|
||||||
if (!mRendered)
|
if (!mRendered)
|
||||||
{
|
{
|
||||||
mRendered = true;
|
mRendered = true;
|
||||||
mParent->markForRemoval(mCamera);
|
mParent->markForRemoval(static_cast<osg::Camera*>(node));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note, we intentionally do not traverse children here. The map camera's scene data is the same as the master camera's,
|
// Note, we intentionally do not traverse children here. The map camera's scene data is the same as the master camera's,
|
||||||
|
@ -55,7 +54,6 @@ namespace
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mRendered;
|
bool mRendered;
|
||||||
osg::ref_ptr<osg::Camera> mCamera;
|
|
||||||
MWRender::LocalMap* mParent;
|
MWRender::LocalMap* mParent;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -205,7 +203,7 @@ osg::ref_ptr<osg::Camera> LocalMap::createOrthographicCamera(float x, float y, f
|
||||||
camera->setStateSet(stateset);
|
camera->setStateSet(stateset);
|
||||||
camera->setGraphicsContext(mViewer->getCamera()->getGraphicsContext());
|
camera->setGraphicsContext(mViewer->getCamera()->getGraphicsContext());
|
||||||
camera->setViewport(0, 0, mMapResolution, mMapResolution);
|
camera->setViewport(0, 0, mMapResolution, mMapResolution);
|
||||||
camera->setUpdateCallback(new CameraLocalUpdateCallback(camera, this));
|
camera->setUpdateCallback(new CameraLocalUpdateCallback(this));
|
||||||
|
|
||||||
return camera;
|
return camera;
|
||||||
}
|
}
|
||||||
|
|
|
@ -281,7 +281,9 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, osg::ref_ptr<osg::Group> par
|
||||||
mShowWeapons(false),
|
mShowWeapons(false),
|
||||||
mShowCarriedLeft(true),
|
mShowCarriedLeft(true),
|
||||||
mNpcType(Type_Normal),
|
mNpcType(Type_Normal),
|
||||||
mSoundsDisabled(disableSounds)
|
mSoundsDisabled(disableSounds),
|
||||||
|
mAccurateAiming(false),
|
||||||
|
mAimingFactor(0.f)
|
||||||
{
|
{
|
||||||
mNpc = mPtr.get<ESM::NPC>()->mBase;
|
mNpc = mPtr.get<ESM::NPC>()->mBase;
|
||||||
|
|
||||||
|
@ -726,7 +728,14 @@ osg::Vec3f NpcAnimation::runAnimation(float timepassed)
|
||||||
|
|
||||||
if (mFirstPersonNeckController)
|
if (mFirstPersonNeckController)
|
||||||
{
|
{
|
||||||
mFirstPersonNeckController->setRotate(osg::Quat(mPtr.getRefData().getPosition().rot[0], osg::Vec3f(-1,0,0)));
|
if (mAccurateAiming)
|
||||||
|
mAimingFactor = 1.f;
|
||||||
|
else
|
||||||
|
mAimingFactor = std::max(0.f, mAimingFactor - timepassed * 0.5f);
|
||||||
|
|
||||||
|
float rotateFactor = 0.75f + 0.25f * mAimingFactor;
|
||||||
|
|
||||||
|
mFirstPersonNeckController->setRotate(osg::Quat(mPtr.getRefData().getPosition().rot[0] * rotateFactor, osg::Vec3f(-1,0,0)));
|
||||||
mFirstPersonNeckController->setOffset(mFirstPersonOffset);
|
mFirstPersonNeckController->setOffset(mFirstPersonOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1072,4 +1081,9 @@ void NpcAnimation::updatePtr(const MWWorld::Ptr &updated)
|
||||||
mHeadAnimationTime->updatePtr(updated);
|
mHeadAnimationTime->updatePtr(updated);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NpcAnimation::setAccurateAiming(bool enabled)
|
||||||
|
{
|
||||||
|
mAccurateAiming = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,9 @@ private:
|
||||||
|
|
||||||
bool mSoundsDisabled;
|
bool mSoundsDisabled;
|
||||||
|
|
||||||
|
bool mAccurateAiming;
|
||||||
|
float mAimingFactor;
|
||||||
|
|
||||||
void updateNpcBase();
|
void updateNpcBase();
|
||||||
|
|
||||||
PartHolderPtr insertBoundedPart(const std::string &model, const std::string &bonename,
|
PartHolderPtr insertBoundedPart(const std::string &model, const std::string &bonename,
|
||||||
|
@ -104,6 +107,10 @@ public:
|
||||||
|
|
||||||
virtual void enableHeadAnimation(bool enable);
|
virtual void enableHeadAnimation(bool enable);
|
||||||
|
|
||||||
|
/// 1: the first person meshes follow the camera's rotation completely
|
||||||
|
/// 0: the first person meshes follow the camera with a reduced factor, so you can look down at your own hands
|
||||||
|
virtual void setAccurateAiming(bool enabled);
|
||||||
|
|
||||||
virtual void setWeaponGroup(const std::string& group);
|
virtual void setWeaponGroup(const std::string& group);
|
||||||
|
|
||||||
virtual osg::Vec3f runAnimation(float timepassed);
|
virtual osg::Vec3f runAnimation(float timepassed);
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <osg/Geode>
|
#include <osg/Geode>
|
||||||
#include <osg/PositionAttitudeTransform>
|
#include <osg/PositionAttitudeTransform>
|
||||||
#include <osg/UserDataContainer>
|
#include <osg/UserDataContainer>
|
||||||
|
#include <osg/Version>
|
||||||
|
|
||||||
#include <osgParticle/ParticleSystem>
|
#include <osgParticle/ParticleSystem>
|
||||||
#include <osgParticle/ParticleProcessor>
|
#include <osgParticle/ParticleProcessor>
|
||||||
|
@ -54,11 +55,19 @@ namespace
|
||||||
for (std::vector<osgParticle::ParticleSystem*>::iterator it = partsysVector.begin(); it != partsysVector.end(); ++it)
|
for (std::vector<osgParticle::ParticleSystem*>::iterator it = partsysVector.begin(); it != partsysVector.end(); ++it)
|
||||||
geode.removeDrawable(*it);
|
geode.removeDrawable(*it);
|
||||||
}
|
}
|
||||||
|
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3)
|
||||||
|
virtual void apply(osg::Drawable& drw)
|
||||||
|
{
|
||||||
|
if (osgParticle::ParticleSystem* partsys = dynamic_cast<osgParticle::ParticleSystem*>(&drw))
|
||||||
|
mToRemove.push_back(partsys);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void remove()
|
void remove()
|
||||||
{
|
{
|
||||||
for (std::vector<osg::ref_ptr<osg::Node> >::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it)
|
for (std::vector<osg::ref_ptr<osg::Node> >::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it)
|
||||||
{
|
{
|
||||||
|
// FIXME: a Drawable might have more than one parent
|
||||||
osg::Node* node = *it;
|
osg::Node* node = *it;
|
||||||
if (node->getNumParents())
|
if (node->getNumParents())
|
||||||
node->getParent(0)->removeChild(node);
|
node->getParent(0)->removeChild(node);
|
||||||
|
|
|
@ -137,7 +137,10 @@ namespace MWRender
|
||||||
, mUnderwaterIndoorFog(fallback->getFallbackFloat("Water_UnderwaterIndoorFog"))
|
, mUnderwaterIndoorFog(fallback->getFallbackFloat("Water_UnderwaterIndoorFog"))
|
||||||
, mNightEyeFactor(0.f)
|
, mNightEyeFactor(0.f)
|
||||||
{
|
{
|
||||||
|
resourceSystem->getSceneManager()->setParticleSystemMask(MWRender::Mask_ParticleSystem);
|
||||||
|
|
||||||
osg::ref_ptr<SceneUtil::LightManager> lightRoot = new SceneUtil::LightManager;
|
osg::ref_ptr<SceneUtil::LightManager> lightRoot = new SceneUtil::LightManager;
|
||||||
|
lightRoot->setLightingMask(Mask_Lighting);
|
||||||
mLightRoot = lightRoot;
|
mLightRoot = lightRoot;
|
||||||
lightRoot->setStartLight(1);
|
lightRoot->setStartLight(1);
|
||||||
|
|
||||||
|
@ -163,7 +166,7 @@ namespace MWRender
|
||||||
mViewer->setLightingMode(osgViewer::View::NO_LIGHT);
|
mViewer->setLightingMode(osgViewer::View::NO_LIGHT);
|
||||||
|
|
||||||
osg::ref_ptr<osg::LightSource> source = new osg::LightSource;
|
osg::ref_ptr<osg::LightSource> source = new osg::LightSource;
|
||||||
source->setNodeMask(SceneUtil::Mask_Lit);
|
source->setNodeMask(Mask_Lighting);
|
||||||
mSunLight = new osg::Light;
|
mSunLight = new osg::Light;
|
||||||
source->setLight(mSunLight);
|
source->setLight(mSunLight);
|
||||||
mSunLight->setDiffuse(osg::Vec4f(0,0,0,1));
|
mSunLight->setDiffuse(osg::Vec4f(0,0,0,1));
|
||||||
|
@ -439,6 +442,9 @@ namespace MWRender
|
||||||
void RenderingManager::scaleObject(const MWWorld::Ptr &ptr, const osg::Vec3f &scale)
|
void RenderingManager::scaleObject(const MWWorld::Ptr &ptr, const osg::Vec3f &scale)
|
||||||
{
|
{
|
||||||
ptr.getRefData().getBaseNode()->setScale(scale);
|
ptr.getRefData().getBaseNode()->setScale(scale);
|
||||||
|
|
||||||
|
if (ptr == mCamera->getTrackingPtr()) // update height of camera
|
||||||
|
mCamera->processViewChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingManager::removeObject(const MWWorld::Ptr &ptr)
|
void RenderingManager::removeObject(const MWWorld::Ptr &ptr)
|
||||||
|
|
|
@ -27,7 +27,7 @@ protected:
|
||||||
|
|
||||||
bool mEnabled;
|
bool mEnabled;
|
||||||
osg::Quat mRotate;
|
osg::Quat mRotate;
|
||||||
osg::ref_ptr<osg::Node> mRelativeTo;
|
osg::Node* mRelativeTo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -351,10 +351,14 @@ public:
|
||||||
for (unsigned int i=0; i<geode.getNumDrawables(); ++i)
|
for (unsigned int i=0; i<geode.getNumDrawables(); ++i)
|
||||||
{
|
{
|
||||||
osg::Drawable* drw = geode.getDrawable(i);
|
osg::Drawable* drw = geode.getDrawable(i);
|
||||||
|
apply(*drw);
|
||||||
osg::Geometry* geom = drw->asGeometry();
|
}
|
||||||
|
}
|
||||||
|
void apply(osg::Drawable& drw)
|
||||||
|
{
|
||||||
|
osg::Geometry* geom = drw.asGeometry();
|
||||||
if (!geom)
|
if (!geom)
|
||||||
continue;
|
return;
|
||||||
|
|
||||||
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array(geom->getVertexArray()->getNumElements());
|
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array(geom->getVertexArray()->getNumElements());
|
||||||
for (unsigned int i=0; i<colors->size(); ++i)
|
for (unsigned int i=0; i<colors->size(); ++i)
|
||||||
|
@ -378,7 +382,6 @@ public:
|
||||||
|
|
||||||
geom->setColorArray(colors, osg::Array::BIND_PER_VERTEX);
|
geom->setColorArray(colors, osg::Array::BIND_PER_VERTEX);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int mMeshType;
|
int mMeshType;
|
||||||
|
@ -1268,7 +1271,7 @@ public:
|
||||||
if (stateset->getAttribute(osg::StateAttribute::MATERIAL))
|
if (stateset->getAttribute(osg::StateAttribute::MATERIAL))
|
||||||
{
|
{
|
||||||
SceneUtil::CompositeStateSetUpdater* composite = NULL;
|
SceneUtil::CompositeStateSetUpdater* composite = NULL;
|
||||||
#if OSG_MIN_VERSION_REQUIRED(3,3,3)
|
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3)
|
||||||
osg::Callback* callback = node.getUpdateCallback();
|
osg::Callback* callback = node.getUpdateCallback();
|
||||||
#else
|
#else
|
||||||
osg::NodeCallback* callback = node.getUpdateCallback();
|
osg::NodeCallback* callback = node.getUpdateCallback();
|
||||||
|
|
|
@ -15,16 +15,16 @@ 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_Water = (1<<6),
|
Mask_Water = (1<<6), // choose Water or SimpleWater depending on detail required
|
||||||
Mask_Terrain = (1<<7),
|
Mask_SimpleWater = (1<<7),
|
||||||
Mask_FirstPerson = (1<<8),
|
Mask_Terrain = (1<<8),
|
||||||
|
Mask_FirstPerson = (1<<9),
|
||||||
|
|
||||||
// child of Sky
|
// child of Sky
|
||||||
Mask_Sun = (1<<9),
|
Mask_Sun = (1<<10),
|
||||||
Mask_WeatherParticles = (1<<10),
|
Mask_WeatherParticles = (1<<11),
|
||||||
|
|
||||||
// child of Water
|
// child of Water
|
||||||
Mask_SimpleWater = (1<<11),
|
|
||||||
|
|
||||||
// top level masks
|
// top level masks
|
||||||
Mask_Scene = (1<<12),
|
Mask_Scene = (1<<12),
|
||||||
|
@ -34,9 +34,10 @@ namespace MWRender
|
||||||
Mask_ParticleSystem = (1<<14),
|
Mask_ParticleSystem = (1<<14),
|
||||||
|
|
||||||
// Set on cameras within the main scene graph
|
// Set on cameras within the main scene graph
|
||||||
Mask_RenderToTexture = (1<<15)
|
Mask_RenderToTexture = (1<<15),
|
||||||
|
|
||||||
// reserved: (1<<16) for SceneUtil::Mask_Lit
|
// Set on a camera's cull mask to enable the LightManager
|
||||||
|
Mask_Lighting = (1<<16)
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -302,7 +302,7 @@ public:
|
||||||
setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
|
setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
|
||||||
setReferenceFrame(osg::Camera::RELATIVE_RF);
|
setReferenceFrame(osg::Camera::RELATIVE_RF);
|
||||||
|
|
||||||
setCullMask(Mask_Effect|Mask_Scene|Mask_Terrain|Mask_Actor|Mask_ParticleSystem|Mask_Sky|Mask_Sun|Mask_Player|(1<<16));
|
setCullMask(Mask_Effect|Mask_Scene|Mask_Terrain|Mask_Actor|Mask_ParticleSystem|Mask_Sky|Mask_Sun|Mask_Player|Mask_Lighting);
|
||||||
setNodeMask(Mask_RenderToTexture);
|
setNodeMask(Mask_RenderToTexture);
|
||||||
setViewport(0, 0, rttSize, rttSize);
|
setViewport(0, 0, rttSize, rttSize);
|
||||||
|
|
||||||
|
@ -378,7 +378,7 @@ public:
|
||||||
setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
|
setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
|
||||||
setReferenceFrame(osg::Camera::RELATIVE_RF);
|
setReferenceFrame(osg::Camera::RELATIVE_RF);
|
||||||
|
|
||||||
setCullMask(Mask_Effect|Mask_Scene|Mask_Terrain|Mask_Actor|Mask_ParticleSystem|Mask_Sky|Mask_Player|(1<<16));
|
setCullMask(Mask_Effect|Mask_Scene|Mask_Terrain|Mask_Actor|Mask_ParticleSystem|Mask_Sky|Mask_Player|Mask_Lighting);
|
||||||
setNodeMask(Mask_RenderToTexture);
|
setNodeMask(Mask_RenderToTexture);
|
||||||
|
|
||||||
unsigned int rttSize = Settings::Manager::getInt("rtt size", "Water");
|
unsigned int rttSize = Settings::Manager::getInt("rtt size", "Water");
|
||||||
|
|
|
@ -146,7 +146,7 @@ namespace NifOsg
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
UVController();
|
UVController();
|
||||||
UVController(const UVController&,const osg::CopyOp& = osg::CopyOp::SHALLOW_COPY);
|
UVController(const UVController&,const osg::CopyOp&);
|
||||||
UVController(const Nif::NiUVData *data, std::set<int> textureUnits);
|
UVController(const Nif::NiUVData *data, std::set<int> textureUnits);
|
||||||
|
|
||||||
META_Object(NifOsg,UVController)
|
META_Object(NifOsg,UVController)
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <osg/Geode>
|
#include <osg/Geode>
|
||||||
#include <osg/Geometry>
|
#include <osg/Geometry>
|
||||||
#include <osg/Array>
|
#include <osg/Array>
|
||||||
|
#include <osg/Version>
|
||||||
|
|
||||||
// resource
|
// resource
|
||||||
#include <components/misc/stringops.hpp>
|
#include <components/misc/stringops.hpp>
|
||||||
|
@ -536,7 +537,7 @@ namespace NifOsg
|
||||||
handleSkinnedTriShape(triShape, node, composite, boundTextures, animflags);
|
handleSkinnedTriShape(triShape, node, composite, boundTextures, animflags);
|
||||||
|
|
||||||
if (!nifNode->controller.empty())
|
if (!nifNode->controller.empty())
|
||||||
handleMeshControllers(nifNode, composite, boundTextures, animflags);
|
handleMeshControllers(nifNode, node, composite, boundTextures, animflags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(nifNode->recType == Nif::RC_NiAutoNormalParticles || nifNode->recType == Nif::RC_NiRotatingParticles)
|
if(nifNode->recType == Nif::RC_NiAutoNormalParticles || nifNode->recType == Nif::RC_NiRotatingParticles)
|
||||||
|
@ -570,7 +571,7 @@ namespace NifOsg
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleMeshControllers(const Nif::Node *nifNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<int> &boundTextures, int animflags)
|
void handleMeshControllers(const Nif::Node *nifNode, osg::Node* node, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<int> &boundTextures, int animflags)
|
||||||
{
|
{
|
||||||
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
|
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
|
||||||
{
|
{
|
||||||
|
@ -587,6 +588,14 @@ namespace NifOsg
|
||||||
setupController(uvctrl, ctrl, animflags);
|
setupController(uvctrl, ctrl, animflags);
|
||||||
composite->addController(ctrl);
|
composite->addController(ctrl);
|
||||||
}
|
}
|
||||||
|
else if (ctrl->recType == Nif::RC_NiVisController)
|
||||||
|
{
|
||||||
|
handleVisController(static_cast<const Nif::NiVisController*>(ctrl.getPtr()), node, animflags);
|
||||||
|
}
|
||||||
|
else if(ctrl->recType == Nif::RC_NiGeomMorpherController)
|
||||||
|
{} // handled in handleTriShape
|
||||||
|
else
|
||||||
|
std::cerr << "Unhandled controller " << ctrl->recName << " on node " << nifNode->recIndex << " in " << mFilename << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -609,13 +618,18 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
else if (ctrl->recType == Nif::RC_NiVisController)
|
else if (ctrl->recType == Nif::RC_NiVisController)
|
||||||
{
|
{
|
||||||
const Nif::NiVisController* visctrl = static_cast<const Nif::NiVisController*>(ctrl.getPtr());
|
handleVisController(static_cast<const Nif::NiVisController*>(ctrl.getPtr()), transformNode, animflags);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
std::cerr << "Unhandled controller " << ctrl->recName << " on node " << nifNode->recIndex << " in " << mFilename << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleVisController(const Nif::NiVisController* visctrl, osg::Node* node, int animflags)
|
||||||
|
{
|
||||||
osg::ref_ptr<VisController> callback(new VisController(visctrl->data.getPtr()));
|
osg::ref_ptr<VisController> callback(new VisController(visctrl->data.getPtr()));
|
||||||
setupController(visctrl, callback, animflags);
|
setupController(visctrl, callback, animflags);
|
||||||
transformNode->addUpdateCallback(callback);
|
node->addUpdateCallback(callback);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleMaterialControllers(const Nif::Property *materialProperty, SceneUtil::CompositeStateSetUpdater* composite, int animflags)
|
void handleMaterialControllers(const Nif::Property *materialProperty, SceneUtil::CompositeStateSetUpdater* composite, int animflags)
|
||||||
|
@ -810,6 +824,8 @@ namespace NifOsg
|
||||||
continue;
|
continue;
|
||||||
if(ctrl->recType == Nif::RC_NiParticleSystemController || ctrl->recType == Nif::RC_NiBSPArrayController)
|
if(ctrl->recType == Nif::RC_NiParticleSystemController || ctrl->recType == Nif::RC_NiBSPArrayController)
|
||||||
partctrl = static_cast<Nif::NiParticleSystemController*>(ctrl.getPtr());
|
partctrl = static_cast<Nif::NiParticleSystemController*>(ctrl.getPtr());
|
||||||
|
else
|
||||||
|
std::cerr << "Unhandled controller " << ctrl->recName << " on node " << nifNode->recIndex << " in " << mFilename << std::endl;
|
||||||
}
|
}
|
||||||
if (!partctrl)
|
if (!partctrl)
|
||||||
{
|
{
|
||||||
|
@ -870,9 +886,6 @@ namespace NifOsg
|
||||||
// localToWorldMatrix for transforming to particle space
|
// localToWorldMatrix for transforming to particle space
|
||||||
handleParticlePrograms(partctrl->affectors, partctrl->colliders, parentNode, partsys.get(), rf);
|
handleParticlePrograms(partctrl->affectors, partctrl->colliders, parentNode, partsys.get(), rf);
|
||||||
|
|
||||||
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
|
||||||
geode->addDrawable(partsys);
|
|
||||||
|
|
||||||
std::vector<const Nif::Property*> drawableProps;
|
std::vector<const Nif::Property*> drawableProps;
|
||||||
collectDrawableProperties(nifNode, drawableProps);
|
collectDrawableProperties(nifNode, drawableProps);
|
||||||
applyDrawableProperties(parentNode, drawableProps, composite, true, animflags);
|
applyDrawableProperties(parentNode, drawableProps, composite, true, animflags);
|
||||||
|
@ -892,13 +905,21 @@ namespace NifOsg
|
||||||
updater->addParticleSystem(partsys);
|
updater->addParticleSystem(partsys);
|
||||||
parentNode->addChild(updater);
|
parentNode->addChild(updater);
|
||||||
|
|
||||||
|
#if OSG_VERSION_LESS_THAN(3,3,3)
|
||||||
|
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
||||||
|
geode->addDrawable(partsys);
|
||||||
|
osg::Node* toAttach = geode.get();
|
||||||
|
#else
|
||||||
|
osg::Node* toAttach = partsys.get();
|
||||||
|
#endif
|
||||||
|
|
||||||
if (rf == osgParticle::ParticleProcessor::RELATIVE_RF)
|
if (rf == osgParticle::ParticleProcessor::RELATIVE_RF)
|
||||||
parentNode->addChild(geode);
|
parentNode->addChild(toAttach);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
osg::MatrixTransform* trans = new osg::MatrixTransform;
|
osg::MatrixTransform* trans = new osg::MatrixTransform;
|
||||||
trans->setUpdateCallback(new InverseWorldMatrix);
|
trans->setUpdateCallback(new InverseWorldMatrix);
|
||||||
trans->addChild(geode);
|
trans->addChild(toAttach);
|
||||||
parentNode->addChild(trans);
|
parentNode->addChild(trans);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -943,11 +964,11 @@ namespace NifOsg
|
||||||
void handleTriShape(const Nif::NiTriShape* triShape, osg::Group* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<int>& boundTextures, int animflags)
|
void handleTriShape(const Nif::NiTriShape* triShape, osg::Group* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<int>& boundTextures, int animflags)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Geometry> geometry;
|
osg::ref_ptr<osg::Geometry> geometry;
|
||||||
if(!triShape->controller.empty())
|
for (Nif::ControllerPtr ctrl = triShape->controller; !ctrl.empty(); ctrl = ctrl->next)
|
||||||
{
|
{
|
||||||
Nif::ControllerPtr ctrl = triShape->controller;
|
if (!(ctrl->flags & Nif::NiNode::ControllerFlag_Active))
|
||||||
do {
|
continue;
|
||||||
if(ctrl->recType == Nif::RC_NiGeomMorpherController && ctrl->flags & Nif::NiNode::ControllerFlag_Active)
|
if(ctrl->recType == Nif::RC_NiGeomMorpherController)
|
||||||
{
|
{
|
||||||
geometry = handleMorphGeometry(static_cast<const Nif::NiGeomMorpherController*>(ctrl.getPtr()));
|
geometry = handleMorphGeometry(static_cast<const Nif::NiGeomMorpherController*>(ctrl.getPtr()));
|
||||||
|
|
||||||
|
@ -957,30 +978,43 @@ namespace NifOsg
|
||||||
geometry->setUpdateCallback(morphctrl);
|
geometry->setUpdateCallback(morphctrl);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while(!(ctrl=ctrl->next).empty());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!geometry.get())
|
if (!geometry.get())
|
||||||
geometry = new osg::Geometry;
|
geometry = new osg::Geometry;
|
||||||
|
|
||||||
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
|
||||||
triShapeToGeometry(triShape, geometry, parentNode, composite, boundTextures, animflags);
|
triShapeToGeometry(triShape, geometry, parentNode, composite, boundTextures, animflags);
|
||||||
|
|
||||||
|
#if OSG_VERSION_LESS_THAN(3,3,3)
|
||||||
|
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
||||||
geode->addDrawable(geometry);
|
geode->addDrawable(geometry);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (geometry->getDataVariance() == osg::Object::DYNAMIC)
|
if (geometry->getDataVariance() == osg::Object::DYNAMIC)
|
||||||
{
|
{
|
||||||
// Add a copy, we will alternate between the two copies every other frame using the FrameSwitch
|
// Add a copy, we will alternate between the two copies every other frame using the FrameSwitch
|
||||||
// This is so we can set the DataVariance as STATIC, giving a huge performance boost
|
// This is so we can set the DataVariance as STATIC, giving a huge performance boost
|
||||||
geometry->setDataVariance(osg::Object::STATIC);
|
geometry->setDataVariance(osg::Object::STATIC);
|
||||||
osg::ref_ptr<osg::Geode> geode2 = static_cast<osg::Geode*>(osg::clone(geode.get(), osg::CopyOp::DEEP_COPY_NODES|osg::CopyOp::DEEP_COPY_DRAWABLES));
|
|
||||||
osg::ref_ptr<FrameSwitch> frameswitch = new FrameSwitch;
|
osg::ref_ptr<FrameSwitch> frameswitch = new FrameSwitch;
|
||||||
|
|
||||||
|
#if OSG_VERSION_LESS_THAN(3,3,3)
|
||||||
|
osg::ref_ptr<osg::Geode> geode2 = static_cast<osg::Geode*>(osg::clone(geode.get(), osg::CopyOp::DEEP_COPY_NODES|osg::CopyOp::DEEP_COPY_DRAWABLES));
|
||||||
frameswitch->addChild(geode);
|
frameswitch->addChild(geode);
|
||||||
frameswitch->addChild(geode2);
|
frameswitch->addChild(geode2);
|
||||||
|
#else
|
||||||
|
osg::ref_ptr<osg::Geometry> geom2 = static_cast<osg::Geometry*>(osg::clone(geometry.get(), osg::CopyOp::DEEP_COPY_NODES|osg::CopyOp::DEEP_COPY_DRAWABLES));
|
||||||
|
frameswitch->addChild(geometry);
|
||||||
|
frameswitch->addChild(geom2);
|
||||||
|
#endif
|
||||||
|
|
||||||
parentNode->addChild(frameswitch);
|
parentNode->addChild(frameswitch);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#if OSG_VERSION_LESS_THAN(3,3,3)
|
||||||
parentNode->addChild(geode);
|
parentNode->addChild(geode);
|
||||||
|
#else
|
||||||
|
parentNode->addChild(geometry);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::ref_ptr<osg::Geometry> handleMorphGeometry(const Nif::NiGeomMorpherController* morpher)
|
osg::ref_ptr<osg::Geometry> handleMorphGeometry(const Nif::NiGeomMorpherController* morpher)
|
||||||
|
@ -1041,8 +1075,6 @@ namespace NifOsg
|
||||||
void handleSkinnedTriShape(const Nif::NiTriShape *triShape, osg::Group *parentNode, SceneUtil::CompositeStateSetUpdater* composite,
|
void handleSkinnedTriShape(const Nif::NiTriShape *triShape, osg::Group *parentNode, SceneUtil::CompositeStateSetUpdater* composite,
|
||||||
const std::vector<int>& boundTextures, int animflags)
|
const std::vector<int>& boundTextures, int animflags)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
|
||||||
|
|
||||||
osg::ref_ptr<osg::Geometry> geometry (new osg::Geometry);
|
osg::ref_ptr<osg::Geometry> geometry (new osg::Geometry);
|
||||||
triShapeToGeometry(triShape, geometry, parentNode, composite, boundTextures, animflags);
|
triShapeToGeometry(triShape, geometry, parentNode, composite, boundTextures, animflags);
|
||||||
|
|
||||||
|
@ -1075,17 +1107,27 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
rig->setInfluenceMap(map);
|
rig->setInfluenceMap(map);
|
||||||
|
|
||||||
geode->addDrawable(rig);
|
|
||||||
|
|
||||||
// Add a copy, we will alternate between the two copies every other frame using the FrameSwitch
|
// Add a copy, we will alternate between the two copies every other frame using the FrameSwitch
|
||||||
// This is so we can set the DataVariance as STATIC, giving a huge performance boost
|
// This is so we can set the DataVariance as STATIC, giving a huge performance boost
|
||||||
rig->setDataVariance(osg::Object::STATIC);
|
rig->setDataVariance(osg::Object::STATIC);
|
||||||
|
|
||||||
|
osg::ref_ptr<FrameSwitch> frameswitch = new FrameSwitch;
|
||||||
|
|
||||||
|
#if OSG_VERSION_LESS_THAN(3,3,3)
|
||||||
|
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
||||||
|
geode->addDrawable(rig);
|
||||||
|
|
||||||
osg::Geode* geode2 = static_cast<osg::Geode*>(osg::clone(geode.get(), osg::CopyOp::DEEP_COPY_NODES|
|
osg::Geode* geode2 = static_cast<osg::Geode*>(osg::clone(geode.get(), osg::CopyOp::DEEP_COPY_NODES|
|
||||||
osg::CopyOp::DEEP_COPY_DRAWABLES));
|
osg::CopyOp::DEEP_COPY_DRAWABLES));
|
||||||
|
|
||||||
osg::ref_ptr<FrameSwitch> frameswitch = new FrameSwitch;
|
|
||||||
frameswitch->addChild(geode);
|
frameswitch->addChild(geode);
|
||||||
frameswitch->addChild(geode2);
|
frameswitch->addChild(geode2);
|
||||||
|
#else
|
||||||
|
SceneUtil::RigGeometry* rig2 = static_cast<SceneUtil::RigGeometry*>(osg::clone(rig.get(), osg::CopyOp::DEEP_COPY_NODES|
|
||||||
|
osg::CopyOp::DEEP_COPY_DRAWABLES));
|
||||||
|
frameswitch->addChild(rig);
|
||||||
|
frameswitch->addChild(rig2);
|
||||||
|
#endif
|
||||||
|
|
||||||
parentNode->addChild(frameswitch);
|
parentNode->addChild(frameswitch);
|
||||||
}
|
}
|
||||||
|
@ -1365,7 +1407,7 @@ namespace NifOsg
|
||||||
osg::StateSet* stateset = node->getOrCreateStateSet();
|
osg::StateSet* stateset = node->getOrCreateStateSet();
|
||||||
|
|
||||||
int specFlags = 0; // Specular is disabled by default, even if there's a specular color in the NiMaterialProperty
|
int specFlags = 0; // Specular is disabled by default, even if there's a specular color in the NiMaterialProperty
|
||||||
osg::Material* mat = new osg::Material;
|
osg::ref_ptr<osg::Material> mat (new osg::Material);
|
||||||
mat->setColorMode(hasVertexColors ? osg::Material::AMBIENT_AND_DIFFUSE : osg::Material::OFF);
|
mat->setColorMode(hasVertexColors ? osg::Material::AMBIENT_AND_DIFFUSE : osg::Material::OFF);
|
||||||
|
|
||||||
// NIF material defaults don't match OpenGL defaults
|
// NIF material defaults don't match OpenGL defaults
|
||||||
|
@ -1420,12 +1462,11 @@ namespace NifOsg
|
||||||
case Nif::RC_NiAlphaProperty:
|
case Nif::RC_NiAlphaProperty:
|
||||||
{
|
{
|
||||||
const Nif::NiAlphaProperty* alphaprop = static_cast<const Nif::NiAlphaProperty*>(property);
|
const Nif::NiAlphaProperty* alphaprop = static_cast<const Nif::NiAlphaProperty*>(property);
|
||||||
osg::BlendFunc* blendfunc = new osg::BlendFunc;
|
|
||||||
if (alphaprop->flags&1)
|
if (alphaprop->flags&1)
|
||||||
{
|
{
|
||||||
blendfunc->setFunction(getBlendMode((alphaprop->flags>>1)&0xf),
|
stateset->setAttributeAndModes(new osg::BlendFunc(getBlendMode((alphaprop->flags>>1)&0xf),
|
||||||
getBlendMode((alphaprop->flags>>5)&0xf));
|
getBlendMode((alphaprop->flags>>5)&0xf)),
|
||||||
stateset->setAttributeAndModes(blendfunc, osg::StateAttribute::ON);
|
osg::StateAttribute::ON);
|
||||||
|
|
||||||
bool noSort = (alphaprop->flags>>13)&1;
|
bool noSort = (alphaprop->flags>>13)&1;
|
||||||
if (!noSort)
|
if (!noSort)
|
||||||
|
@ -1440,11 +1481,10 @@ namespace NifOsg
|
||||||
stateset->setRenderBinToInherit();
|
stateset->setRenderBinToInherit();
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::AlphaFunc* alphafunc = new osg::AlphaFunc;
|
|
||||||
if((alphaprop->flags>>9)&1)
|
if((alphaprop->flags>>9)&1)
|
||||||
{
|
{
|
||||||
alphafunc->setFunction(getTestMode((alphaprop->flags>>10)&0x7), alphaprop->data.threshold/255.f);
|
stateset->setAttributeAndModes(new osg::AlphaFunc(getTestMode((alphaprop->flags>>10)&0x7),
|
||||||
stateset->setAttributeAndModes(alphafunc, osg::StateAttribute::ON);
|
alphaprop->data.threshold/255.f), osg::StateAttribute::ON);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -60,7 +60,7 @@ namespace NifOsg
|
||||||
InverseWorldMatrix()
|
InverseWorldMatrix()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
InverseWorldMatrix(const InverseWorldMatrix& copy, const osg::CopyOp& op = osg::CopyOp::SHALLOW_COPY)
|
InverseWorldMatrix(const InverseWorldMatrix& copy, const osg::CopyOp& op)
|
||||||
: osg::Object(), osg::NodeCallback()
|
: osg::Object(), osg::NodeCallback()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -139,9 +139,6 @@ namespace NifOsg
|
||||||
|
|
||||||
META_Object(NifOsg, ParticleColorAffector)
|
META_Object(NifOsg, ParticleColorAffector)
|
||||||
|
|
||||||
// TODO: very similar to vec3 version, refactor to a template
|
|
||||||
osg::Vec4f interpolate(const float time, const Nif::Vector4KeyMap::MapType& keys);
|
|
||||||
|
|
||||||
virtual void operate(osgParticle::Particle* particle, double dt);
|
virtual void operate(osgParticle::Particle* particle, double dt);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <osg/Node>
|
#include <osg/Node>
|
||||||
#include <osg/Geode>
|
#include <osg/Geode>
|
||||||
#include <osg/UserDataContainer>
|
#include <osg/UserDataContainer>
|
||||||
|
#include <osg/Version>
|
||||||
|
|
||||||
#include <osgParticle/ParticleSystem>
|
#include <osgParticle/ParticleSystem>
|
||||||
|
|
||||||
|
@ -25,35 +26,54 @@ namespace
|
||||||
class InitWorldSpaceParticlesVisitor : public osg::NodeVisitor
|
class InitWorldSpaceParticlesVisitor : public osg::NodeVisitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
InitWorldSpaceParticlesVisitor()
|
/// @param mask The node mask to set on ParticleSystem nodes.
|
||||||
|
InitWorldSpaceParticlesVisitor(unsigned int mask)
|
||||||
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||||
|
, mMask(mask)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void apply(osg::Node& node)
|
bool isWorldSpaceParticleSystem(osgParticle::ParticleSystem* partsys)
|
||||||
{
|
|
||||||
if (osg::Geode* geode = node.asGeode())
|
|
||||||
{
|
|
||||||
for (unsigned int i=0;i<geode->getNumDrawables();++i)
|
|
||||||
{
|
|
||||||
if (osgParticle::ParticleSystem* partsys = dynamic_cast<osgParticle::ParticleSystem*>(geode->getDrawable(i)))
|
|
||||||
{
|
{
|
||||||
// HACK: ParticleSystem has no getReferenceFrame()
|
// HACK: ParticleSystem has no getReferenceFrame()
|
||||||
if (partsys->getUserDataContainer()
|
return (partsys->getUserDataContainer()
|
||||||
&& partsys->getUserDataContainer()->getNumDescriptions() > 0
|
&& partsys->getUserDataContainer()->getNumDescriptions() > 0
|
||||||
&& partsys->getUserDataContainer()->getDescriptions()[0] == "worldspace")
|
&& partsys->getUserDataContainer()->getDescriptions()[0] == "worldspace");
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply(osg::Geode& geode)
|
||||||
|
{
|
||||||
|
for (unsigned int i=0;i<geode.getNumDrawables();++i)
|
||||||
|
{
|
||||||
|
if (osgParticle::ParticleSystem* partsys = dynamic_cast<osgParticle::ParticleSystem*>(geode.getDrawable(i)))
|
||||||
|
{
|
||||||
|
if (isWorldSpaceParticleSystem(partsys))
|
||||||
{
|
{
|
||||||
// HACK: Ignore the InverseWorldMatrix transform the geode is attached to
|
// HACK: Ignore the InverseWorldMatrix transform the geode is attached to
|
||||||
if (geode->getNumParents() && geode->getParent(0)->getNumParents())
|
if (geode.getNumParents() && geode.getParent(0)->getNumParents())
|
||||||
transformInitialParticles(partsys, geode->getParent(0)->getParent(0));
|
transformInitialParticles(partsys, geode.getParent(0)->getParent(0));
|
||||||
}
|
}
|
||||||
geode->setNodeMask((1<<10)); //MWRender::Mask_ParticleSystem
|
geode.setNodeMask(mMask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
traverse(node);
|
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3)
|
||||||
|
// in OSG 3.3 and up Drawables can be directly in the scene graph without a Geode decorating them.
|
||||||
|
void apply(osg::Drawable& drw)
|
||||||
|
{
|
||||||
|
if (osgParticle::ParticleSystem* partsys = dynamic_cast<osgParticle::ParticleSystem*>(&drw))
|
||||||
|
{
|
||||||
|
if (isWorldSpaceParticleSystem(partsys))
|
||||||
|
{
|
||||||
|
// HACK: Ignore the InverseWorldMatrix transform the particle system is attached to
|
||||||
|
if (partsys->getNumParents() && partsys->getParent(0)->getNumParents())
|
||||||
|
transformInitialParticles(partsys, partsys->getParent(0)->getParent(0));
|
||||||
}
|
}
|
||||||
|
partsys->setNodeMask(mMask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void transformInitialParticles(osgParticle::ParticleSystem* partsys, osg::Node* node)
|
void transformInitialParticles(osgParticle::ParticleSystem* partsys, osg::Node* node)
|
||||||
{
|
{
|
||||||
|
@ -74,8 +94,9 @@ namespace
|
||||||
box.expandBy(sphere);
|
box.expandBy(sphere);
|
||||||
partsys->setInitialBound(box);
|
partsys->setInitialBound(box);
|
||||||
}
|
}
|
||||||
|
private:
|
||||||
|
unsigned int mMask;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Resource
|
namespace Resource
|
||||||
|
@ -84,6 +105,7 @@ namespace Resource
|
||||||
SceneManager::SceneManager(const VFS::Manager *vfs, Resource::TextureManager* textureManager)
|
SceneManager::SceneManager(const VFS::Manager *vfs, Resource::TextureManager* textureManager)
|
||||||
: mVFS(vfs)
|
: mVFS(vfs)
|
||||||
, mTextureManager(textureManager)
|
, mTextureManager(textureManager)
|
||||||
|
, mParticleSystemMask(~0u)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +205,7 @@ namespace Resource
|
||||||
|
|
||||||
void SceneManager::notifyAttached(osg::Node *node) const
|
void SceneManager::notifyAttached(osg::Node *node) const
|
||||||
{
|
{
|
||||||
InitWorldSpaceParticlesVisitor visitor;
|
InitWorldSpaceParticlesVisitor visitor (mParticleSystemMask);
|
||||||
node->accept(visitor);
|
node->accept(visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,4 +219,9 @@ namespace Resource
|
||||||
return mTextureManager;
|
return mTextureManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SceneManager::setParticleSystemMask(unsigned int mask)
|
||||||
|
{
|
||||||
|
mParticleSystemMask = mask;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,12 +73,17 @@ namespace Resource
|
||||||
|
|
||||||
Resource::TextureManager* getTextureManager();
|
Resource::TextureManager* getTextureManager();
|
||||||
|
|
||||||
|
/// @param mask The node mask to apply to loaded particle system nodes.
|
||||||
|
void setParticleSystemMask(unsigned int mask);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const VFS::Manager* mVFS;
|
const VFS::Manager* mVFS;
|
||||||
Resource::TextureManager* mTextureManager;
|
Resource::TextureManager* mTextureManager;
|
||||||
|
|
||||||
osg::ref_ptr<osgUtil::IncrementalCompileOperation> mIncrementalCompileOperation;
|
osg::ref_ptr<osgUtil::IncrementalCompileOperation> mIncrementalCompileOperation;
|
||||||
|
|
||||||
|
unsigned int mParticleSystemMask;
|
||||||
|
|
||||||
// observer_ptr?
|
// observer_ptr?
|
||||||
typedef std::map<std::string, osg::ref_ptr<const osg::Node> > Index;
|
typedef std::map<std::string, osg::ref_ptr<const osg::Node> > Index;
|
||||||
Index mIndex;
|
Index mIndex;
|
||||||
|
|
|
@ -119,7 +119,7 @@ namespace Resource
|
||||||
case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT):
|
case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT):
|
||||||
case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT):
|
case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT):
|
||||||
{
|
{
|
||||||
#if OSG_MIN_VERSION_REQUIRED(3,3,3)
|
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3)
|
||||||
osg::GLExtensions* exts = osg::GLExtensions::Get(0, false);
|
osg::GLExtensions* exts = osg::GLExtensions::Get(0, false);
|
||||||
if (exts && !exts->isTextureCompressionS3TCSupported
|
if (exts && !exts->isTextureCompressionS3TCSupported
|
||||||
// This one works too. Should it be included in isTextureCompressionS3TCSupported()? Submitted as a patch to OSG.
|
// This one works too. Should it be included in isTextureCompressionS3TCSupported()? Submitted as a patch to OSG.
|
||||||
|
|
|
@ -65,7 +65,7 @@ namespace SceneUtil
|
||||||
|
|
||||||
void ControllerVisitor::apply(osg::Node &node)
|
void ControllerVisitor::apply(osg::Node &node)
|
||||||
{
|
{
|
||||||
#if OSG_MIN_VERSION_REQUIRED(3,3,3)
|
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3)
|
||||||
osg::Callback* callback = node.getUpdateCallback();
|
osg::Callback* callback = node.getUpdateCallback();
|
||||||
#else
|
#else
|
||||||
osg::NodeCallback* callback = node.getUpdateCallback();
|
osg::NodeCallback* callback = node.getUpdateCallback();
|
||||||
|
@ -96,7 +96,7 @@ namespace SceneUtil
|
||||||
{
|
{
|
||||||
osg::Drawable* drw = geode.getDrawable(i);
|
osg::Drawable* drw = geode.getDrawable(i);
|
||||||
|
|
||||||
#if OSG_MIN_VERSION_REQUIRED(3,3,3)
|
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3)
|
||||||
osg::Callback* callback = drw->getUpdateCallback();
|
osg::Callback* callback = drw->getUpdateCallback();
|
||||||
#else
|
#else
|
||||||
osg::Drawable::UpdateCallback* callback = drw->getUpdateCallback();
|
osg::Drawable::UpdateCallback* callback = drw->getUpdateCallback();
|
||||||
|
|
|
@ -131,6 +131,7 @@ namespace SceneUtil
|
||||||
|
|
||||||
LightManager::LightManager()
|
LightManager::LightManager()
|
||||||
: mStartLight(0)
|
: mStartLight(0)
|
||||||
|
, mLightingMask(~0u)
|
||||||
{
|
{
|
||||||
setUpdateCallback(new LightManagerUpdateCallback);
|
setUpdateCallback(new LightManagerUpdateCallback);
|
||||||
}
|
}
|
||||||
|
@ -138,10 +139,21 @@ namespace SceneUtil
|
||||||
LightManager::LightManager(const LightManager ©, const osg::CopyOp ©op)
|
LightManager::LightManager(const LightManager ©, const osg::CopyOp ©op)
|
||||||
: osg::Group(copy, copyop)
|
: osg::Group(copy, copyop)
|
||||||
, mStartLight(copy.mStartLight)
|
, mStartLight(copy.mStartLight)
|
||||||
|
, mLightingMask(copy.mLightingMask)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LightManager::setLightingMask(unsigned int mask)
|
||||||
|
{
|
||||||
|
mLightingMask = mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int LightManager::getLightingMask() const
|
||||||
|
{
|
||||||
|
return mLightingMask;
|
||||||
|
}
|
||||||
|
|
||||||
void LightManager::update()
|
void LightManager::update()
|
||||||
{
|
{
|
||||||
mLights.clear();
|
mLights.clear();
|
||||||
|
@ -237,7 +249,6 @@ namespace SceneUtil
|
||||||
LightSource::LightSource()
|
LightSource::LightSource()
|
||||||
: mRadius(0.f)
|
: mRadius(0.f)
|
||||||
{
|
{
|
||||||
setNodeMask(Mask_Lit);
|
|
||||||
setUpdateCallback(new CollectLightCallback);
|
setUpdateCallback(new CollectLightCallback);
|
||||||
mId = sLightId++;
|
mId = sLightId++;
|
||||||
}
|
}
|
||||||
|
@ -260,12 +271,6 @@ namespace SceneUtil
|
||||||
{
|
{
|
||||||
osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(nv);
|
osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(nv);
|
||||||
|
|
||||||
if (!(cv->getCurrentCamera()->getCullMask()&Mask_Lit))
|
|
||||||
{
|
|
||||||
traverse(node, nv);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mLightManager)
|
if (!mLightManager)
|
||||||
{
|
{
|
||||||
mLightManager = findLightManager(nv->getNodePath());
|
mLightManager = findLightManager(nv->getNodePath());
|
||||||
|
@ -276,6 +281,12 @@ namespace SceneUtil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(cv->getCurrentCamera()->getCullMask() & mLightManager->getLightingMask()))
|
||||||
|
{
|
||||||
|
traverse(node, nv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Possible optimizations:
|
// Possible optimizations:
|
||||||
// - 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
|
||||||
|
|
|
@ -9,9 +9,6 @@
|
||||||
namespace SceneUtil
|
namespace SceneUtil
|
||||||
{
|
{
|
||||||
|
|
||||||
// This mask should be included in the Cull and Update visitor's traversal mask if lighting is desired.
|
|
||||||
const int Mask_Lit = (1<<16);
|
|
||||||
|
|
||||||
/// LightSource managed by a LightManager.
|
/// LightSource managed by a LightManager.
|
||||||
class LightSource : public osg::Node
|
class LightSource : public osg::Node
|
||||||
{
|
{
|
||||||
|
@ -68,6 +65,14 @@ namespace SceneUtil
|
||||||
|
|
||||||
LightManager(const LightManager& copy, const osg::CopyOp& copyop);
|
LightManager(const LightManager& copy, const osg::CopyOp& copyop);
|
||||||
|
|
||||||
|
/// @param mask This mask is compared with the current Camera's cull mask to determine if lighting is desired.
|
||||||
|
/// By default, it's ~0u i.e. always on.
|
||||||
|
/// If you have some views that do not require lighting, then set the Camera's cull mask to not include
|
||||||
|
/// the lightingMask for a much faster cull and rendering.
|
||||||
|
void setLightingMask (unsigned int mask);
|
||||||
|
|
||||||
|
unsigned int getLightingMask() const;
|
||||||
|
|
||||||
// Called automatically by the UpdateCallback
|
// Called automatically by the UpdateCallback
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
|
@ -111,6 +116,8 @@ namespace SceneUtil
|
||||||
LightStateSetMap mStateSetCache;
|
LightStateSetMap mStateSetCache;
|
||||||
|
|
||||||
int mStartLight;
|
int mStartLight;
|
||||||
|
|
||||||
|
unsigned int mLightingMask;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @note Not thread safe for CullThreadPerCamera threading mode.
|
/// @note Not thread safe for CullThreadPerCamera threading mode.
|
||||||
|
@ -121,7 +128,7 @@ namespace SceneUtil
|
||||||
: mLightManager(NULL)
|
: mLightManager(NULL)
|
||||||
, mLastFrameNumber(0)
|
, mLastFrameNumber(0)
|
||||||
{}
|
{}
|
||||||
LightListCallback(const LightListCallback& copy, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY)
|
LightListCallback(const LightListCallback& copy, const osg::CopyOp& copyop)
|
||||||
: osg::Object(copy, copyop), osg::NodeCallback(copy, copyop)
|
: osg::Object(copy, copyop), osg::NodeCallback(copy, copyop)
|
||||||
, mLightManager(copy.mLightManager)
|
, mLightManager(copy.mLightManager)
|
||||||
, mLastFrameNumber(0)
|
, mLastFrameNumber(0)
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include <osg/Version>
|
||||||
#include <osg/MatrixTransform>
|
#include <osg/MatrixTransform>
|
||||||
|
|
||||||
#include "skeleton.hpp"
|
#include "skeleton.hpp"
|
||||||
|
@ -58,6 +58,14 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// We can't compute the bounds without a NodeVisitor, since we need the current geomToSkelMatrix.
|
||||||
|
// So we return nothing. Bounds are updated every frame in the UpdateCallback.
|
||||||
|
class DummyComputeBoundCallback : public osg::Drawable::ComputeBoundingBoxCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual osg::BoundingBox computeBound(const osg::Drawable&) const { return osg::BoundingBox(); }
|
||||||
|
};
|
||||||
|
|
||||||
RigGeometry::RigGeometry()
|
RigGeometry::RigGeometry()
|
||||||
: mSkeleton(NULL)
|
: mSkeleton(NULL)
|
||||||
, mLastFrameNumber(0)
|
, mLastFrameNumber(0)
|
||||||
|
@ -66,6 +74,7 @@ RigGeometry::RigGeometry()
|
||||||
setCullCallback(new UpdateRigGeometry);
|
setCullCallback(new UpdateRigGeometry);
|
||||||
setUpdateCallback(new UpdateRigBounds);
|
setUpdateCallback(new UpdateRigBounds);
|
||||||
setSupportsDisplayList(false);
|
setSupportsDisplayList(false);
|
||||||
|
setComputeBoundingBoxCallback(new DummyComputeBoundCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
RigGeometry::RigGeometry(const RigGeometry ©, const osg::CopyOp ©op)
|
RigGeometry::RigGeometry(const RigGeometry ©, const osg::CopyOp ©op)
|
||||||
|
@ -278,6 +287,12 @@ void RigGeometry::updateBounds(osg::NodeVisitor *nv)
|
||||||
}
|
}
|
||||||
|
|
||||||
_boundingBox = box;
|
_boundingBox = box;
|
||||||
|
_boundingBoxComputed = true;
|
||||||
|
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3)
|
||||||
|
// in OSG 3.3.3 and up Drawable inherits from Node, so has a bounding sphere as well.
|
||||||
|
_boundingSphere = osg::BoundingSphere(_boundingBox);
|
||||||
|
_boundingSphereComputed = true;
|
||||||
|
#endif
|
||||||
for (unsigned int i=0; i<getNumParents(); ++i)
|
for (unsigned int i=0; i<getNumParents(); ++i)
|
||||||
getParent(i)->dirtyBound();
|
getParent(i)->dirtyBound();
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,11 +22,13 @@ namespace SceneUtil
|
||||||
void DisableFreezeOnCullVisitor::apply(osg::Geode &geode)
|
void DisableFreezeOnCullVisitor::apply(osg::Geode &geode)
|
||||||
{
|
{
|
||||||
for (unsigned int i=0; i<geode.getNumDrawables(); ++i)
|
for (unsigned int i=0; i<geode.getNumDrawables(); ++i)
|
||||||
{
|
apply(*geode.getDrawable(i));
|
||||||
osg::Drawable* drw = geode.getDrawable(i);
|
|
||||||
if (osgParticle::ParticleSystem* partsys = dynamic_cast<osgParticle::ParticleSystem*>(drw))
|
|
||||||
partsys->setFreezeOnCull(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DisableFreezeOnCullVisitor::apply(osg::Drawable& drw)
|
||||||
|
{
|
||||||
|
if (osgParticle::ParticleSystem* partsys = dynamic_cast<osgParticle::ParticleSystem*>(&drw))
|
||||||
|
partsys->setFreezeOnCull(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ namespace SceneUtil
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void apply(osg::Geode &geode);
|
virtual void apply(osg::Geode &geode);
|
||||||
|
virtual void apply(osg::Drawable& drw);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
#include <SDL_video.h>
|
#include <SDL_video.h>
|
||||||
|
|
||||||
#include <osg/DeleteHandler>
|
|
||||||
#include <osg/Version>
|
#include <osg/Version>
|
||||||
|
|
||||||
namespace SDLUtil
|
namespace SDLUtil
|
||||||
|
@ -79,15 +78,13 @@ void GraphicsWindowSDL2::init()
|
||||||
if(!_traits.valid())
|
if(!_traits.valid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// getEventQueue()->setCurrentEventState(osgGA::GUIEventAdapter::getAccumulatedEventState().get());
|
|
||||||
|
|
||||||
WindowData *inheritedWindowData = dynamic_cast<WindowData*>(_traits->inheritedWindowData.get());
|
WindowData *inheritedWindowData = dynamic_cast<WindowData*>(_traits->inheritedWindowData.get());
|
||||||
mWindow = inheritedWindowData ? inheritedWindowData->mWindow : NULL;
|
mWindow = inheritedWindowData ? inheritedWindowData->mWindow : NULL;
|
||||||
|
|
||||||
mOwnsWindow = (mWindow == 0);
|
mOwnsWindow = (mWindow == 0);
|
||||||
if(mOwnsWindow)
|
if(mOwnsWindow)
|
||||||
{
|
{
|
||||||
OSG_NOTICE<<"Error: No SDL window provided."<<std::endl;
|
OSG_FATAL<<"Error: No SDL window provided."<<std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +96,7 @@ void GraphicsWindowSDL2::init()
|
||||||
mContext = SDL_GL_CreateContext(mWindow);
|
mContext = SDL_GL_CreateContext(mWindow);
|
||||||
if(!mContext)
|
if(!mContext)
|
||||||
{
|
{
|
||||||
OSG_NOTICE<< "Error: Unable to create OpenGL graphics context: "<<SDL_GetError() <<std::endl;
|
OSG_FATAL<< "Error: Unable to create OpenGL graphics context: "<<SDL_GetError() <<std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +106,7 @@ void GraphicsWindowSDL2::init()
|
||||||
|
|
||||||
mValid = true;
|
mValid = true;
|
||||||
|
|
||||||
#if OSG_MIN_VERSION_REQUIRED(3,3,4)
|
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,4)
|
||||||
getEventQueue()->syncWindowRectangleWithGraphicsContext();
|
getEventQueue()->syncWindowRectangleWithGraphicsContext();
|
||||||
#else
|
#else
|
||||||
getEventQueue()->syncWindowRectangleWithGraphcisContext();
|
getEventQueue()->syncWindowRectangleWithGraphcisContext();
|
||||||
|
@ -130,7 +127,7 @@ bool GraphicsWindowSDL2::realizeImplementation()
|
||||||
|
|
||||||
SDL_ShowWindow(mWindow);
|
SDL_ShowWindow(mWindow);
|
||||||
|
|
||||||
#if OSG_MIN_VERSION_REQUIRED(3,3,4)
|
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,4)
|
||||||
getEventQueue()->syncWindowRectangleWithGraphicsContext();
|
getEventQueue()->syncWindowRectangleWithGraphicsContext();
|
||||||
#else
|
#else
|
||||||
getEventQueue()->syncWindowRectangleWithGraphcisContext();
|
getEventQueue()->syncWindowRectangleWithGraphcisContext();
|
||||||
|
@ -145,7 +142,7 @@ bool GraphicsWindowSDL2::makeCurrentImplementation()
|
||||||
{
|
{
|
||||||
if(!mRealized)
|
if(!mRealized)
|
||||||
{
|
{
|
||||||
OSG_NOTICE<<"Warning: GraphicsWindow not realized, cannot do makeCurrent."<<std::endl;
|
OSG_WARN<<"Warning: GraphicsWindow not realized, cannot do makeCurrent."<<std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +153,7 @@ bool GraphicsWindowSDL2::releaseContextImplementation()
|
||||||
{
|
{
|
||||||
if(!mRealized)
|
if(!mRealized)
|
||||||
{
|
{
|
||||||
OSG_NOTICE<< "Warning: GraphicsWindow not realized, cannot do releaseContext." <<std::endl;
|
OSG_WARN<< "Warning: GraphicsWindow not realized, cannot do releaseContext." <<std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,8 +163,6 @@ bool GraphicsWindowSDL2::releaseContextImplementation()
|
||||||
|
|
||||||
void GraphicsWindowSDL2::closeImplementation()
|
void GraphicsWindowSDL2::closeImplementation()
|
||||||
{
|
{
|
||||||
// OSG_NOTICE<<"Closing GraphicsWindowSDL2"<<std::endl;
|
|
||||||
|
|
||||||
if(mContext)
|
if(mContext)
|
||||||
SDL_GL_DeleteContext(mContext);
|
SDL_GL_DeleteContext(mContext);
|
||||||
mContext = NULL;
|
mContext = NULL;
|
||||||
|
@ -184,8 +179,6 @@ void GraphicsWindowSDL2::swapBuffersImplementation()
|
||||||
{
|
{
|
||||||
if(!mRealized) return;
|
if(!mRealized) return;
|
||||||
|
|
||||||
//OSG_NOTICE<< "swapBuffersImplementation "<<this<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
|
|
||||||
|
|
||||||
SDL_GL_SwapWindow(mWindow);
|
SDL_GL_SwapWindow(mWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue