diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index bb00791b15..9a0f08f39c 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -113,7 +113,7 @@ namespace Nif void NiMaterialColorController::read(NIFStream *nif) { - NiSingleInterpController::read(nif); + NiPoint3InterpController::read(nif); // Two bits that correspond to the controlled material color. // 00: Ambient // 01: Diffuse @@ -129,7 +129,7 @@ namespace Nif void NiMaterialColorController::post(NIFFile *nif) { - NiSingleInterpController::post(nif); + NiPoint3InterpController::post(nif); mData.post(nif); } @@ -241,16 +241,16 @@ namespace Nif { NiInterpController::read(nif); if (nif->getVersion() >= NIFFile::NIFVersion::VER_OB_OLD) - /*bool updateNormals = !!*/nif->getUShort(); - data.read(nif); + mUpdateNormals = nif->getUShort() & 1; + mData.read(nif); if (nif->getVersion() >= NIFFile::NIFVersion::VER_MW) { - /*bool alwaysActive = */nif->getChar(); // Always 0 + mAlwaysActive = nif->getChar(); if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,106)) { if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB) { - interpolators.read(nif); + mInterpolators.read(nif); if (nif->getVersion() >= NIFStream::generateVersion(10,2,0,0) && nif->getBethVersion() > 9) { unsigned int numUnknown = nif->getUInt(); @@ -259,9 +259,16 @@ namespace Nif } else { - // TODO: handle weighted interpolators - unsigned int numInterps = nif->getUInt(); - nif->skip(8 * numInterps); + std::vector interpolators; + size_t numInterps = nif->getUInt(); + interpolators.resize(numInterps); + mWeights.resize(numInterps); + for (size_t i = 0; i < numInterps; i++) + { + interpolators[i].read(nif); + mWeights[i] = nif->getFloat(); + } + mInterpolators = interpolators; } } } @@ -270,8 +277,8 @@ namespace Nif void NiGeomMorpherController::post(NIFFile *nif) { NiInterpController::post(nif); - data.post(nif); - interpolators.post(nif); + mData.post(nif); + mInterpolators.post(nif); } void NiVisController::read(NIFStream *nif) diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index 44a3bcf427..07d35efa50 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -47,6 +47,15 @@ struct NiSingleInterpController : public NiInterpController void post(NIFFile* nif) override; }; +// Base class for controllers that use a NiFloatInterpolator to animate their target. +struct NiFloatInterpController : public NiSingleInterpController { }; + +// Ditto for NiBoolInterpolator. +struct NiBoolInterpController : public NiSingleInterpController { }; + +// Ditto for NiPoint3Interpolator. +struct NiPoint3InterpController : public NiSingleInterpController { }; + struct NiParticleSystemController : public Controller { enum BSPArrayController { @@ -106,7 +115,7 @@ struct NiParticleSystemController : public Controller }; using NiBSPArrayController = NiParticleSystemController; -struct NiMaterialColorController : public NiSingleInterpController +struct NiMaterialColorController : public NiPoint3InterpController { NiPosDataPtr mData; unsigned int mTargetColor; @@ -172,12 +181,6 @@ struct NiMultiTargetTransformController : public NiInterpController void post(NIFFile *nif) override; }; -// Base class for controllers that use a NiFloatInterpolator to animate their target. -struct NiFloatInterpController : public NiSingleInterpController { }; - -// Ditto for NiBoolInterpolator. -struct NiBoolInterpController : public NiSingleInterpController { }; - struct NiAlphaController : public NiFloatInterpController { NiFloatDataPtr mData; @@ -196,8 +199,11 @@ struct NiRollController : public NiSingleInterpController struct NiGeomMorpherController : public NiInterpController { - NiMorphDataPtr data; - NiFloatInterpolatorList interpolators; + bool mUpdateNormals{false}; + bool mAlwaysActive{false}; + NiMorphDataPtr mData; + NiInterpolatorList mInterpolators; + std::vector mWeights; void read(NIFStream *nif) override; void post(NIFFile *nif) override; diff --git a/components/nif/recordptr.hpp b/components/nif/recordptr.hpp index e98fe89cab..f9c0f32cf3 100644 --- a/components/nif/recordptr.hpp +++ b/components/nif/recordptr.hpp @@ -152,7 +152,6 @@ struct bhkSerializable; struct hkPackedNiTriStripsData; struct NiAccumulator; struct NiInterpolator; -struct NiFloatInterpolator; using NodePtr = RecordPtrT; using ExtraPtr = RecordPtrT; @@ -188,7 +187,7 @@ using NodeList = RecordListT; using PropertyList = RecordListT; using ExtraList = RecordListT; using NiSourceTextureList = RecordListT; -using NiFloatInterpolatorList = RecordListT; +using NiInterpolatorList = RecordListT; using NiTriStripsDataList = RecordListT; using bhkShapeList = RecordListT; using bhkSerializableList = RecordListT; diff --git a/components/nifosg/controller.cpp b/components/nifosg/controller.cpp index 280940dc40..5403a29ab2 100644 --- a/components/nifosg/controller.cpp +++ b/components/nifosg/controller.cpp @@ -196,26 +196,31 @@ GeomMorpherController::GeomMorpherController(const GeomMorpherController ©, : Controller(copy) , SceneUtil::NodeCallback(copy, copyop) , mKeyFrames(copy.mKeyFrames) + , mWeights(copy.mWeights) { } GeomMorpherController::GeomMorpherController(const Nif::NiGeomMorpherController* ctrl) { - if (ctrl->interpolators.length() == 0) + if (ctrl->mInterpolators.length() == 0) { - if (ctrl->data.empty()) - return; - for (const auto& morph : ctrl->data->mMorphs) - mKeyFrames.emplace_back(morph.mKeyFrames); + if (!ctrl->mData.empty()) + { + for (const auto& morph : ctrl->mData->mMorphs) + mKeyFrames.emplace_back(morph.mKeyFrames); + } + return; } - else + + mKeyFrames.resize(ctrl->mInterpolators.length()); + mWeights = ctrl->mWeights; + + for (size_t i = 0; i < ctrl->mInterpolators.length(); ++i) { - for (size_t i = 0; i < ctrl->interpolators.length(); ++i) + if (!ctrl->mInterpolators[i].empty() && ctrl->mInterpolators[i]->recType == Nif::RC_NiFloatInterpolator) { - if (!ctrl->interpolators[i].empty()) - mKeyFrames.emplace_back(ctrl->interpolators[i].getPtr()); - else - mKeyFrames.emplace_back(); + auto interpolator = static_cast(ctrl->mInterpolators[i].getPtr()); + mKeyFrames[i] = FloatInterpolator(interpolator); } } } @@ -227,12 +232,16 @@ void GeomMorpherController::operator()(SceneUtil::MorphGeometry* node, osg::Node if (mKeyFrames.size() <= 1) return; float input = getInputValue(nv); - int i = 1; + size_t i = 1; for (std::vector::iterator it = mKeyFrames.begin()+1; it != mKeyFrames.end(); ++it,++i) { float val = 0; if (!(*it).empty()) + { val = it->interpKey(input); + if (i < mWeights.size()) + val *= mWeights[i]; + } SceneUtil::MorphGeometry::MorphTarget& target = node->getMorphTarget(i); if (target.getWeight() != val) diff --git a/components/nifosg/controller.hpp b/components/nifosg/controller.hpp index af658c0bd5..bb839caa53 100644 --- a/components/nifosg/controller.hpp +++ b/components/nifosg/controller.hpp @@ -225,6 +225,7 @@ namespace NifOsg private: std::vector mKeyFrames; + std::vector mWeights; }; #ifdef _MSC_VER diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 918e0ee2b3..81eb72ba9e 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -1357,7 +1357,7 @@ namespace NifOsg if(ctrl->recType == Nif::RC_NiGeomMorpherController) { const Nif::NiGeomMorpherController* nimorphctrl = static_cast(ctrl.getPtr()); - if (nimorphctrl->data.empty()) + if (nimorphctrl->mData.empty()) continue; drawable = handleMorphGeometry(nimorphctrl, geom, parentNode, composite, boundTextures, animflags); @@ -1378,7 +1378,7 @@ namespace NifOsg osg::ref_ptr morphGeom = new SceneUtil::MorphGeometry; morphGeom->setSourceGeometry(sourceGeometry); - const std::vector& morphs = morpher->data.getPtr()->mMorphs; + const std::vector& morphs = morpher->mData.getPtr()->mMorphs; if (morphs.empty()) return morphGeom; if (morphs[0].mVertices.size() != static_cast(sourceGeometry->getVertexArray())->size())