mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 21:23:52 +00:00
Port nifloader to the more efficient StateSetController
This commit is contained in:
parent
5dd1ab24fe
commit
de2c85e0f8
5 changed files with 132 additions and 80 deletions
|
@ -278,7 +278,7 @@ UVController::UVController(const Nif::NiUVData *data, std::set<int> textureUnits
|
||||||
}
|
}
|
||||||
|
|
||||||
UVController::UVController(const UVController& copy, const osg::CopyOp& copyop)
|
UVController::UVController(const UVController& copy, const osg::CopyOp& copyop)
|
||||||
: osg::Object(copy, copyop), osg::NodeCallback(copy, copyop), Controller(copy)
|
: osg::Object(copy, copyop), StateSetController(copy, copyop), Controller(copy)
|
||||||
, mUTrans(copy.mUTrans)
|
, mUTrans(copy.mUTrans)
|
||||||
, mVTrans(copy.mVTrans)
|
, mVTrans(copy.mVTrans)
|
||||||
, mUScale(copy.mUScale)
|
, mUScale(copy.mUScale)
|
||||||
|
@ -287,11 +287,17 @@ UVController::UVController(const UVController& copy, const osg::CopyOp& copyop)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void UVController::operator()(osg::Node* node, osg::NodeVisitor* nv)
|
void UVController::setDefaults(osg::StateSet *stateset)
|
||||||
|
{
|
||||||
|
osg::TexMat* texMat = new osg::TexMat;
|
||||||
|
for (std::set<int>::const_iterator it = mTextureUnits.begin(); it != mTextureUnits.end(); ++it)
|
||||||
|
stateset->setTextureAttributeAndModes(*it, texMat, osg::StateAttribute::ON);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UVController::apply(osg::StateSet* stateset, osg::NodeVisitor* nv)
|
||||||
{
|
{
|
||||||
if (hasInput())
|
if (hasInput())
|
||||||
{
|
{
|
||||||
osg::StateSet* stateset = getWritableStateSet(node);
|
|
||||||
float value = getInputValue(nv);
|
float value = getInputValue(nv);
|
||||||
float uTrans = interpKey(mUTrans->mKeys, value, 0.0f);
|
float uTrans = interpKey(mUTrans->mKeys, value, 0.0f);
|
||||||
float vTrans = interpKey(mVTrans->mKeys, value, 0.0f);
|
float vTrans = interpKey(mVTrans->mKeys, value, 0.0f);
|
||||||
|
@ -301,15 +307,13 @@ void UVController::operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||||
osg::Matrixf mat = osg::Matrixf::scale(uScale, vScale, 1);
|
osg::Matrixf mat = osg::Matrixf::scale(uScale, vScale, 1);
|
||||||
mat.setTrans(uTrans, vTrans, 0);
|
mat.setTrans(uTrans, vTrans, 0);
|
||||||
|
|
||||||
osg::TexMat* texMat = new osg::TexMat;
|
// setting once is enough because all other texture units share the same TexMat (see setDefaults).
|
||||||
texMat->setMatrix(mat);
|
if (mTextureUnits.size())
|
||||||
|
|
||||||
for (std::set<int>::const_iterator it = mTextureUnits.begin(); it != mTextureUnits.end(); ++it)
|
|
||||||
{
|
{
|
||||||
stateset->setTextureAttributeAndModes(*it, texMat, osg::StateAttribute::ON);
|
osg::TexMat* texMat = static_cast<osg::TexMat*>(stateset->getTextureAttribute(*mTextureUnits.begin(), osg::StateAttribute::TEXMAT));
|
||||||
|
texMat->setMatrix(mat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
traverse(node, nv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VisController::VisController(const Nif::NiVisData *data)
|
VisController::VisController(const Nif::NiVisData *data)
|
||||||
|
@ -363,27 +367,22 @@ AlphaController::AlphaController()
|
||||||
}
|
}
|
||||||
|
|
||||||
AlphaController::AlphaController(const AlphaController ©, const osg::CopyOp ©op)
|
AlphaController::AlphaController(const AlphaController ©, const osg::CopyOp ©op)
|
||||||
: osg::NodeCallback(copy, copyop), ValueInterpolator(), Controller(copy)
|
: StateSetController(copy, copyop), ValueInterpolator(), Controller(copy)
|
||||||
, mData(copy.mData)
|
, mData(copy.mData)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlphaController::operator () (osg::Node* node, osg::NodeVisitor* nv)
|
void AlphaController::apply(osg::StateSet *stateset, osg::NodeVisitor *nv)
|
||||||
{
|
{
|
||||||
if (hasInput())
|
if (hasInput())
|
||||||
{
|
{
|
||||||
osg::StateSet* stateset = getWritableStateSet(node);
|
|
||||||
float value = interpKey(mData->mKeys, getInputValue(nv));
|
float value = interpKey(mData->mKeys, getInputValue(nv));
|
||||||
osg::Material* mat = dynamic_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
|
osg::Material* mat = static_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
|
||||||
if (mat)
|
|
||||||
{
|
|
||||||
osg::Vec4f diffuse = mat->getDiffuse(osg::Material::FRONT_AND_BACK);
|
osg::Vec4f diffuse = mat->getDiffuse(osg::Material::FRONT_AND_BACK);
|
||||||
diffuse.a() = value;
|
diffuse.a() = value;
|
||||||
mat->setDiffuse(osg::Material::FRONT_AND_BACK, diffuse);
|
mat->setDiffuse(osg::Material::FRONT_AND_BACK, diffuse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
traverse(node, nv);
|
|
||||||
}
|
|
||||||
|
|
||||||
MaterialColorController::MaterialColorController(const Nif::NiPosData *data)
|
MaterialColorController::MaterialColorController(const Nif::NiPosData *data)
|
||||||
: mData(data->mKeyList)
|
: mData(data->mKeyList)
|
||||||
|
@ -395,27 +394,22 @@ MaterialColorController::MaterialColorController()
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialColorController::MaterialColorController(const MaterialColorController ©, const osg::CopyOp ©op)
|
MaterialColorController::MaterialColorController(const MaterialColorController ©, const osg::CopyOp ©op)
|
||||||
: osg::NodeCallback(copy, copyop), Controller(copy)
|
: StateSetController(copy, copyop), Controller(copy)
|
||||||
, mData(copy.mData)
|
, mData(copy.mData)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void MaterialColorController::operator() (osg::Node* node, osg::NodeVisitor* nv)
|
void MaterialColorController::apply(osg::StateSet *stateset, osg::NodeVisitor *nv)
|
||||||
{
|
{
|
||||||
if (hasInput())
|
if (hasInput())
|
||||||
{
|
{
|
||||||
osg::StateSet* stateset = getWritableStateSet(node);
|
|
||||||
osg::Vec3f value = interpKey(mData->mKeys, getInputValue(nv));
|
osg::Vec3f value = interpKey(mData->mKeys, getInputValue(nv));
|
||||||
osg::Material* mat = dynamic_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
|
osg::Material* mat = static_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
|
||||||
if (mat)
|
|
||||||
{
|
|
||||||
osg::Vec4f diffuse = mat->getDiffuse(osg::Material::FRONT_AND_BACK);
|
osg::Vec4f diffuse = mat->getDiffuse(osg::Material::FRONT_AND_BACK);
|
||||||
diffuse.set(value.x(), value.y(), value.z(), diffuse.a());
|
diffuse.set(value.x(), value.y(), value.z(), diffuse.a());
|
||||||
mat->setDiffuse(osg::Material::FRONT_AND_BACK, diffuse);
|
mat->setDiffuse(osg::Material::FRONT_AND_BACK, diffuse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
traverse(node, nv);
|
|
||||||
}
|
|
||||||
|
|
||||||
FlipController::FlipController(const Nif::NiFlipController *ctrl, std::vector<osg::ref_ptr<osg::Texture2D> > textures)
|
FlipController::FlipController(const Nif::NiFlipController *ctrl, std::vector<osg::ref_ptr<osg::Texture2D> > textures)
|
||||||
: mTexSlot(ctrl->mTexSlot)
|
: mTexSlot(ctrl->mTexSlot)
|
||||||
|
@ -429,7 +423,7 @@ FlipController::FlipController()
|
||||||
}
|
}
|
||||||
|
|
||||||
FlipController::FlipController(const FlipController ©, const osg::CopyOp ©op)
|
FlipController::FlipController(const FlipController ©, const osg::CopyOp ©op)
|
||||||
: osg::NodeCallback(copy, copyop)
|
: StateSetController(copy, copyop)
|
||||||
, Controller(copy)
|
, Controller(copy)
|
||||||
, mTexSlot(copy.mTexSlot)
|
, mTexSlot(copy.mTexSlot)
|
||||||
, mDelta(copy.mDelta)
|
, mDelta(copy.mDelta)
|
||||||
|
@ -437,15 +431,13 @@ FlipController::FlipController(const FlipController ©, const osg::CopyOp &co
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlipController::operator() (osg::Node* node, osg::NodeVisitor* nv)
|
void FlipController::apply(osg::StateSet* stateset, osg::NodeVisitor* nv)
|
||||||
{
|
{
|
||||||
if (hasInput() && mDelta != 0)
|
if (hasInput() && mDelta != 0)
|
||||||
{
|
{
|
||||||
osg::StateSet* stateset = getWritableStateSet(node);
|
|
||||||
int curTexture = int(getInputValue(nv) / mDelta) % mTextures.size();
|
int curTexture = int(getInputValue(nv) / mDelta) % mTextures.size();
|
||||||
stateset->setTextureAttribute(mTexSlot, mTextures[curTexture]);
|
stateset->setTextureAttribute(mTexSlot, mTextures[curTexture]);
|
||||||
}
|
}
|
||||||
traverse(node, nv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ParticleSystemController::ParticleSystemController(const Nif::NiParticleSystemController *ctrl)
|
ParticleSystemController::ParticleSystemController(const Nif::NiParticleSystemController *ctrl)
|
||||||
|
@ -507,12 +499,4 @@ void SourcedKeyframeController::operator ()(osg::Node* node, osg::NodeVisitor* n
|
||||||
traverse(node, nv);
|
traverse(node, nv);
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::StateSet *StateSetController::getWritableStateSet(osg::Node *node)
|
|
||||||
{
|
|
||||||
osg::StateSet* orig = node->getOrCreateStateSet();
|
|
||||||
osg::StateSet* cloned = new osg::StateSet(*orig, osg::CopyOp::SHALLOW_COPY);
|
|
||||||
node->setStateSet(cloned);
|
|
||||||
return cloned;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
#include <components/nifcache/nifcache.hpp>
|
#include <components/nifcache/nifcache.hpp>
|
||||||
|
|
||||||
|
#include <components/sceneutil/statesetcontroller.hpp>
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
#include <set> //UVController
|
#include <set> //UVController
|
||||||
|
@ -189,19 +191,7 @@ namespace NifOsg
|
||||||
bool mEnabled;
|
bool mEnabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
class StateSetController
|
class UVController : public SceneUtil::StateSetController, public Controller, public ValueInterpolator
|
||||||
{
|
|
||||||
protected:
|
|
||||||
// Clones a StateSet to make it "writable". This is to prevent race conditions when the OSG draw thread of the last frame
|
|
||||||
// queues up a StateSet that we want to modify. Note, we could also set the StateSet to DYNAMIC data variance but that would
|
|
||||||
// undo all the benefits of the threading model - having the cull and draw traversals run in parallel can yield up to 200% framerates.
|
|
||||||
// If the StateSet allocations per frame are proving too much of an overhead we could "reuse" StateSets from previous frames,
|
|
||||||
// kind of like a double buffering scheme.
|
|
||||||
osg::StateSet* getWritableStateSet(osg::Node* node);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Note we're using NodeCallback instead of StateSet::Callback because the StateSet callback doesn't support nesting
|
|
||||||
class UVController : public osg::NodeCallback, public Controller, public StateSetController, public ValueInterpolator
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
UVController();
|
UVController();
|
||||||
|
@ -210,7 +200,8 @@ namespace NifOsg
|
||||||
|
|
||||||
META_Object(NifOsg,UVController)
|
META_Object(NifOsg,UVController)
|
||||||
|
|
||||||
virtual void operator() (osg::Node*, osg::NodeVisitor*);
|
virtual void setDefaults(osg::StateSet* stateset);
|
||||||
|
virtual void apply(osg::StateSet *stateset, osg::NodeVisitor *nv);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Nif::FloatKeyMapPtr mUTrans;
|
Nif::FloatKeyMapPtr mUTrans;
|
||||||
|
@ -237,7 +228,7 @@ namespace NifOsg
|
||||||
virtual void operator() (osg::Node* node, osg::NodeVisitor* nv);
|
virtual void operator() (osg::Node* node, osg::NodeVisitor* nv);
|
||||||
};
|
};
|
||||||
|
|
||||||
class AlphaController : public osg::NodeCallback, public Controller, public StateSetController, public ValueInterpolator
|
class AlphaController : public SceneUtil::StateSetController, public Controller, public ValueInterpolator
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
Nif::FloatKeyMapPtr mData;
|
Nif::FloatKeyMapPtr mData;
|
||||||
|
@ -247,12 +238,12 @@ namespace NifOsg
|
||||||
AlphaController();
|
AlphaController();
|
||||||
AlphaController(const AlphaController& copy, const osg::CopyOp& copyop);
|
AlphaController(const AlphaController& copy, const osg::CopyOp& copyop);
|
||||||
|
|
||||||
virtual void operator() (osg::Node* node, osg::NodeVisitor* nv);
|
virtual void apply(osg::StateSet* stateset, osg::NodeVisitor* nv);
|
||||||
|
|
||||||
META_Object(NifOsg, AlphaController)
|
META_Object(NifOsg, AlphaController)
|
||||||
};
|
};
|
||||||
|
|
||||||
class MaterialColorController : public osg::NodeCallback, public Controller, public StateSetController, public ValueInterpolator
|
class MaterialColorController : public SceneUtil::StateSetController, public Controller, public ValueInterpolator
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
Nif::Vector3KeyMapPtr mData;
|
Nif::Vector3KeyMapPtr mData;
|
||||||
|
@ -264,10 +255,10 @@ namespace NifOsg
|
||||||
|
|
||||||
META_Object(NifOsg, MaterialColorController)
|
META_Object(NifOsg, MaterialColorController)
|
||||||
|
|
||||||
virtual void operator() (osg::Node* node, osg::NodeVisitor* nv);
|
virtual void apply(osg::StateSet* stateset, osg::NodeVisitor* nv);
|
||||||
};
|
};
|
||||||
|
|
||||||
class FlipController : public osg::NodeCallback, public Controller, public StateSetController
|
class FlipController : public SceneUtil::StateSetController, public Controller
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
int mTexSlot;
|
int mTexSlot;
|
||||||
|
@ -281,7 +272,7 @@ namespace NifOsg
|
||||||
|
|
||||||
META_Object(NifOsg, FlipController)
|
META_Object(NifOsg, FlipController)
|
||||||
|
|
||||||
virtual void operator() (osg::Node* node, osg::NodeVisitor* nv);
|
virtual void apply(osg::StateSet *stateset, osg::NodeVisitor *nv);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ParticleSystemController : public osg::NodeCallback, public Controller
|
class ParticleSystemController : public osg::NodeCallback, public Controller
|
||||||
|
|
|
@ -719,13 +719,13 @@ namespace NifOsg
|
||||||
return skel;
|
return skel;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void applyNodeProperties(const Nif::Node *nifNode, osg::Node *applyTo, Resource::TextureManager* textureManager, std::map<int, int>& boundTextures, int animflags)
|
static void applyNodeProperties(const Nif::Node *nifNode, osg::Node *applyTo, SceneUtil::CompositeStateSetController* composite, Resource::TextureManager* textureManager, std::map<int, int>& boundTextures, int animflags)
|
||||||
{
|
{
|
||||||
const Nif::PropertyList& props = nifNode->props;
|
const Nif::PropertyList& props = nifNode->props;
|
||||||
for (size_t i = 0; i <props.length();++i)
|
for (size_t i = 0; i <props.length();++i)
|
||||||
{
|
{
|
||||||
if (!props[i].empty())
|
if (!props[i].empty())
|
||||||
handleProperty(props[i].getPtr(), applyTo, textureManager, boundTextures, animflags);
|
handleProperty(props[i].getPtr(), applyTo, composite, textureManager, boundTextures, animflags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -825,7 +825,9 @@ namespace NifOsg
|
||||||
transformNode->setNodeMask(0x1);
|
transformNode->setNodeMask(0x1);
|
||||||
}
|
}
|
||||||
|
|
||||||
applyNodeProperties(nifNode, transformNode, textureManager, boundTextures, animflags);
|
osg::ref_ptr<SceneUtil::CompositeStateSetController> composite = new SceneUtil::CompositeStateSetController;
|
||||||
|
|
||||||
|
applyNodeProperties(nifNode, transformNode, composite, textureManager, boundTextures, animflags);
|
||||||
|
|
||||||
if (nifNode->recType == Nif::RC_NiTriShape && !skipMeshes)
|
if (nifNode->recType == Nif::RC_NiTriShape && !skipMeshes)
|
||||||
{
|
{
|
||||||
|
@ -836,9 +838,12 @@ namespace NifOsg
|
||||||
handleSkinnedTriShape(triShape, transformNode, boundTextures, animflags);
|
handleSkinnedTriShape(triShape, transformNode, boundTextures, animflags);
|
||||||
|
|
||||||
if (!nifNode->controller.empty())
|
if (!nifNode->controller.empty())
|
||||||
handleMeshControllers(nifNode, transformNode, boundTextures, animflags);
|
handleMeshControllers(nifNode, composite, boundTextures, animflags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (composite->getNumControllers() > 0)
|
||||||
|
transformNode->addUpdateCallback(composite);
|
||||||
|
|
||||||
if(nifNode->recType == Nif::RC_NiAutoNormalParticles || nifNode->recType == Nif::RC_NiRotatingParticles)
|
if(nifNode->recType == Nif::RC_NiAutoNormalParticles || nifNode->recType == Nif::RC_NiRotatingParticles)
|
||||||
handleParticleSystem(nifNode, transformNode, animflags, particleflags, rootNode);
|
handleParticleSystem(nifNode, transformNode, animflags, particleflags, rootNode);
|
||||||
|
|
||||||
|
@ -866,7 +871,7 @@ namespace NifOsg
|
||||||
return transformNode;
|
return transformNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleMeshControllers(const Nif::Node *nifNode, osg::MatrixTransform *transformNode, const std::map<int, int> &boundTextures, int animflags)
|
static void handleMeshControllers(const Nif::Node *nifNode, SceneUtil::CompositeStateSetController* composite, const std::map<int, 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)
|
||||||
{
|
{
|
||||||
|
@ -881,8 +886,7 @@ namespace NifOsg
|
||||||
|
|
||||||
osg::ref_ptr<UVController> ctrl = new UVController(uvctrl->data.getPtr(), texUnits);
|
osg::ref_ptr<UVController> ctrl = new UVController(uvctrl->data.getPtr(), texUnits);
|
||||||
setupController(uvctrl, ctrl, animflags);
|
setupController(uvctrl, ctrl, animflags);
|
||||||
|
composite->addController(ctrl);
|
||||||
transformNode->addUpdateCallback(ctrl);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -915,8 +919,9 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleMaterialControllers(const Nif::Property *materialProperty, osg::Node* node, osg::StateSet *stateset, int animflags)
|
static void handleMaterialControllers(const Nif::Property *materialProperty, osg::Node* node, int animflags)
|
||||||
{
|
{
|
||||||
|
osg::ref_ptr<SceneUtil::CompositeStateSetController> composite = new SceneUtil::CompositeStateSetController;
|
||||||
for (Nif::ControllerPtr ctrl = materialProperty->controller; !ctrl.empty(); ctrl = ctrl->next)
|
for (Nif::ControllerPtr ctrl = materialProperty->controller; !ctrl.empty(); ctrl = ctrl->next)
|
||||||
{
|
{
|
||||||
if (!(ctrl->flags & Nif::NiNode::ControllerFlag_Active))
|
if (!(ctrl->flags & Nif::NiNode::ControllerFlag_Active))
|
||||||
|
@ -926,21 +931,23 @@ namespace NifOsg
|
||||||
const Nif::NiAlphaController* alphactrl = static_cast<const Nif::NiAlphaController*>(ctrl.getPtr());
|
const Nif::NiAlphaController* alphactrl = static_cast<const Nif::NiAlphaController*>(ctrl.getPtr());
|
||||||
osg::ref_ptr<AlphaController> ctrl(new AlphaController(alphactrl->data.getPtr()));
|
osg::ref_ptr<AlphaController> ctrl(new AlphaController(alphactrl->data.getPtr()));
|
||||||
setupController(alphactrl, ctrl, animflags);
|
setupController(alphactrl, ctrl, animflags);
|
||||||
node->addUpdateCallback(ctrl);
|
composite->addController(ctrl);
|
||||||
}
|
}
|
||||||
else if (ctrl->recType == Nif::RC_NiMaterialColorController)
|
else if (ctrl->recType == Nif::RC_NiMaterialColorController)
|
||||||
{
|
{
|
||||||
const Nif::NiMaterialColorController* matctrl = static_cast<const Nif::NiMaterialColorController*>(ctrl.getPtr());
|
const Nif::NiMaterialColorController* matctrl = static_cast<const Nif::NiMaterialColorController*>(ctrl.getPtr());
|
||||||
osg::ref_ptr<MaterialColorController> ctrl(new MaterialColorController(matctrl->data.getPtr()));
|
osg::ref_ptr<MaterialColorController> ctrl(new MaterialColorController(matctrl->data.getPtr()));
|
||||||
setupController(matctrl, ctrl, animflags);
|
setupController(matctrl, ctrl, animflags);
|
||||||
node->addUpdateCallback(ctrl);
|
composite->addController(ctrl);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
std::cerr << "Unexpected material controller " << ctrl->recType << std::endl;
|
std::cerr << "Unexpected material controller " << ctrl->recType << std::endl;
|
||||||
}
|
}
|
||||||
|
if (composite->getNumControllers() > 0)
|
||||||
|
node->addUpdateCallback(composite);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleTextureControllers(const Nif::Property *texProperty, osg::Node* node, Resource::TextureManager* textureManager, osg::StateSet *stateset, int animflags)
|
static void handleTextureControllers(const Nif::Property *texProperty, SceneUtil::CompositeStateSetController* composite, Resource::TextureManager* textureManager, osg::StateSet *stateset, int animflags)
|
||||||
{
|
{
|
||||||
for (Nif::ControllerPtr ctrl = texProperty->controller; !ctrl.empty(); ctrl = ctrl->next)
|
for (Nif::ControllerPtr ctrl = texProperty->controller; !ctrl.empty(); ctrl = ctrl->next)
|
||||||
{
|
{
|
||||||
|
@ -972,7 +979,7 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
osg::ref_ptr<FlipController> callback(new FlipController(flipctrl, textures));
|
osg::ref_ptr<FlipController> callback(new FlipController(flipctrl, textures));
|
||||||
setupController(ctrl.getPtr(), callback, animflags);
|
setupController(ctrl.getPtr(), callback, animflags);
|
||||||
node->addUpdateCallback(callback);
|
composite->addController(callback);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
std::cerr << "Unexpected texture controller " << ctrl->recName << std::endl;
|
std::cerr << "Unexpected texture controller " << ctrl->recName << std::endl;
|
||||||
|
@ -1419,7 +1426,7 @@ namespace NifOsg
|
||||||
|
|
||||||
|
|
||||||
static void handleProperty(const Nif::Property *property,
|
static void handleProperty(const Nif::Property *property,
|
||||||
osg::Node *node, Resource::TextureManager* textureManager, std::map<int, int>& boundTextures, int animflags)
|
osg::Node *node, SceneUtil::CompositeStateSetController* composite, Resource::TextureManager* textureManager, std::map<int, int>& boundTextures, int animflags)
|
||||||
{
|
{
|
||||||
osg::StateSet* stateset = node->getOrCreateStateSet();
|
osg::StateSet* stateset = node->getOrCreateStateSet();
|
||||||
|
|
||||||
|
@ -1594,7 +1601,7 @@ namespace NifOsg
|
||||||
stateset->setTextureAttributeAndModes(i, new osg::Texture2D, osg::StateAttribute::OFF);
|
stateset->setTextureAttributeAndModes(i, new osg::Texture2D, osg::StateAttribute::OFF);
|
||||||
boundTextures.erase(i);
|
boundTextures.erase(i);
|
||||||
}
|
}
|
||||||
handleTextureControllers(texprop, node, textureManager, stateset, animflags);
|
handleTextureControllers(texprop, composite, textureManager, stateset, animflags);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1646,7 +1653,7 @@ namespace NifOsg
|
||||||
mat->setShininess(osg::Material::FRONT_AND_BACK, matprop->data.glossiness);
|
mat->setShininess(osg::Material::FRONT_AND_BACK, matprop->data.glossiness);
|
||||||
|
|
||||||
if (!matprop->controller.empty())
|
if (!matprop->controller.empty())
|
||||||
handleMaterialControllers(matprop, node, stateset, animflags);
|
handleMaterialControllers(matprop, node, animflags);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,4 +28,47 @@ namespace SceneUtil
|
||||||
traverse(node, nv);
|
traverse(node, nv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StateSetController::StateSetController()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
StateSetController::StateSetController(const StateSetController ©, const osg::CopyOp ©op)
|
||||||
|
: osg::NodeCallback(copy, copyop)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void CompositeStateSetController::apply(osg::StateSet *stateset, osg::NodeVisitor *nv)
|
||||||
|
{
|
||||||
|
for (unsigned int i=0; i<mCtrls.size(); ++i)
|
||||||
|
mCtrls[i]->apply(stateset, nv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompositeStateSetController::setDefaults(osg::StateSet *stateset)
|
||||||
|
{
|
||||||
|
for (unsigned int i=0; i<mCtrls.size(); ++i)
|
||||||
|
mCtrls[i]->setDefaults(stateset);
|
||||||
|
}
|
||||||
|
|
||||||
|
CompositeStateSetController::CompositeStateSetController()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CompositeStateSetController::CompositeStateSetController(const CompositeStateSetController ©, const osg::CopyOp ©op)
|
||||||
|
: StateSetController(copy, copyop)
|
||||||
|
, mCtrls(copy.mCtrls)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int CompositeStateSetController::getNumControllers()
|
||||||
|
{
|
||||||
|
return mCtrls.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompositeStateSetController::addController(StateSetController *ctrl)
|
||||||
|
{
|
||||||
|
mCtrls.push_back(ctrl);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,16 +15,21 @@ 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 multiple StateSetControllers on the same Node as they will conflict - instead use the CompositeStateSetController.
|
||||||
class StateSetController : public osg::NodeCallback
|
class StateSetController : public osg::NodeCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
StateSetController();
|
||||||
|
StateSetController(const StateSetController& copy, const osg::CopyOp& copyop);
|
||||||
|
|
||||||
|
META_Object(SceneUtil, StateSetController)
|
||||||
|
|
||||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
|
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
|
||||||
|
|
||||||
protected:
|
|
||||||
/// Apply state - to override in derived classes
|
/// Apply state - to override in derived classes
|
||||||
/// @note Due to the double buffering approach you *have* to apply all state
|
/// @note Due to the double buffering approach you *have* to apply all state
|
||||||
/// even if it has not changed since the last frame.
|
/// even if it has not changed since the last frame.
|
||||||
virtual void apply(osg::StateSet* stateset, osg::NodeVisitor* nv) = 0;
|
virtual void apply(osg::StateSet* stateset, osg::NodeVisitor* nv) {}
|
||||||
|
|
||||||
/// Set default state - optionally override in derived classes
|
/// Set default state - optionally override in derived classes
|
||||||
/// @par May be used e.g. to allocate StateAttributes.
|
/// @par May be used e.g. to allocate StateAttributes.
|
||||||
|
@ -34,6 +39,28 @@ namespace SceneUtil
|
||||||
osg::ref_ptr<osg::StateSet> mStateSets[2];
|
osg::ref_ptr<osg::StateSet> mStateSets[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// @brief A variant of the StateSetController that can be made up of multiple controllers all controlling the same target.
|
||||||
|
class CompositeStateSetController : public StateSetController
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CompositeStateSetController();
|
||||||
|
CompositeStateSetController(const CompositeStateSetController& copy, const osg::CopyOp& copyop);
|
||||||
|
|
||||||
|
META_Object(SceneUtil, CompositeStateSetController)
|
||||||
|
|
||||||
|
unsigned int getNumControllers();
|
||||||
|
|
||||||
|
void addController(StateSetController* ctrl);
|
||||||
|
|
||||||
|
virtual void apply(osg::StateSet* stateset, osg::NodeVisitor* nv);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void setDefaults(osg::StateSet *stateset);
|
||||||
|
|
||||||
|
std::vector<osg::ref_ptr<StateSetController> > mCtrls;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue