From f3f5dcb016507e3661583c40661137dc53200b83 Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Tue, 10 Nov 2020 22:30:44 +0300 Subject: [PATCH 1/2] Read a few more NIF types NiFloatInterpolator, NiPoint3Interpolator, NiTransformInterpolator, NiBoolInterpolator Update a few existing controller records Update NiSkinInstance --- components/nif/controller.cpp | 96 +++++++++++++++++++++++++++++++- components/nif/controller.hpp | 42 ++++++++++++++ components/nif/data.cpp | 5 +- components/nif/niffile.cpp | 5 ++ components/nif/nifkey.hpp | 15 ++++- components/nif/record.hpp | 6 +- components/nif/recordptr.hpp | 7 +++ components/nifosg/controller.cpp | 53 ++++++++++++++++-- components/nifosg/controller.hpp | 41 ++++++++++++++ components/nifosg/nifloader.cpp | 50 +++++++++++++---- 10 files changed, 299 insertions(+), 21 deletions(-) diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index 1f1dd01c1..2cd61950b 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -92,6 +92,8 @@ namespace Nif void NiMaterialColorController::read(NIFStream *nif) { Controller::read(nif); + if (nif->getVersion() > NIFStream::generateVersion(10,1,0,103)) + interpolator.read(nif); // Two bits that correspond to the controlled material color. // 00: Ambient // 01: Diffuse @@ -101,12 +103,14 @@ namespace Nif targetColor = nif->getUShort() & 3; else targetColor = (flags >> 4) & 3; - data.read(nif); + if (nif->getVersion() <= NIFStream::generateVersion(10,1,0,103)) + data.read(nif); } void NiMaterialColorController::post(NIFFile *nif) { Controller::post(nif); + interpolator.post(nif); data.post(nif); } @@ -161,25 +165,33 @@ namespace Nif void NiKeyframeController::read(NIFStream *nif) { Controller::read(nif); - data.read(nif); + if (nif->getVersion() <= NIFStream::generateVersion(10,1,0,103)) + data.read(nif); + else + interpolator.read(nif); } void NiKeyframeController::post(NIFFile *nif) { Controller::post(nif); data.post(nif); + interpolator.post(nif); } void NiFloatInterpController::read(NIFStream *nif) { Controller::read(nif); - data.read(nif); + if (nif->getVersion() <= NIFStream::generateVersion(10,1,0,103)) + data.read(nif); + else + interpolator.read(nif); } void NiFloatInterpController::post(NIFFile *nif) { Controller::post(nif); data.post(nif); + interpolator.post(nif); } void NiGeomMorpherController::read(NIFStream *nif) @@ -189,13 +201,33 @@ namespace Nif /*bool updateNormals = !!*/nif->getUShort(); data.read(nif); if (nif->getVersion() >= NIFFile::NIFVersion::VER_MW) + { /*bool alwaysActive = */nif->getChar(); // Always 0 + if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,106)) + { + if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB) + { + interpolators.read(nif); + if (nif->getVersion() >= NIFStream::generateVersion(10,2,0,0) && nif->getBethVersion() > 9) + { + unsigned int numUnknown = nif->getUInt(); + nif->skip(4 * numUnknown); + } + } + else + { + unsigned int numInterps = nif->getUInt(); + nif->skip(8 * numInterps); + } + } + } } void NiGeomMorpherController::post(NIFFile *nif) { Controller::post(nif); data.post(nif); + interpolators.post(nif); } void NiVisController::read(NIFStream *nif) @@ -213,6 +245,8 @@ namespace Nif void NiFlipController::read(NIFStream *nif) { Controller::read(nif); + if (nif->getVersion() >= NIFStream::generateVersion(10,2,0,0)) + mInterpolator.read(nif); mTexSlot = nif->getUInt(); if (nif->getVersion() <= NIFStream::generateVersion(10,1,0,103)) { @@ -225,6 +259,7 @@ namespace Nif void NiFlipController::post(NIFFile *nif) { Controller::post(nif); + mInterpolator.post(nif); mSources.post(nif); } @@ -234,4 +269,59 @@ namespace Nif nif->getUInt(); // Zero } + void NiPoint3Interpolator::read(NIFStream *nif) + { + defaultVal = nif->getVector3(); + data.read(nif); + } + + void NiPoint3Interpolator::post(NIFFile *nif) + { + data.post(nif); + } + + void NiBoolInterpolator::read(NIFStream *nif) + { + defaultVal = nif->getBoolean(); + data.read(nif); + } + + void NiBoolInterpolator::post(NIFFile *nif) + { + data.post(nif); + } + + void NiFloatInterpolator::read(NIFStream *nif) + { + defaultVal = nif->getFloat(); + data.read(nif); + } + + void NiFloatInterpolator::post(NIFFile *nif) + { + data.post(nif); + } + + void NiTransformInterpolator::read(NIFStream *nif) + { + defaultPos = nif->getVector3(); + defaultRot = nif->getQuaternion(); + defaultScale = nif->getFloat(); + if (nif->getVersion() <= NIFStream::generateVersion(10,1,0,109)) + { + if (!nif->getBoolean()) + defaultPos = osg::Vec3f(); + if (!nif->getBoolean()) + defaultRot = osg::Quat(); + if (!nif->getBoolean()) + defaultScale = 1.f; + } + data.read(nif); + } + + void NiTransformInterpolator::post(NIFFile *nif) + { + data.post(nif); + } + } diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index ac6783b8d..6b84d3749 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -83,6 +83,7 @@ using NiBSPArrayController = NiParticleSystemController; class NiMaterialColorController : public Controller { public: + NiPoint3InterpolatorPtr interpolator; NiPosDataPtr data; unsigned int targetColor; @@ -138,6 +139,7 @@ class NiKeyframeController : public Controller { public: NiKeyframeDataPtr data; + NiTransformInterpolatorPtr interpolator; void read(NIFStream *nif) override; void post(NIFFile *nif) override; @@ -146,6 +148,7 @@ public: struct NiFloatInterpController : public Controller { NiFloatDataPtr data; + NiFloatInterpolatorPtr interpolator; void read(NIFStream *nif) override; void post(NIFFile *nif) override; @@ -158,6 +161,7 @@ class NiGeomMorpherController : public Controller { public: NiMorphDataPtr data; + NiFloatInterpolatorList interpolators; void read(NIFStream *nif) override; void post(NIFFile *nif) override; @@ -175,6 +179,7 @@ public: class NiFlipController : public Controller { public: + NiFloatInterpolatorPtr mInterpolator; int mTexSlot; // NiTexturingProperty::TextureType float mDelta; // Time between two flips. delta = (start_time - stop_time) / num_sources NiSourceTextureList mSources; @@ -188,5 +193,42 @@ struct bhkBlendController : public Controller void read(NIFStream *nif) override; }; +struct Interpolator : public Record { }; + +struct NiPoint3Interpolator : public Interpolator +{ + osg::Vec3f defaultVal; + NiPosDataPtr data; + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; +}; + +struct NiBoolInterpolator : public Interpolator +{ + bool defaultVal; + NiBoolDataPtr data; + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; +}; + +struct NiFloatInterpolator : public Interpolator +{ + float defaultVal; + NiFloatDataPtr data; + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; +}; + +struct NiTransformInterpolator : public Interpolator +{ + osg::Vec3f defaultPos; + osg::Quat defaultRot; + float defaultScale; + NiKeyframeDataPtr data; + + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; +}; + } // Namespace #endif diff --git a/components/nif/data.cpp b/components/nif/data.cpp index 6bbab9786..1eb5c40fe 100644 --- a/components/nif/data.cpp +++ b/components/nif/data.cpp @@ -6,6 +6,8 @@ namespace Nif void NiSkinInstance::read(NIFStream *nif) { data.read(nif); + if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,101)) + partitions.read(nif); root.read(nif); bones.read(nif); } @@ -13,6 +15,7 @@ void NiSkinInstance::read(NIFStream *nif) void NiSkinInstance::post(NIFFile *nif) { data.post(nif); + partitions.post(nif); root.post(nif); bones.post(nif); @@ -418,7 +421,7 @@ void NiMorphData::read(NIFStream *nif) for(int i = 0;i < morphCount;i++) { mMorphs[i].mKeyFrames = std::make_shared(); - mMorphs[i].mKeyFrames->read(nif, true); + mMorphs[i].mKeyFrames->read(nif, true, /*morph*/true); nif->getVector3s(mMorphs[i].mVertices, vertCount); } } diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 06b4a89d0..7915908d1 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -122,6 +122,11 @@ static std::map makeFactory() factory["NiTransformData"] = {&construct , RC_NiKeyframeData }; factory["BSFadeNode"] = {&construct , RC_NiNode }; factory["bhkBlendController"] = {&construct , RC_bhkBlendController }; + factory["NiFloatInterpolator"] = {&construct , RC_NiFloatInterpolator }; + factory["NiBoolInterpolator"] = {&construct , RC_NiBoolInterpolator }; + factory["NiPoint3Interpolator"] = {&construct , RC_NiPoint3Interpolator }; + factory["NiTransformController"] = {&construct , RC_NiKeyframeController }; + factory["NiTransformInterpolator"] = {&construct , RC_NiTransformInterpolator }; return factory; } diff --git a/components/nif/nifkey.hpp b/components/nif/nifkey.hpp index 4c10327e1..de2fa31c8 100644 --- a/components/nif/nifkey.hpp +++ b/components/nif/nifkey.hpp @@ -52,16 +52,27 @@ struct KeyMapT { MapType mKeys; //Read in a KeyGroup (see http://niftools.sourceforge.net/doc/nif/NiKeyframeData.html) - void read(NIFStream *nif, bool force=false) + void read(NIFStream *nif, bool force = false, bool morph = false) { assert(nif); mInterpolationType = InterpolationType_Unknown; + if (morph && nif->getVersion() >= NIFStream::generateVersion(10,1,0,106)) + nif->getString(); // Frame name + size_t count = nif->getUInt(); - if(count == 0 && !force) + if (count == 0 && !force && !morph) return; + if (morph && nif->getVersion() > NIFStream::generateVersion(10,1,0,0)) + { + if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,104) && + nif->getVersion() <= NIFStream::generateVersion(20,1,0,2) && nif->getBethVersion() < 10) + nif->getFloat(); // Legacy weight + return; + } + mKeys.clear(); mInterpolationType = nif->getUInt(); diff --git a/components/nif/record.hpp b/components/nif/record.hpp index d3ee01fd4..c5773643a 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -115,7 +115,11 @@ enum RecordType RC_NiSkinPartition, RC_BSXFlags, RC_BSBound, - RC_bhkBlendController + RC_bhkBlendController, + RC_NiFloatInterpolator, + RC_NiPoint3Interpolator, + RC_NiBoolInterpolator, + RC_NiTransformInterpolator, }; /// Base class for all records diff --git a/components/nif/recordptr.hpp b/components/nif/recordptr.hpp index 2748f4073..b40a17583 100644 --- a/components/nif/recordptr.hpp +++ b/components/nif/recordptr.hpp @@ -145,6 +145,9 @@ struct NiParticleModifier; struct NiLinesData; struct NiBoolData; struct NiSkinPartition; +struct NiFloatInterpolator; +struct NiPoint3Interpolator; +struct NiTransformInterpolator; using NodePtr = RecordPtrT; using ExtraPtr = RecordPtrT; @@ -170,11 +173,15 @@ using NiPalettePtr = RecordPtrT; using NiParticleModifierPtr = RecordPtrT; using NiBoolDataPtr = RecordPtrT; using NiSkinPartitionPtr = RecordPtrT; +using NiFloatInterpolatorPtr = RecordPtrT; +using NiPoint3InterpolatorPtr = RecordPtrT; +using NiTransformInterpolatorPtr = RecordPtrT; using NodeList = RecordListT; using PropertyList = RecordListT; using ExtraList = RecordListT; using NiSourceTextureList = RecordListT; +using NiFloatInterpolatorList = RecordListT; } // Namespace #endif diff --git a/components/nifosg/controller.cpp b/components/nifosg/controller.cpp index 9c654b9d1..c0f7522d5 100644 --- a/components/nifosg/controller.cpp +++ b/components/nifosg/controller.cpp @@ -92,6 +92,26 @@ KeyframeController::KeyframeController(const Nif::NiKeyframeData *data) { } +KeyframeController::KeyframeController(const Nif::NiTransformInterpolator* interpolator) + : mRotations(interpolator->data->mRotations, interpolator->defaultRot) + , mXRotations(interpolator->data->mXRotations, 0.f) + , mYRotations(interpolator->data->mYRotations, 0.f) + , mZRotations(interpolator->data->mZRotations, 0.f) + , mTranslations(interpolator->data->mTranslations, interpolator->defaultPos) + , mScales(interpolator->data->mScales, interpolator->defaultScale) +{ +} + +KeyframeController::KeyframeController(const float scale, const osg::Vec3f& pos, const osg::Quat& rot) + : mRotations(Nif::QuaternionKeyMapPtr(), rot) + , mXRotations(Nif::FloatKeyMapPtr(), 0.f) + , mYRotations(Nif::FloatKeyMapPtr(), 0.f) + , mZRotations(Nif::FloatKeyMapPtr(), 0.f) + , mTranslations(Nif::Vector3KeyMapPtr(), pos) + , mScales(Nif::FloatKeyMapPtr(), scale) +{ +} + osg::Quat KeyframeController::getXYZRotation(float time) const { float xrot = 0, yrot = 0, zrot = 0; @@ -313,6 +333,11 @@ RollController::RollController(const Nif::NiFloatData *data) { } +RollController::RollController(const Nif::NiFloatInterpolator* interpolator) + : mData(interpolator) +{ +} + RollController::RollController(const RollController ©, const osg::CopyOp ©op) : osg::NodeCallback(copy, copyop) , Controller(copy) @@ -344,6 +369,10 @@ void RollController::operator() (osg::Node* node, osg::NodeVisitor* nv) } } +AlphaController::AlphaController() +{ +} + AlphaController::AlphaController(const Nif::NiFloatData *data, const osg::Material* baseMaterial) : mData(data->mKeyList, 1.f) , mBaseMaterial(baseMaterial) @@ -351,7 +380,9 @@ AlphaController::AlphaController(const Nif::NiFloatData *data, const osg::Materi } -AlphaController::AlphaController() +AlphaController::AlphaController(const Nif::NiFloatInterpolator* interpolator, const osg::Material* baseMaterial) + : mData(interpolator) + , mBaseMaterial(baseMaterial) { } @@ -379,6 +410,10 @@ void AlphaController::apply(osg::StateSet *stateset, osg::NodeVisitor *nv) } } +MaterialColorController::MaterialColorController() +{ +} + MaterialColorController::MaterialColorController(const Nif::NiPosData *data, TargetColor color, const osg::Material* baseMaterial) : mData(data->mKeyList, osg::Vec3f(1,1,1)) , mTargetColor(color) @@ -386,7 +421,10 @@ MaterialColorController::MaterialColorController(const Nif::NiPosData *data, Tar { } -MaterialColorController::MaterialColorController() +MaterialColorController::MaterialColorController(const Nif::NiPoint3Interpolator* interpolator, TargetColor color, const osg::Material* baseMaterial) + : mData(interpolator) + , mTargetColor(color) + , mBaseMaterial(baseMaterial) { } @@ -448,6 +486,8 @@ FlipController::FlipController(const Nif::NiFlipController *ctrl, const std::vec , mDelta(ctrl->mDelta) , mTextures(textures) { + if (!ctrl->mInterpolator.empty()) + mData = ctrl->mInterpolator.getPtr(); } FlipController::FlipController(int texSlot, float delta, const std::vector >& textures) @@ -463,14 +503,19 @@ FlipController::FlipController(const FlipController ©, const osg::CopyOp &co , mTexSlot(copy.mTexSlot) , mDelta(copy.mDelta) , mTextures(copy.mTextures) + , mData(copy.mData) { } void FlipController::apply(osg::StateSet* stateset, osg::NodeVisitor* nv) { - if (hasInput() && mDelta != 0 && !mTextures.empty()) + if (hasInput() && !mTextures.empty()) { - int curTexture = int(getInputValue(nv) / mDelta) % mTextures.size(); + int curTexture = 0; + if (mDelta != 0) + curTexture = int(getInputValue(nv) / mDelta) % mTextures.size(); + else + curTexture = int(mData.interpKey(getInputValue(nv))) % mTextures.size(); stateset->setTextureAttribute(mTexSlot, mTextures[curTexture]); } } diff --git a/components/nifosg/controller.hpp b/components/nifosg/controller.hpp index c087e635f..fa154d207 100644 --- a/components/nifosg/controller.hpp +++ b/components/nifosg/controller.hpp @@ -58,6 +58,8 @@ namespace NifOsg using ValueT = typename MapT::ValueType; ValueInterpolator() = default; + ValueInterpolator(const Nif::NiFloatInterpolator* interpolator) = delete; + ValueInterpolator(const Nif::NiPoint3Interpolator* interpolator) = delete; ValueInterpolator(std::shared_ptr keys, ValueT defaultVal = ValueT()) : mKeys(keys) @@ -161,6 +163,34 @@ namespace NifOsg using Vec3Interpolator = ValueInterpolator; using Vec4Interpolator = ValueInterpolator; + template<> + inline FloatInterpolator::ValueInterpolator(const Nif::NiFloatInterpolator* interpolator) + : mDefaultVal(interpolator->defaultVal) + { + if (interpolator->data.empty()) + return; + mKeys = interpolator->data->mKeyList; + if (mKeys) + { + mLastLowKey = mKeys->mKeys.end(); + mLastHighKey = mKeys->mKeys.end(); + } + } + + template<> + inline Vec3Interpolator::ValueInterpolator(const Nif::NiPoint3Interpolator* interpolator) + : mDefaultVal(interpolator->defaultVal) + { + if (interpolator->data.empty()) + return; + mKeys = interpolator->data->mKeyList; + if (mKeys) + { + mLastLowKey = mKeys->mKeys.end(); + mLastHighKey = mKeys->mKeys.end(); + } + } + class ControllerFunction : public SceneUtil::ControllerFunction { private: @@ -203,7 +233,14 @@ namespace NifOsg class KeyframeController : public osg::NodeCallback, public SceneUtil::Controller { public: + // This is used if there's no interpolator but there is data (Morrowind meshes). KeyframeController(const Nif::NiKeyframeData *data); + // This is used if the interpolator has data. + KeyframeController(const Nif::NiTransformInterpolator* interpolator); + // This is used if there are default values available (e.g. from a data-less interpolator). + // If there's neither keyframe data nor an interpolator a KeyframeController must not be created. + KeyframeController(const float scale, const osg::Vec3f& pos, const osg::Quat& rot); + KeyframeController(); KeyframeController(const KeyframeController& copy, const osg::CopyOp& copyop); @@ -272,6 +309,7 @@ namespace NifOsg public: RollController(const Nif::NiFloatData *data); + RollController(const Nif::NiFloatInterpolator* interpolator); RollController() = default; RollController(const RollController& copy, const osg::CopyOp& copyop); @@ -287,6 +325,7 @@ namespace NifOsg osg::ref_ptr mBaseMaterial; public: AlphaController(const Nif::NiFloatData *data, const osg::Material* baseMaterial); + AlphaController(const Nif::NiFloatInterpolator* interpolator, const osg::Material* baseMaterial); AlphaController(); AlphaController(const AlphaController& copy, const osg::CopyOp& copyop); @@ -308,6 +347,7 @@ namespace NifOsg Emissive = 3 }; MaterialColorController(const Nif::NiPosData *data, TargetColor color, const osg::Material* baseMaterial); + MaterialColorController(const Nif::NiPoint3Interpolator* interpolator, TargetColor color, const osg::Material* baseMaterial); MaterialColorController(); MaterialColorController(const MaterialColorController& copy, const osg::CopyOp& copyop); @@ -329,6 +369,7 @@ namespace NifOsg int mTexSlot{0}; float mDelta{0.f}; std::vector > mTextures; + FloatInterpolator mData; public: FlipController(const Nif::NiFlipController* ctrl, const std::vector >& textures); diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 805283b42..030252412 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -281,10 +281,10 @@ namespace NifOsg const Nif::NiStringExtraData *strdata = static_cast(extra.getPtr()); const Nif::NiKeyframeController *key = static_cast(ctrl.getPtr()); - if(key->data.empty()) + if (key->data.empty() && key->interpolator.empty()) continue; - osg::ref_ptr callback(new NifOsg::KeyframeController(key->data.getPtr())); + osg::ref_ptr callback(handleKeyframeController(key)); callback->setFunction(std::shared_ptr(new NifOsg::ControllerFunction(key))); if (!target.mKeyframeControllers.emplace(strdata->string, callback).second) @@ -725,6 +725,24 @@ namespace NifOsg } } + static osg::ref_ptr handleKeyframeController(const Nif::NiKeyframeController* keyctrl) + { + osg::ref_ptr ctrl; + if (!keyctrl->interpolator.empty()) + { + const Nif::NiTransformInterpolator* interp = keyctrl->interpolator.getPtr(); + if (!interp->data.empty()) + ctrl = new NifOsg::KeyframeController(interp); + else + ctrl = new NifOsg::KeyframeController(interp->defaultScale, interp->defaultPos, interp->defaultRot); + } + else if (!keyctrl->data.empty()) + { + ctrl = new NifOsg::KeyframeController(keyctrl->data.getPtr()); + } + return ctrl; + } + void handleNodeControllers(const Nif::Node* nifNode, osg::Node* node, int animflags, bool& isAnimated) { for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next) @@ -734,9 +752,9 @@ namespace NifOsg if (ctrl->recType == Nif::RC_NiKeyframeController) { const Nif::NiKeyframeController *key = static_cast(ctrl.getPtr()); - if (key->data.empty()) + if (key->data.empty() && key->interpolator.empty()) continue; - osg::ref_ptr callback(new KeyframeController(key->data.getPtr())); + osg::ref_ptr callback(handleKeyframeController(key)); setupController(key, callback, animflags); node->addUpdateCallback(callback); isAnimated = true; @@ -763,9 +781,13 @@ namespace NifOsg else if (ctrl->recType == Nif::RC_NiRollController) { const Nif::NiRollController *rollctrl = static_cast(ctrl.getPtr()); - if (rollctrl->data.empty()) + if (rollctrl->data.empty() && rollctrl->interpolator.empty()) continue; - osg::ref_ptr callback(new RollController(rollctrl->data.getPtr())); + osg::ref_ptr callback; + if (!rollctrl->interpolator.empty()) + callback = new RollController(rollctrl->interpolator.getPtr()); + else // if (!rollctrl->data.empty()) + callback = new RollController(rollctrl->data.getPtr()); setupController(rollctrl, callback, animflags); node->addUpdateCallback(callback); isAnimated = true; @@ -791,19 +813,27 @@ namespace NifOsg if (ctrl->recType == Nif::RC_NiAlphaController) { const Nif::NiAlphaController* alphactrl = static_cast(ctrl.getPtr()); - if (alphactrl->data.empty()) + if (alphactrl->data.empty() && alphactrl->interpolator.empty()) continue; - osg::ref_ptr osgctrl(new AlphaController(alphactrl->data.getPtr(), baseMaterial)); + osg::ref_ptr osgctrl; + if (!alphactrl->interpolator.empty()) + osgctrl = new AlphaController(alphactrl->interpolator.getPtr(), baseMaterial); + else // if (!alphactrl->data.empty()) + osgctrl = new AlphaController(alphactrl->data.getPtr(), baseMaterial); setupController(alphactrl, osgctrl, animflags); composite->addController(osgctrl); } else if (ctrl->recType == Nif::RC_NiMaterialColorController) { const Nif::NiMaterialColorController* matctrl = static_cast(ctrl.getPtr()); - if (matctrl->data.empty()) + if (matctrl->data.empty() && matctrl->interpolator.empty()) continue; + osg::ref_ptr osgctrl; auto targetColor = static_cast(matctrl->targetColor); - osg::ref_ptr osgctrl(new MaterialColorController(matctrl->data.getPtr(), targetColor, baseMaterial)); + if (!matctrl->interpolator.empty()) + osgctrl = new MaterialColorController(matctrl->interpolator.getPtr(), targetColor, baseMaterial); + else // if (!matctrl->data.empty()) + osgctrl = new MaterialColorController(matctrl->data.getPtr(), targetColor, baseMaterial); setupController(matctrl, osgctrl, animflags); composite->addController(osgctrl); } From a46699fb1e91a0fa21cdb2a1c78eaa134246d5ee Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Tue, 10 Nov 2020 23:23:11 +0300 Subject: [PATCH 2/2] Handle NiGeomMorpherController interpolator list --- components/nif/controller.cpp | 1 + components/nifosg/controller.cpp | 21 ++++++++++++++++++--- components/nifosg/controller.hpp | 2 +- components/nifosg/nifloader.cpp | 2 +- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index 2cd61950b..1e909120e 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -216,6 +216,7 @@ namespace Nif } else { + // TODO: handle weighted interpolators unsigned int numInterps = nif->getUInt(); nif->skip(8 * numInterps); } diff --git a/components/nifosg/controller.cpp b/components/nifosg/controller.cpp index c0f7522d5..64e9f7de6 100644 --- a/components/nifosg/controller.cpp +++ b/components/nifosg/controller.cpp @@ -197,10 +197,25 @@ GeomMorpherController::GeomMorpherController(const GeomMorpherController ©, { } -GeomMorpherController::GeomMorpherController(const Nif::NiMorphData *data) +GeomMorpherController::GeomMorpherController(const Nif::NiGeomMorpherController* ctrl) { - for (unsigned int i=0; imMorphs.size(); ++i) - mKeyFrames.emplace_back(data->mMorphs[i].mKeyFrames); + if (ctrl->interpolators.length() == 0) + { + if (ctrl->data.empty()) + return; + for (const auto& morph : ctrl->data->mMorphs) + mKeyFrames.emplace_back(morph.mKeyFrames); + } + else + { + for (size_t i = 0; i < ctrl->interpolators.length(); ++i) + { + if (!ctrl->interpolators[i].empty()) + mKeyFrames.emplace_back(ctrl->interpolators[i].getPtr()); + else + mKeyFrames.emplace_back(); + } + } } void GeomMorpherController::update(osg::NodeVisitor *nv, osg::Drawable *drawable) diff --git a/components/nifosg/controller.hpp b/components/nifosg/controller.hpp index fa154d207..dd3068ac8 100644 --- a/components/nifosg/controller.hpp +++ b/components/nifosg/controller.hpp @@ -218,7 +218,7 @@ namespace NifOsg class GeomMorpherController : public osg::Drawable::UpdateCallback, public SceneUtil::Controller { public: - GeomMorpherController(const Nif::NiMorphData* data); + GeomMorpherController(const Nif::NiGeomMorpherController* ctrl); GeomMorpherController(); GeomMorpherController(const GeomMorpherController& copy, const osg::CopyOp& copyop); diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 030252412..a5a61b317 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -1244,7 +1244,7 @@ namespace NifOsg continue; drawable = handleMorphGeometry(nimorphctrl, geom, parentNode, composite, boundTextures, animflags); - osg::ref_ptr morphctrl = new GeomMorpherController(nimorphctrl->data.getPtr()); + osg::ref_ptr morphctrl = new GeomMorpherController(nimorphctrl); setupController(ctrl.getPtr(), morphctrl, animflags); drawable->setUpdateCallback(morphctrl); break;