From 9242e6d256601c220597ed9851e1eeac26e81001 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 22 Mar 2015 23:47:49 +0100 Subject: [PATCH] Avoid copying keyframes in controller instances --- components/nif/data.cpp | 37 +++++++++++++------ components/nif/data.hpp | 23 ++++++------ components/nif/nifkey.hpp | 7 ++++ components/nifosg/controller.cpp | 63 +++++++++++++++++--------------- components/nifosg/controller.hpp | 33 ++++++++--------- components/nifosg/nifloader.cpp | 17 +-------- components/nifosg/particle.cpp | 2 +- 7 files changed, 95 insertions(+), 87 deletions(-) diff --git a/components/nif/data.cpp b/components/nif/data.cpp index c4de1e1bf..1fef8d56f 100644 --- a/components/nif/data.cpp +++ b/components/nif/data.cpp @@ -115,18 +115,23 @@ void NiRotatingParticlesData::read(NIFStream *nif) void NiPosData::read(NIFStream *nif) { - mKeyList.read(nif); + mKeyList.reset(new Vector3KeyMap); + mKeyList->read(nif); } void NiUVData::read(NIFStream *nif) { 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) { - mKeyList.read(nif); + mKeyList.reset(new FloatKeyMap); + mKeyList->read(nif); } void NiPixelData::read(NIFStream *nif) @@ -163,7 +168,8 @@ void NiPixelData::read(NIFStream *nif) void NiColorData::read(NIFStream *nif) { - mKeyMap.read(nif); + mKeyMap.reset(new Vector4KeyMap); + mKeyMap->read(nif); } void NiVisData::read(NIFStream *nif) @@ -215,24 +221,31 @@ void NiMorphData::read(NIFStream *nif) mMorphs.resize(morphCount); 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); } } void NiKeyframeData::read(NIFStream *nif) { - mRotations.read(nif); - if(mRotations.mInterpolationType == mRotations.sXYZInterpolation) + mRotations.reset(new QuaternionKeyMap); + mRotations->read(nif); + if(mRotations->mInterpolationType == Vector3KeyMap::sXYZInterpolation) { //Chomp unused float nif->getFloat(); - mXRotations.read(nif, true); - mYRotations.read(nif, true); - mZRotations.read(nif, true); + mXRotations.reset(new FloatKeyMap); + mYRotations.reset(new FloatKeyMap); + mZRotations.reset(new FloatKeyMap); + mXRotations->read(nif, true); + mYRotations->read(nif, true); + mZRotations->read(nif, true); } - mTranslations.read(nif); - mScales.read(nif); + mTranslations.reset(new Vector3KeyMap); + mTranslations->read(nif); + mScales.reset(new FloatKeyMap); + mScales->read(nif); } } // Namespace diff --git a/components/nif/data.hpp b/components/nif/data.hpp index 3b1244831..702fbf313 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -78,7 +78,7 @@ public: class NiPosData : public Record { public: - Vector3KeyMap mKeyList; + Vector3KeyMapPtr mKeyList; void read(NIFStream *nif); }; @@ -86,7 +86,7 @@ public: class NiUVData : public Record { public: - FloatKeyMap mKeyList[4]; + FloatKeyMapPtr mKeyList[4]; void read(NIFStream *nif); }; @@ -94,7 +94,7 @@ public: class NiFloatData : public Record { public: - FloatKeyMap mKeyList; + FloatKeyMapPtr mKeyList; void read(NIFStream *nif); }; @@ -111,7 +111,7 @@ public: class NiColorData : public Record { public: - Vector4KeyMap mKeyMap; + Vector4KeyMapPtr mKeyMap; void read(NIFStream *nif); }; @@ -164,7 +164,7 @@ public: struct NiMorphData : public Record { struct MorphData { - FloatKeyMap mData; + FloatKeyMapPtr mKeyFrames; std::vector mVertices; }; std::vector mMorphs; @@ -175,14 +175,15 @@ struct NiMorphData : public Record struct NiKeyframeData : public Record { - QuaternionKeyMap mRotations; + QuaternionKeyMapPtr mRotations; - FloatKeyMap mXRotations; - FloatKeyMap mYRotations; - FloatKeyMap mZRotations; + // may be NULL + FloatKeyMapPtr mXRotations; + FloatKeyMapPtr mYRotations; + FloatKeyMapPtr mZRotations; - Vector3KeyMap mTranslations; - FloatKeyMap mScales; + Vector3KeyMapPtr mTranslations; + FloatKeyMapPtr mScales; void read(NIFStream *nif); }; diff --git a/components/nif/nifkey.hpp b/components/nif/nifkey.hpp index 98687a2f9..d702d0292 100644 --- a/components/nif/nifkey.hpp +++ b/components/nif/nifkey.hpp @@ -8,6 +8,8 @@ #include #include +#include + #include "niffile.hpp" namespace Nif @@ -146,5 +148,10 @@ typedef KeyMapT Vector3KeyMap; typedef KeyMapT Vector4KeyMap; typedef KeyMapT QuaternionKeyMap; +typedef boost::shared_ptr FloatKeyMapPtr; +typedef boost::shared_ptr Vector3KeyMapPtr; +typedef boost::shared_ptr Vector4KeyMapPtr; +typedef boost::shared_ptr QuaternionKeyMapPtr; + } // Namespace #endif //#ifndef OPENMW_COMPONENTS_NIF_NIFKEY_HPP diff --git a/components/nifosg/controller.cpp b/components/nifosg/controller.cpp index d61a8937a..88802f81e 100644 --- a/components/nifosg/controller.cpp +++ b/components/nifosg/controller.cpp @@ -77,18 +77,16 @@ KeyframeController::KeyframeController(const KeyframeController ©, const osg , mZRotations(copy.mZRotations) , mTranslations(copy.mTranslations) , mScales(copy.mScales) - , mNif(copy.mNif) { } -KeyframeController::KeyframeController(const Nif::NIFFilePtr &nif, const Nif::NiKeyframeData *data) - : mRotations(&data->mRotations) - , mXRotations(&data->mXRotations) - , mYRotations(&data->mYRotations) - , mZRotations(&data->mZRotations) - , mTranslations(&data->mTranslations) - , mScales(&data->mScales) - , mNif(nif) +KeyframeController::KeyframeController(const Nif::NiKeyframeData *data) + : mRotations(data->mRotations) + , mXRotations(data->mXRotations) + , mYRotations(data->mYRotations) + , mZRotations(data->mZRotations) + , mTranslations(data->mTranslations) + , mScales(data->mScales) { } @@ -127,9 +125,13 @@ osg::Quat KeyframeController::interpKey(const Nif::QuaternionKeyMap::MapType &ke osg::Quat KeyframeController::getXYZRotation(float time) const { - float xrot = interpKey(mXRotations->mKeys, time); - float yrot = interpKey(mYRotations->mKeys, time); - float zrot = interpKey(mZRotations->mKeys, time); + float xrot = 0, yrot = 0, zrot = 0; + if (mXRotations.get()) + 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 yr(yrot, osg::Vec3f(0,1,0)); 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 { - if(mTranslations->mKeys.size() > 0) + if(mTranslations.get() && mTranslations->mKeys.size() > 0) return interpKey(mTranslations->mKeys, time); return osg::Vec3f(); } @@ -156,12 +158,12 @@ void KeyframeController::operator() (osg::Node* node, osg::NodeVisitor* nv) Nif::Matrix3& rot = userdata->mRotationScale; bool setRot = false; - if(mRotations->mKeys.size() > 0) + if(mRotations.get() && !mRotations->mKeys.empty()) { mat.setRotate(interpKey(mRotations->mKeys, time)); 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)); setRot = true; @@ -179,17 +181,17 @@ void KeyframeController::operator() (osg::Node* node, osg::NodeVisitor* nv) for (int j=0;j<3;++j) 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; - if(mScales->mKeys.size() > 0) + if(mScales.get() && !mScales->mKeys.empty()) scale = interpKey(mScales->mKeys, time); for (int i=0;i<3;++i) for (int j=0;j<3;++j) mat(i,j) *= scale; - if(mTranslations->mKeys.size() > 0) + if(mTranslations.get() && !mTranslations->mKeys.empty()) mat.setTrans(interpKey(mTranslations->mKeys, time)); + trans->setMatrix(mat); } @@ -217,13 +219,14 @@ GeomMorpherController::GeomMorpherController() GeomMorpherController::GeomMorpherController(const GeomMorpherController ©, const osg::CopyOp ©op) : osg::Drawable::UpdateCallback(copy, copyop) , Controller(copy) - , mMorphs(copy.mMorphs) + , mKeyFrames(copy.mKeyFrames) { } GeomMorpherController::GeomMorpherController(const Nif::NiMorphData *data) - : mMorphs(data->mMorphs) { + for (unsigned int i=0; imMorphs.size(); ++i) + mKeyFrames.push_back(data->mMorphs[i].mKeyFrames); } 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 (mMorphs.size() <= 1) + if (mKeyFrames.size() <= 1) return; float input = getInputValue(nv); int i = 0; - for (std::vector::iterator it = mMorphs.begin()+1; it != mMorphs.end(); ++it,++i) + for (std::vector::iterator it = mKeyFrames.begin()+1; it != mKeyFrames.end(); ++it,++i) { float val = 0; - if (!it->mData.mKeys.empty()) - val = interpKey(it->mData.mKeys, input); + if (!(*it)->mKeys.empty()) + val = interpKey((*it)->mKeys, input); val = std::max(0.f, std::min(1.f, val)); morphGeom->setWeight(i, val); @@ -281,10 +284,10 @@ void UVController::operator()(osg::Node* node, osg::NodeVisitor* nv) { osg::StateSet* stateset = node->getStateSet(); float value = getInputValue(nv); - float uTrans = interpKey(mUTrans.mKeys, value, 0.0f); - float vTrans = interpKey(mVTrans.mKeys, value, 0.0f); - float uScale = interpKey(mUScale.mKeys, value, 1.0f); - float vScale = interpKey(mVScale.mKeys, value, 1.0f); + float uTrans = interpKey(mUTrans->mKeys, value, 0.0f); + float vTrans = interpKey(mVTrans->mKeys, value, 0.0f); + float uScale = interpKey(mUScale->mKeys, value, 1.0f); + float vScale = interpKey(mVScale->mKeys, value, 1.0f); osg::Matrixf mat = osg::Matrixf::scale(uScale, vScale, 1); mat.setTrans(uTrans, vTrans, 0); @@ -360,7 +363,7 @@ void AlphaController::operator () (osg::Node* node, osg::NodeVisitor* nv) if (hasInput()) { osg::StateSet* stateset = node->getStateSet(); - float value = interpKey(mData.mKeys, getInputValue(nv)); + float value = interpKey(mData->mKeys, getInputValue(nv)); osg::Material* mat = dynamic_cast(stateset->getAttribute(osg::StateAttribute::MATERIAL)); if (mat) { @@ -392,7 +395,7 @@ void MaterialColorController::operator() (osg::Node* node, osg::NodeVisitor* nv) if (hasInput()) { 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(stateset->getAttribute(osg::StateAttribute::MATERIAL)); if (mat) { diff --git a/components/nifosg/controller.hpp b/components/nifosg/controller.hpp index fb24fb518..eb9b95a81 100644 --- a/components/nifosg/controller.hpp +++ b/components/nifosg/controller.hpp @@ -135,20 +135,20 @@ namespace NifOsg virtual void update(osg::NodeVisitor* nv, osg::Drawable* drawable); private: - std::vector mMorphs; + std::vector mKeyFrames; }; class KeyframeController : public osg::NodeCallback, public Controller, public ValueInterpolator { private: - const Nif::QuaternionKeyMap* mRotations; - const Nif::FloatKeyMap* mXRotations; - const Nif::FloatKeyMap* mYRotations; - const Nif::FloatKeyMap* mZRotations; - const Nif::Vector3KeyMap* mTranslations; - const Nif::FloatKeyMap* mScales; - // TODO: we don't need to keep the whole NIF around, just change the key maps to Referenced - Nif::NIFFilePtr mNif; // Hold a SharedPtr to make sure key lists stay valid + Nif::QuaternionKeyMapPtr mRotations; + + Nif::FloatKeyMapPtr mXRotations; + Nif::FloatKeyMapPtr mYRotations; + Nif::FloatKeyMapPtr mZRotations; + + Nif::Vector3KeyMapPtr mTranslations; + Nif::FloatKeyMapPtr mScales; using ValueInterpolator::interpKey; @@ -158,8 +158,7 @@ namespace NifOsg osg::Quat getXYZRotation(float time) const; public: - /// @note The NiKeyFrameData must be valid as long as this KeyframeController exists. - KeyframeController(const Nif::NIFFilePtr& nif, const Nif::NiKeyframeData *data); + KeyframeController(const Nif::NiKeyframeData *data); KeyframeController(); KeyframeController(const KeyframeController& copy, const osg::CopyOp& copyop); @@ -183,10 +182,10 @@ namespace NifOsg virtual void operator() (osg::Node*, osg::NodeVisitor*); private: - Nif::FloatKeyMap mUTrans; - Nif::FloatKeyMap mVTrans; - Nif::FloatKeyMap mUScale; - Nif::FloatKeyMap mVScale; + Nif::FloatKeyMapPtr mUTrans; + Nif::FloatKeyMapPtr mVTrans; + Nif::FloatKeyMapPtr mUScale; + Nif::FloatKeyMapPtr mVScale; std::set mTextureUnits; }; @@ -210,7 +209,7 @@ namespace NifOsg class AlphaController : public osg::NodeCallback, public Controller, public ValueInterpolator { private: - Nif::FloatKeyMap mData; + Nif::FloatKeyMapPtr mData; public: AlphaController(const Nif::NiFloatData *data); @@ -225,7 +224,7 @@ namespace NifOsg class MaterialColorController : public osg::NodeCallback, public Controller, public ValueInterpolator { private: - Nif::Vector3KeyMap mData; + Nif::Vector3KeyMapPtr mData; public: MaterialColorController(const Nif::NiPosData *data); diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index edc011c54..1e69ee4f5 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -454,7 +454,6 @@ namespace NifOsg 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) { if (!(ctrl->flags & Nif::NiNode::ControllerFlag_Active)) @@ -464,24 +463,10 @@ namespace NifOsg const Nif::NiKeyframeController *key = static_cast(ctrl.getPtr()); if(!key->data.empty()) { - if (seenKeyframeCtrl) - { - 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 callback(new KeyframeController(mNif, key->data.getPtr())); + osg::ref_ptr callback(new KeyframeController(key->data.getPtr())); setupController(key, callback, animflags); transformNode->addUpdateCallback(callback); - - seenKeyframeCtrl = true; } } else if (ctrl->recType == Nif::RC_NiVisController) diff --git a/components/nifosg/particle.cpp b/components/nifosg/particle.cpp index 16c2b692c..25970c862 100644 --- a/components/nifosg/particle.cpp +++ b/components/nifosg/particle.cpp @@ -142,7 +142,7 @@ ParticleColorAffector::ParticleColorAffector(const ParticleColorAffector ©, void ParticleColorAffector::operate(osgParticle::Particle* particle, double /* dt */) { float time = static_cast(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)); }