Avoid copying keyframes in controller instances

c++11
scrawl 10 years ago
parent 2db5df77f0
commit 9242e6d256

@ -115,18 +115,23 @@ void NiRotatingParticlesData::read(NIFStream *nif)
void NiPosData::read(NIFStream *nif) void NiPosData::read(NIFStream *nif)
{ {
mKeyList.read(nif); mKeyList.reset(new Vector3KeyMap);
mKeyList->read(nif);
} }
void NiUVData::read(NIFStream *nif) void NiUVData::read(NIFStream *nif)
{ {
for(int i = 0;i < 4;i++) for(int i = 0;i < 4;i++)
mKeyList[i].read(nif); {
mKeyList[i].reset(new FloatKeyMap);
mKeyList[i]->read(nif);
}
} }
void NiFloatData::read(NIFStream *nif) void NiFloatData::read(NIFStream *nif)
{ {
mKeyList.read(nif); mKeyList.reset(new FloatKeyMap);
mKeyList->read(nif);
} }
void NiPixelData::read(NIFStream *nif) void NiPixelData::read(NIFStream *nif)
@ -163,7 +168,8 @@ void NiPixelData::read(NIFStream *nif)
void NiColorData::read(NIFStream *nif) void NiColorData::read(NIFStream *nif)
{ {
mKeyMap.read(nif); mKeyMap.reset(new Vector4KeyMap);
mKeyMap->read(nif);
} }
void NiVisData::read(NIFStream *nif) void NiVisData::read(NIFStream *nif)
@ -215,24 +221,31 @@ void NiMorphData::read(NIFStream *nif)
mMorphs.resize(morphCount); mMorphs.resize(morphCount);
for(int i = 0;i < morphCount;i++) for(int i = 0;i < morphCount;i++)
{ {
mMorphs[i].mData.read(nif, true); mMorphs[i].mKeyFrames.reset(new FloatKeyMap);
mMorphs[i].mKeyFrames->read(nif, true);
nif->getVector3s(mMorphs[i].mVertices, vertCount); nif->getVector3s(mMorphs[i].mVertices, vertCount);
} }
} }
void NiKeyframeData::read(NIFStream *nif) void NiKeyframeData::read(NIFStream *nif)
{ {
mRotations.read(nif); mRotations.reset(new QuaternionKeyMap);
if(mRotations.mInterpolationType == mRotations.sXYZInterpolation) mRotations->read(nif);
if(mRotations->mInterpolationType == Vector3KeyMap::sXYZInterpolation)
{ {
//Chomp unused float //Chomp unused float
nif->getFloat(); nif->getFloat();
mXRotations.read(nif, true); mXRotations.reset(new FloatKeyMap);
mYRotations.read(nif, true); mYRotations.reset(new FloatKeyMap);
mZRotations.read(nif, true); mZRotations.reset(new FloatKeyMap);
mXRotations->read(nif, true);
mYRotations->read(nif, true);
mZRotations->read(nif, true);
} }
mTranslations.read(nif); mTranslations.reset(new Vector3KeyMap);
mScales.read(nif); mTranslations->read(nif);
mScales.reset(new FloatKeyMap);
mScales->read(nif);
} }
} // Namespace } // Namespace

@ -78,7 +78,7 @@ public:
class NiPosData : public Record class NiPosData : public Record
{ {
public: public:
Vector3KeyMap mKeyList; Vector3KeyMapPtr mKeyList;
void read(NIFStream *nif); void read(NIFStream *nif);
}; };
@ -86,7 +86,7 @@ public:
class NiUVData : public Record class NiUVData : public Record
{ {
public: public:
FloatKeyMap mKeyList[4]; FloatKeyMapPtr mKeyList[4];
void read(NIFStream *nif); void read(NIFStream *nif);
}; };
@ -94,7 +94,7 @@ public:
class NiFloatData : public Record class NiFloatData : public Record
{ {
public: public:
FloatKeyMap mKeyList; FloatKeyMapPtr mKeyList;
void read(NIFStream *nif); void read(NIFStream *nif);
}; };
@ -111,7 +111,7 @@ public:
class NiColorData : public Record class NiColorData : public Record
{ {
public: public:
Vector4KeyMap mKeyMap; Vector4KeyMapPtr mKeyMap;
void read(NIFStream *nif); void read(NIFStream *nif);
}; };
@ -164,7 +164,7 @@ public:
struct NiMorphData : public Record struct NiMorphData : public Record
{ {
struct MorphData { struct MorphData {
FloatKeyMap mData; FloatKeyMapPtr mKeyFrames;
std::vector<osg::Vec3f> mVertices; std::vector<osg::Vec3f> mVertices;
}; };
std::vector<MorphData> mMorphs; std::vector<MorphData> mMorphs;
@ -175,14 +175,15 @@ struct NiMorphData : public Record
struct NiKeyframeData : public Record struct NiKeyframeData : public Record
{ {
QuaternionKeyMap mRotations; QuaternionKeyMapPtr mRotations;
FloatKeyMap mXRotations; // may be NULL
FloatKeyMap mYRotations; FloatKeyMapPtr mXRotations;
FloatKeyMap mZRotations; FloatKeyMapPtr mYRotations;
FloatKeyMapPtr mZRotations;
Vector3KeyMap mTranslations; Vector3KeyMapPtr mTranslations;
FloatKeyMap mScales; FloatKeyMapPtr mScales;
void read(NIFStream *nif); void read(NIFStream *nif);
}; };

@ -8,6 +8,8 @@
#include <sstream> #include <sstream>
#include <map> #include <map>
#include <boost/shared_ptr.hpp>
#include "niffile.hpp" #include "niffile.hpp"
namespace Nif namespace Nif
@ -146,5 +148,10 @@ typedef KeyMapT<osg::Vec3f,&NIFStream::getVector3> Vector3KeyMap;
typedef KeyMapT<osg::Vec4f,&NIFStream::getVector4> Vector4KeyMap; typedef KeyMapT<osg::Vec4f,&NIFStream::getVector4> Vector4KeyMap;
typedef KeyMapT<osg::Quat,&NIFStream::getQuaternion> QuaternionKeyMap; typedef KeyMapT<osg::Quat,&NIFStream::getQuaternion> QuaternionKeyMap;
typedef boost::shared_ptr<FloatKeyMap> FloatKeyMapPtr;
typedef boost::shared_ptr<Vector3KeyMap> Vector3KeyMapPtr;
typedef boost::shared_ptr<Vector4KeyMap> Vector4KeyMapPtr;
typedef boost::shared_ptr<QuaternionKeyMap> QuaternionKeyMapPtr;
} // Namespace } // Namespace
#endif //#ifndef OPENMW_COMPONENTS_NIF_NIFKEY_HPP #endif //#ifndef OPENMW_COMPONENTS_NIF_NIFKEY_HPP

@ -77,18 +77,16 @@ KeyframeController::KeyframeController(const KeyframeController &copy, const osg
, mZRotations(copy.mZRotations) , mZRotations(copy.mZRotations)
, mTranslations(copy.mTranslations) , mTranslations(copy.mTranslations)
, mScales(copy.mScales) , mScales(copy.mScales)
, mNif(copy.mNif)
{ {
} }
KeyframeController::KeyframeController(const Nif::NIFFilePtr &nif, const Nif::NiKeyframeData *data) KeyframeController::KeyframeController(const Nif::NiKeyframeData *data)
: mRotations(&data->mRotations) : mRotations(data->mRotations)
, mXRotations(&data->mXRotations) , mXRotations(data->mXRotations)
, mYRotations(&data->mYRotations) , mYRotations(data->mYRotations)
, mZRotations(&data->mZRotations) , mZRotations(data->mZRotations)
, mTranslations(&data->mTranslations) , mTranslations(data->mTranslations)
, mScales(&data->mScales) , mScales(data->mScales)
, mNif(nif)
{ {
} }
@ -127,9 +125,13 @@ osg::Quat KeyframeController::interpKey(const Nif::QuaternionKeyMap::MapType &ke
osg::Quat KeyframeController::getXYZRotation(float time) const osg::Quat KeyframeController::getXYZRotation(float time) const
{ {
float xrot = interpKey(mXRotations->mKeys, time); float xrot = 0, yrot = 0, zrot = 0;
float yrot = interpKey(mYRotations->mKeys, time); if (mXRotations.get())
float zrot = interpKey(mZRotations->mKeys, time); xrot = interpKey(mXRotations->mKeys, time);
if (mYRotations.get())
yrot = interpKey(mYRotations->mKeys, time);
if (mZRotations.get())
zrot = interpKey(mZRotations->mKeys, time);
osg::Quat xr(xrot, osg::Vec3f(1,0,0)); osg::Quat xr(xrot, osg::Vec3f(1,0,0));
osg::Quat yr(yrot, osg::Vec3f(0,1,0)); osg::Quat yr(yrot, osg::Vec3f(0,1,0));
osg::Quat zr(zrot, osg::Vec3f(0,0,1)); osg::Quat zr(zrot, osg::Vec3f(0,0,1));
@ -138,7 +140,7 @@ osg::Quat KeyframeController::getXYZRotation(float time) const
osg::Vec3f KeyframeController::getTranslation(float time) const osg::Vec3f KeyframeController::getTranslation(float time) const
{ {
if(mTranslations->mKeys.size() > 0) if(mTranslations.get() && mTranslations->mKeys.size() > 0)
return interpKey(mTranslations->mKeys, time); return interpKey(mTranslations->mKeys, time);
return osg::Vec3f(); return osg::Vec3f();
} }
@ -156,12 +158,12 @@ void KeyframeController::operator() (osg::Node* node, osg::NodeVisitor* nv)
Nif::Matrix3& rot = userdata->mRotationScale; Nif::Matrix3& rot = userdata->mRotationScale;
bool setRot = false; bool setRot = false;
if(mRotations->mKeys.size() > 0) if(mRotations.get() && !mRotations->mKeys.empty())
{ {
mat.setRotate(interpKey(mRotations->mKeys, time)); mat.setRotate(interpKey(mRotations->mKeys, time));
setRot = true; setRot = true;
} }
else if (!mXRotations->mKeys.empty() || !mYRotations->mKeys.empty() || !mZRotations->mKeys.empty()) else if (mXRotations.get() || mYRotations.get() || mZRotations.get())
{ {
mat.setRotate(getXYZRotation(time)); mat.setRotate(getXYZRotation(time));
setRot = true; setRot = true;
@ -179,17 +181,17 @@ void KeyframeController::operator() (osg::Node* node, osg::NodeVisitor* nv)
for (int j=0;j<3;++j) for (int j=0;j<3;++j)
rot.mValues[i][j] = mat(j,i); // NB column/row major difference rot.mValues[i][j] = mat(j,i); // NB column/row major difference
// let's hope no one's using multiple KeyframeControllers on the same node (not that would make any sense...)
float& scale = userdata->mScale; float& scale = userdata->mScale;
if(mScales->mKeys.size() > 0) if(mScales.get() && !mScales->mKeys.empty())
scale = interpKey(mScales->mKeys, time); scale = interpKey(mScales->mKeys, time);
for (int i=0;i<3;++i) for (int i=0;i<3;++i)
for (int j=0;j<3;++j) for (int j=0;j<3;++j)
mat(i,j) *= scale; mat(i,j) *= scale;
if(mTranslations->mKeys.size() > 0) if(mTranslations.get() && !mTranslations->mKeys.empty())
mat.setTrans(interpKey(mTranslations->mKeys, time)); mat.setTrans(interpKey(mTranslations->mKeys, time));
trans->setMatrix(mat); trans->setMatrix(mat);
} }
@ -217,13 +219,14 @@ GeomMorpherController::GeomMorpherController()
GeomMorpherController::GeomMorpherController(const GeomMorpherController &copy, const osg::CopyOp &copyop) GeomMorpherController::GeomMorpherController(const GeomMorpherController &copy, const osg::CopyOp &copyop)
: osg::Drawable::UpdateCallback(copy, copyop) : osg::Drawable::UpdateCallback(copy, copyop)
, Controller(copy) , Controller(copy)
, mMorphs(copy.mMorphs) , mKeyFrames(copy.mKeyFrames)
{ {
} }
GeomMorpherController::GeomMorpherController(const Nif::NiMorphData *data) GeomMorpherController::GeomMorpherController(const Nif::NiMorphData *data)
: mMorphs(data->mMorphs)
{ {
for (unsigned int i=0; i<data->mMorphs.size(); ++i)
mKeyFrames.push_back(data->mMorphs[i].mKeyFrames);
} }
void GeomMorpherController::update(osg::NodeVisitor *nv, osg::Drawable *drawable) void GeomMorpherController::update(osg::NodeVisitor *nv, osg::Drawable *drawable)
@ -233,15 +236,15 @@ void GeomMorpherController::update(osg::NodeVisitor *nv, osg::Drawable *drawable
{ {
if (hasInput()) if (hasInput())
{ {
if (mMorphs.size() <= 1) if (mKeyFrames.size() <= 1)
return; return;
float input = getInputValue(nv); float input = getInputValue(nv);
int i = 0; int i = 0;
for (std::vector<Nif::NiMorphData::MorphData>::iterator it = mMorphs.begin()+1; it != mMorphs.end(); ++it,++i) for (std::vector<Nif::FloatKeyMapPtr>::iterator it = mKeyFrames.begin()+1; it != mKeyFrames.end(); ++it,++i)
{ {
float val = 0; float val = 0;
if (!it->mData.mKeys.empty()) if (!(*it)->mKeys.empty())
val = interpKey(it->mData.mKeys, input); val = interpKey((*it)->mKeys, input);
val = std::max(0.f, std::min(1.f, val)); val = std::max(0.f, std::min(1.f, val));
morphGeom->setWeight(i, val); morphGeom->setWeight(i, val);
@ -281,10 +284,10 @@ void UVController::operator()(osg::Node* node, osg::NodeVisitor* nv)
{ {
osg::StateSet* stateset = node->getStateSet(); osg::StateSet* stateset = node->getStateSet();
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);
float uScale = interpKey(mUScale.mKeys, value, 1.0f); float uScale = interpKey(mUScale->mKeys, value, 1.0f);
float vScale = interpKey(mVScale.mKeys, value, 1.0f); float vScale = interpKey(mVScale->mKeys, value, 1.0f);
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);
@ -360,7 +363,7 @@ void AlphaController::operator () (osg::Node* node, osg::NodeVisitor* nv)
if (hasInput()) if (hasInput())
{ {
osg::StateSet* stateset = node->getStateSet(); osg::StateSet* stateset = node->getStateSet();
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 = dynamic_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
if (mat) if (mat)
{ {
@ -392,7 +395,7 @@ void MaterialColorController::operator() (osg::Node* node, osg::NodeVisitor* nv)
if (hasInput()) if (hasInput())
{ {
osg::StateSet* stateset = node->getStateSet(); osg::StateSet* stateset = node->getStateSet();
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 = dynamic_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
if (mat) if (mat)
{ {

@ -135,20 +135,20 @@ namespace NifOsg
virtual void update(osg::NodeVisitor* nv, osg::Drawable* drawable); virtual void update(osg::NodeVisitor* nv, osg::Drawable* drawable);
private: private:
std::vector<Nif::NiMorphData::MorphData> mMorphs; std::vector<Nif::FloatKeyMapPtr> mKeyFrames;
}; };
class KeyframeController : public osg::NodeCallback, public Controller, public ValueInterpolator class KeyframeController : public osg::NodeCallback, public Controller, public ValueInterpolator
{ {
private: private:
const Nif::QuaternionKeyMap* mRotations; Nif::QuaternionKeyMapPtr mRotations;
const Nif::FloatKeyMap* mXRotations;
const Nif::FloatKeyMap* mYRotations; Nif::FloatKeyMapPtr mXRotations;
const Nif::FloatKeyMap* mZRotations; Nif::FloatKeyMapPtr mYRotations;
const Nif::Vector3KeyMap* mTranslations; Nif::FloatKeyMapPtr mZRotations;
const Nif::FloatKeyMap* mScales;
// TODO: we don't need to keep the whole NIF around, just change the key maps to Referenced Nif::Vector3KeyMapPtr mTranslations;
Nif::NIFFilePtr mNif; // Hold a SharedPtr to make sure key lists stay valid Nif::FloatKeyMapPtr mScales;
using ValueInterpolator::interpKey; using ValueInterpolator::interpKey;
@ -158,8 +158,7 @@ namespace NifOsg
osg::Quat getXYZRotation(float time) const; osg::Quat getXYZRotation(float time) const;
public: public:
/// @note The NiKeyFrameData must be valid as long as this KeyframeController exists. KeyframeController(const Nif::NiKeyframeData *data);
KeyframeController(const Nif::NIFFilePtr& nif, const Nif::NiKeyframeData *data);
KeyframeController(); KeyframeController();
KeyframeController(const KeyframeController& copy, const osg::CopyOp& copyop); KeyframeController(const KeyframeController& copy, const osg::CopyOp& copyop);
@ -183,10 +182,10 @@ namespace NifOsg
virtual void operator() (osg::Node*, osg::NodeVisitor*); virtual void operator() (osg::Node*, osg::NodeVisitor*);
private: private:
Nif::FloatKeyMap mUTrans; Nif::FloatKeyMapPtr mUTrans;
Nif::FloatKeyMap mVTrans; Nif::FloatKeyMapPtr mVTrans;
Nif::FloatKeyMap mUScale; Nif::FloatKeyMapPtr mUScale;
Nif::FloatKeyMap mVScale; Nif::FloatKeyMapPtr mVScale;
std::set<int> mTextureUnits; std::set<int> mTextureUnits;
}; };
@ -210,7 +209,7 @@ namespace NifOsg
class AlphaController : public osg::NodeCallback, public Controller, public ValueInterpolator class AlphaController : public osg::NodeCallback, public Controller, public ValueInterpolator
{ {
private: private:
Nif::FloatKeyMap mData; Nif::FloatKeyMapPtr mData;
public: public:
AlphaController(const Nif::NiFloatData *data); AlphaController(const Nif::NiFloatData *data);
@ -225,7 +224,7 @@ namespace NifOsg
class MaterialColorController : public osg::NodeCallback, public Controller, public ValueInterpolator class MaterialColorController : public osg::NodeCallback, public Controller, public ValueInterpolator
{ {
private: private:
Nif::Vector3KeyMap mData; Nif::Vector3KeyMapPtr mData;
public: public:
MaterialColorController(const Nif::NiPosData *data); MaterialColorController(const Nif::NiPosData *data);

@ -454,7 +454,6 @@ namespace NifOsg
void Loader::handleNodeControllers(const Nif::Node* nifNode, osg::MatrixTransform* transformNode, int animflags) void Loader::handleNodeControllers(const Nif::Node* nifNode, osg::MatrixTransform* transformNode, int animflags)
{ {
bool seenKeyframeCtrl = false;
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next) for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
{ {
if (!(ctrl->flags & Nif::NiNode::ControllerFlag_Active)) if (!(ctrl->flags & Nif::NiNode::ControllerFlag_Active))
@ -464,24 +463,10 @@ namespace NifOsg
const Nif::NiKeyframeController *key = static_cast<const Nif::NiKeyframeController*>(ctrl.getPtr()); const Nif::NiKeyframeController *key = static_cast<const Nif::NiKeyframeController*>(ctrl.getPtr());
if(!key->data.empty()) if(!key->data.empty())
{ {
if (seenKeyframeCtrl) osg::ref_ptr<KeyframeController> callback(new KeyframeController(key->data.getPtr()));
{
std::cerr << "Warning: multiple KeyframeControllers on the same node" << std::endl;
continue;
}
// build the rotation part manually to avoid issues caused by scaling
osg::Matrixf mat;
for (int i=0;i<3;++i)
for (int j=0;j<3;++j)
mat(j,i) = nifNode->trafo.rotation.mValues[i][j];
osg::ref_ptr<KeyframeController> callback(new KeyframeController(mNif, key->data.getPtr()));
setupController(key, callback, animflags); setupController(key, callback, animflags);
transformNode->addUpdateCallback(callback); transformNode->addUpdateCallback(callback);
seenKeyframeCtrl = true;
} }
} }
else if (ctrl->recType == Nif::RC_NiVisController) else if (ctrl->recType == Nif::RC_NiVisController)

@ -142,7 +142,7 @@ ParticleColorAffector::ParticleColorAffector(const ParticleColorAffector &copy,
void ParticleColorAffector::operate(osgParticle::Particle* particle, double /* dt */) void ParticleColorAffector::operate(osgParticle::Particle* particle, double /* dt */)
{ {
float time = static_cast<float>(particle->getAge()/particle->getLifeTime()); float time = static_cast<float>(particle->getAge()/particle->getLifeTime());
osg::Vec4f color = interpKey(mData.mKeyMap.mKeys, time, osg::Vec4f(1,1,1,1)); osg::Vec4f color = interpKey(mData.mKeyMap->mKeys, time, osg::Vec4f(1,1,1,1));
particle->setColorRange(osgParticle::rangev4(color, color)); particle->setColorRange(osgParticle::rangev4(color, color));
} }

Loading…
Cancel
Save