From 956ede52fbd78922f7f903cdf6fc2cbbb3610249 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 13 Sep 2023 21:56:02 +0300 Subject: [PATCH 01/15] NIFStream: remove getShort, getMatrix3, getQuaternion --- components/nif/controller.cpp | 6 +++--- components/nif/controller.hpp | 2 +- components/nif/nifstream.hpp | 3 --- components/nif/node.cpp | 2 +- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index a3d7f33e45..80cc74ce23 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -264,7 +264,7 @@ namespace Nif bankDir = nif->getInt(); maxBankAngle = nif->getFloat(); smoothing = nif->getFloat(); - followAxis = nif->getShort(); + nif->read(followAxis); posData.read(nif); floatData.read(nif); } @@ -507,7 +507,7 @@ namespace Nif void NiTransformInterpolator::read(NIFStream* nif) { defaultPos = nif->getVector3(); - defaultRot = nif->getQuaternion(); + nif->read(defaultRot); defaultScale = nif->getFloat(); if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 109)) { @@ -655,7 +655,7 @@ namespace Nif if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 109)) { mPosValue = nif->getVector3(); - mRotValue = nif->getQuaternion(); + nif->read(mRotValue); mScaleValue = nif->getFloat(); if (!nif->getBoolean()) mPosValue = osg::Vec3f(); diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index 68e795e7fc..07c042e047 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -203,7 +203,7 @@ namespace Nif int bankDir; float maxBankAngle, smoothing; - short followAxis; + uint16_t followAxis; void read(NIFStream* nif) override; void post(Reader& nif) override; diff --git a/components/nif/nifstream.hpp b/components/nif/nifstream.hpp index f4c35e6625..9c9a097662 100644 --- a/components/nif/nifstream.hpp +++ b/components/nif/nifstream.hpp @@ -149,7 +149,6 @@ namespace Nif /// DEPRECATED: Use read() or get() char getChar() { return get(); } - short getShort() { return get(); } unsigned short getUShort() { return get(); } int getInt() { return get(); } unsigned int getUInt() { return get(); } @@ -157,8 +156,6 @@ namespace Nif osg::Vec2f getVector2() { return get(); } osg::Vec3f getVector3() { return get(); } osg::Vec4f getVector4() { return get(); } - Matrix3 getMatrix3() { return get(); } - osg::Quat getQuaternion() { return get(); } bool getBoolean() { return get(); } std::string getString() { return get(); } }; diff --git a/components/nif/node.cpp b/components/nif/node.cpp index d7b6c3945b..ad966097b0 100644 --- a/components/nif/node.cpp +++ b/components/nif/node.cpp @@ -25,7 +25,7 @@ namespace Nif case BOX_BV: { box.center = nif->getVector3(); - box.axes = nif->getMatrix3(); + nif->read(box.axes); box.extents = nif->getVector3(); break; } From a224bea6d452276bdf0df04c1206dba90b5e1e9c Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 13 Sep 2023 23:15:14 +0300 Subject: [PATCH 02/15] Rewrite NiBlendInterpolator+friends loading --- components/nif/controller.cpp | 144 ++++++++++++---------------------- components/nif/controller.hpp | 87 +++++++++----------- components/nif/nifstream.cpp | 22 ++++++ components/nif/nifstream.hpp | 4 + components/nif/niftypes.hpp | 26 ++++++ 5 files changed, 141 insertions(+), 142 deletions(-) diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index 80cc74ce23..c900f90282 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -540,71 +540,63 @@ namespace Nif void NiBlendInterpolator::read(NIFStream* nif) { if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 112)) - mManagerControlled = nif->getChar() & 1; - size_t numInterps = 0; - if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 109)) { - numInterps = nif->getUShort(); - mArrayGrowBy = nif->getUShort(); - } - else - { - numInterps = nif->getChar(); - if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 112)) + nif->read(mFlags); + mItems.resize(nif->get()); + nif->read(mWeightThreshold); + if (!(mFlags & Flag_ManagerControlled)) { - mWeightThreshold = nif->getFloat(); - if (!mManagerControlled) - { - mInterpCount = nif->getChar(); - mSingleIndex = nif->getChar(); - mHighPriority = nif->getChar(); - mNextHighPriority = nif->getChar(); - mSingleTime = nif->getFloat(); - mHighWeightsSum = nif->getFloat(); - mNextHighWeightsSum = nif->getFloat(); - mHighEaseSpinner = nif->getFloat(); - } + mInterpCount = nif->get(); + mSingleIndex = nif->get(); + mHighPriority = nif->get(); + mNextHighPriority = nif->get(); + nif->read(mSingleTime); + nif->read(mHighWeightsSum); + nif->read(mNextHighWeightsSum); + nif->read(mHighEaseSpinner); + for (Item& item : mItems) + item.read(nif); } + return; } - if (!mManagerControlled) + if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 110)) { - mItems.resize(numInterps); + mItems.resize(nif->get()); for (Item& item : mItems) item.read(nif); + if (nif->get()) + mFlags |= Flag_ManagerControlled; + nif->read(mWeightThreshold); + if (nif->get()) + mFlags |= Flag_OnlyUseHighestWeight; + mInterpCount = nif->get(); + mSingleIndex = nif->get(); + mSingleInterpolator.read(nif); + nif->read(mSingleTime); + mHighPriority = nif->get(); + mNextHighPriority = nif->get(); + return; } - if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 111)) + mItems.resize(nif->get()); + nif->read(mArrayGrowBy); + for (Item& item : mItems) + item.read(nif); + if (nif->get()) + mFlags |= Flag_ManagerControlled; + nif->read(mWeightThreshold); + if (nif->get()) + mFlags |= Flag_OnlyUseHighestWeight; + nif->read(mInterpCount); + nif->read(mSingleIndex); + if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 108)) { - mManagerControlled = nif->getBoolean(); - mWeightThreshold = nif->getFloat(); - mOnlyUseHighestWeight = nif->getBoolean(); - if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 109)) - { - mInterpCount = nif->getUShort(); - mSingleIndex = nif->getUShort(); - } - else - { - mInterpCount = nif->getChar(); - mSingleIndex = nif->getChar(); - } - if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 108)) - { - mSingleInterpolator.read(nif); - mSingleTime = nif->getFloat(); - } - if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 109)) - { - mHighPriority = nif->getInt(); - mNextHighPriority = nif->getInt(); - } - else - { - mHighPriority = nif->getChar(); - mNextHighPriority = nif->getChar(); - } + mSingleInterpolator.read(nif); + nif->read(mSingleTime); } + nif->read(mHighPriority); + nif->read(mNextHighPriority); } void NiBlendInterpolator::post(Reader& nif) @@ -617,13 +609,13 @@ namespace Nif void NiBlendInterpolator::Item::read(NIFStream* nif) { mInterpolator.read(nif); - mWeight = nif->getFloat(); - mNormalizedWeight = nif->getFloat(); - if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 109)) - mPriority = nif->getInt(); + nif->read(mWeight); + nif->read(mNormalizedWeight); + if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 110)) + mPriority = nif->get(); else - mPriority = nif->getChar(); - mEaseSpinner = nif->getFloat(); + nif->read(mPriority); + nif->read(mEaseSpinner); } void NiBlendInterpolator::Item::post(Reader& nif) @@ -631,38 +623,4 @@ namespace Nif mInterpolator.post(nif); } - void NiBlendBoolInterpolator::read(NIFStream* nif) - { - NiBlendInterpolator::read(nif); - mValue = nif->getChar() != 0; - } - - void NiBlendFloatInterpolator::read(NIFStream* nif) - { - NiBlendInterpolator::read(nif); - mValue = nif->getFloat(); - } - - void NiBlendPoint3Interpolator::read(NIFStream* nif) - { - NiBlendInterpolator::read(nif); - mValue = nif->getVector3(); - } - - void NiBlendTransformInterpolator::read(NIFStream* nif) - { - NiBlendInterpolator::read(nif); - if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 109)) - { - mPosValue = nif->getVector3(); - nif->read(mRotValue); - mScaleValue = nif->getFloat(); - if (!nif->getBoolean()) - mPosValue = osg::Vec3f(); - if (!nif->getBoolean()) - mRotValue = osg::Quat(); - if (!nif->getBoolean()) - mScaleValue = 1.f; - } - } } diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index 07c042e047..e21b04bb72 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -1,30 +1,8 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008-2010 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: https://openmw.org/ - - This file (controller.h) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - https://www.gnu.org/licenses/ . - - */ - #ifndef OPENMW_COMPONENTS_NIF_CONTROLLER_HPP #define OPENMW_COMPONENTS_NIF_CONTROLLER_HPP #include "base.hpp" +#include "niftypes.hpp" #include "property.hpp" namespace Nif @@ -378,24 +356,29 @@ namespace Nif // Abstract struct NiBlendInterpolator : public NiInterpolator { + enum Flags + { + Flag_ManagerControlled = 0x1, + Flag_OnlyUseHighestWeight = 0x2, + }; + struct Item { NiInterpolatorPtr mInterpolator; float mWeight, mNormalizedWeight; - int mPriority; + int32_t mPriority; float mEaseSpinner; void read(NIFStream* nif); void post(Reader& nif); }; - bool mManagerControlled{ false }; - bool mOnlyUseHighestWeight{ false }; - unsigned short mArrayGrowBy{ 0 }; + uint8_t mFlags{ 0 }; + uint16_t mArrayGrowBy{ 0 }; float mWeightThreshold; - unsigned short mInterpCount; - unsigned short mSingleIndex; - int mHighPriority, mNextHighPriority; + uint16_t mInterpCount; + uint16_t mSingleIndex; + int32_t mHighPriority, mNextHighPriority; float mSingleTime; float mHighWeightsSum, mNextHighWeightsSum; float mHighEaseSpinner; @@ -406,31 +389,37 @@ namespace Nif void post(Reader& nif) override; }; - struct NiBlendBoolInterpolator : public NiBlendInterpolator + template + struct TypedNiBlendInterpolator : public NiBlendInterpolator { - char mValue; - void read(NIFStream* nif) override; - }; + T mValue; - struct NiBlendFloatInterpolator : public NiBlendInterpolator - { - float mValue; - void read(NIFStream* nif) override; - }; + void read(NIFStream* nif) override + { + NiBlendInterpolator::read(nif); - struct NiBlendPoint3Interpolator : public NiBlendInterpolator - { - osg::Vec3f mValue; - void read(NIFStream* nif) override; + nif->read(mValue); + } }; - struct NiBlendTransformInterpolator : public NiBlendInterpolator + template <> + struct TypedNiBlendInterpolator : public NiBlendInterpolator { - osg::Vec3f mPosValue; - osg::Quat mRotValue; - float mScaleValue; - void read(NIFStream* nif) override; + NiQuatTransform mValue; + + void read(NIFStream* nif) override + { + NiBlendInterpolator::read(nif); + + if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 109)) + nif->read(mValue); + } }; -} // Namespace + using NiBlendBoolInterpolator = TypedNiBlendInterpolator; + using NiBlendFloatInterpolator = TypedNiBlendInterpolator; + using NiBlendPoint3Interpolator = TypedNiBlendInterpolator; + using NiBlendTransformInterpolator = TypedNiBlendInterpolator; + +} #endif diff --git a/components/nif/nifstream.cpp b/components/nif/nifstream.cpp index e33dc4f7b1..2eba746ccf 100644 --- a/components/nif/nifstream.cpp +++ b/components/nif/nifstream.cpp @@ -137,6 +137,22 @@ namespace Nif read(transform.mScale); } + template <> + void NIFStream::read(NiQuatTransform& transform) + { + read(transform.mTranslation); + read(transform.mRotation); + read(transform.mScale); + if (getVersion() >= generateVersion(10, 1, 0, 110)) + return; + if (!get()) + transform.mTranslation = osg::Vec3f(); + if (!get()) + transform.mRotation = osg::Quat(); + if (!get()) + transform.mScale = 1.f; + } + template <> void NIFStream::read(bool& data) { @@ -197,6 +213,12 @@ namespace Nif readRange(*this, dest, size); } + template <> + void NIFStream::read(NiQuatTransform* dest, size_t size) + { + readRange(*this, dest, size); + } + template <> void NIFStream::read(bool* dest, size_t size) { diff --git a/components/nif/nifstream.hpp b/components/nif/nifstream.hpp index 9c9a097662..c1f7cfdf12 100644 --- a/components/nif/nifstream.hpp +++ b/components/nif/nifstream.hpp @@ -175,6 +175,8 @@ namespace Nif template <> void NIFStream::read(NiTransform& transform); template <> + void NIFStream::read(NiQuatTransform& transform); + template <> void NIFStream::read(bool& data); template <> void NIFStream::read(std::string& str); @@ -194,6 +196,8 @@ namespace Nif template <> void NIFStream::read(NiTransform* dest, size_t size); template <> + void NIFStream::read(NiQuatTransform* dest, size_t size); + template <> void NIFStream::read(bool* dest, size_t size); template <> void NIFStream::read(std::string* dest, size_t size); diff --git a/components/nif/niftypes.hpp b/components/nif/niftypes.hpp index 3b2a4c1578..b294756f69 100644 --- a/components/nif/niftypes.hpp +++ b/components/nif/niftypes.hpp @@ -25,6 +25,7 @@ #define OPENMW_COMPONENTS_NIF_NIFTYPES_HPP #include +#include #include // Common types used in NIF files @@ -80,5 +81,30 @@ namespace Nif } }; + struct NiQuatTransform + { + osg::Vec3f mTranslation; + osg::Quat mRotation; + float mScale; + + osg::Matrixf toMatrix() const + { + osg::Matrixf transform(mRotation); + transform.setTrans(mTranslation); + for (int i = 0; i < 3; i++) + transform(i, i) *= mScale; + + return transform; + } + + bool isIdentity() const { return mTranslation == osg::Vec3f() && mRotation == osg::Quat() && mScale == 1.f; } + + static const NiQuatTransform& getIdentity() + { + static const NiQuatTransform identity = { osg::Vec3f(), osg::Quat(), 1.f }; + return identity; + } + }; + } // Namespace #endif From 208bfa9e21fd97ccd9c7f767d126888fcc353d61 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 13 Sep 2023 23:30:13 +0300 Subject: [PATCH 03/15] Refactor NiMaterialColorController --- components/nif/controller.cpp | 12 +++++------- components/nif/controller.hpp | 10 +++++++++- components/nifosg/controller.cpp | 11 ++++++----- components/nifosg/controller.hpp | 9 +-------- components/nifosg/nifloader.cpp | 11 +++++------ 5 files changed, 26 insertions(+), 27 deletions(-) diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index c900f90282..ee219fe5b5 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -224,15 +224,12 @@ namespace Nif void NiMaterialColorController::read(NIFStream* nif) { NiPoint3InterpController::read(nif); - // Two bits that correspond to the controlled material color. - // 00: Ambient - // 01: Diffuse - // 10: Specular - // 11: Emissive + if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0)) - mTargetColor = nif->getUShort() & 3; + mTargetColor = static_cast(nif->get() & 3); else - mTargetColor = (flags >> 4) & 3; + mTargetColor = static_cast((flags >> 4) & 3); + if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103)) mData.read(nif); } @@ -240,6 +237,7 @@ namespace Nif void NiMaterialColorController::post(Reader& nif) { NiPoint3InterpController::post(nif); + mData.post(nif); } diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index e21b04bb72..4b46840d4a 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -157,8 +157,16 @@ namespace Nif struct NiMaterialColorController : public NiPoint3InterpController { + enum class TargetColor + { + Ambient = 0, + Diffuse = 1, + Specular = 2, + Emissive = 3, + }; + NiPosDataPtr mData; - unsigned int mTargetColor; + TargetColor mTargetColor; void read(NIFStream* nif) override; void post(Reader& nif) override; diff --git a/components/nifosg/controller.cpp b/components/nifosg/controller.cpp index 20a3ee92e4..8e9efba8a9 100644 --- a/components/nifosg/controller.cpp +++ b/components/nifosg/controller.cpp @@ -444,7 +444,7 @@ namespace NifOsg MaterialColorController::MaterialColorController( const Nif::NiMaterialColorController* ctrl, const osg::Material* baseMaterial) - : mTargetColor(static_cast(ctrl->mTargetColor)) + : mTargetColor(ctrl->mTargetColor) , mBaseMaterial(baseMaterial) { if (!ctrl->mInterpolator.empty()) @@ -477,30 +477,31 @@ namespace NifOsg { osg::Vec3f value = mData.interpKey(getInputValue(nv)); osg::Material* mat = static_cast(stateset->getAttribute(osg::StateAttribute::MATERIAL)); + using TargetColor = Nif::NiMaterialColorController::TargetColor; switch (mTargetColor) { - case Diffuse: + case TargetColor::Diffuse: { osg::Vec4f diffuse = mat->getDiffuse(osg::Material::FRONT_AND_BACK); diffuse.set(value.x(), value.y(), value.z(), diffuse.a()); mat->setDiffuse(osg::Material::FRONT_AND_BACK, diffuse); break; } - case Specular: + case TargetColor::Specular: { osg::Vec4f specular = mat->getSpecular(osg::Material::FRONT_AND_BACK); specular.set(value.x(), value.y(), value.z(), specular.a()); mat->setSpecular(osg::Material::FRONT_AND_BACK, specular); break; } - case Emissive: + case TargetColor::Emissive: { osg::Vec4f emissive = mat->getEmission(osg::Material::FRONT_AND_BACK); emissive.set(value.x(), value.y(), value.z(), emissive.a()); mat->setEmission(osg::Material::FRONT_AND_BACK, emissive); break; } - case Ambient: + case TargetColor::Ambient: default: { osg::Vec4f ambient = mat->getAmbient(osg::Material::FRONT_AND_BACK); diff --git a/components/nifosg/controller.hpp b/components/nifosg/controller.hpp index 90e87366e1..1025f1988e 100644 --- a/components/nifosg/controller.hpp +++ b/components/nifosg/controller.hpp @@ -336,13 +336,6 @@ namespace NifOsg class MaterialColorController : public SceneUtil::StateSetUpdater, public SceneUtil::Controller { public: - enum TargetColor - { - Ambient = 0, - Diffuse = 1, - Specular = 2, - Emissive = 3 - }; MaterialColorController(const Nif::NiMaterialColorController* ctrl, const osg::Material* baseMaterial); MaterialColorController(); MaterialColorController(const MaterialColorController& copy, const osg::CopyOp& copyop); @@ -355,7 +348,7 @@ namespace NifOsg private: Vec3Interpolator mData; - TargetColor mTargetColor = Ambient; + Nif::NiMaterialColorController::TargetColor mTargetColor; osg::ref_ptr mBaseMaterial; }; diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 9683de9a23..8a4a62b017 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -988,18 +988,17 @@ namespace NifOsg { const Nif::NiMaterialColorController* matctrl = static_cast(ctrl.getPtr()); - if (matctrl->mData.empty() && matctrl->mInterpolator.empty()) + Nif::NiInterpolatorPtr interp = matctrl->mInterpolator; + if (matctrl->mData.empty() && interp.empty()) continue; - auto targetColor = static_cast(matctrl->mTargetColor); if (mVersion <= Nif::NIFFile::VER_MW - && targetColor == MaterialColorController::TargetColor::Specular) + && matctrl->mTargetColor == Nif::NiMaterialColorController::TargetColor::Specular) continue; - if (!matctrl->mInterpolator.empty() - && matctrl->mInterpolator->recType != Nif::RC_NiPoint3Interpolator) + if (!interp.empty() && interp->recType != Nif::RC_NiPoint3Interpolator) { Log(Debug::Error) << "Unsupported interpolator type for NiMaterialColorController " << matctrl->recIndex - << " in " << mFilename << ": " << matctrl->mInterpolator->recName; + << " in " << mFilename << ": " << interp->recName; continue; } osg::ref_ptr osgctrl = new MaterialColorController(matctrl, baseMaterial); From 735a948452b2c23f1ba9491fc333c0774220707c Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 13 Sep 2023 23:43:24 +0300 Subject: [PATCH 04/15] Refactor NiMultiTargetTransformController --- components/nif/controller.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index ee219fe5b5..0e08c4d255 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -305,17 +305,16 @@ namespace Nif void NiMultiTargetTransformController::read(NIFStream* nif) { NiInterpController::read(nif); - size_t numTargets = nif->getUShort(); - std::vector targets; - targets.resize(numTargets); - for (size_t i = 0; i < targets.size(); i++) - targets[i].read(nif); - mExtraTargets = targets; + + mExtraTargets.resize(nif->get()); + for (NiAVObjectPtr& extraTarget : mExtraTargets) + extraTarget.read(nif); } void NiMultiTargetTransformController::post(Reader& nif) { NiInterpController::post(nif); + postRecordList(nif, mExtraTargets); } From 6d82f8b00d006d693ae7b6531ff90c07f1a1d354 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 13 Sep 2023 23:55:26 +0300 Subject: [PATCH 05/15] Refactor NiKeyframeController and NiTransformInterpolator --- components/nif/controller.cpp | 19 +++++-------------- components/nif/controller.hpp | 6 ++---- components/nifosg/controller.cpp | 30 +++++++++++++++++------------- 3 files changed, 24 insertions(+), 31 deletions(-) diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index 0e08c4d255..7d6706aeae 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -292,6 +292,7 @@ namespace Nif void NiKeyframeController::read(NIFStream* nif) { NiSingleInterpController::read(nif); + if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103)) mData.read(nif); } @@ -299,6 +300,7 @@ namespace Nif void NiKeyframeController::post(Reader& nif) { NiSingleInterpController::post(nif); + mData.post(nif); } @@ -503,24 +505,13 @@ namespace Nif void NiTransformInterpolator::read(NIFStream* nif) { - defaultPos = nif->getVector3(); - nif->read(defaultRot); - 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); + nif->read(mDefaultTransform); + mData.read(nif); } void NiTransformInterpolator::post(Reader& nif) { - data.post(nif); + mData.post(nif); } void NiColorInterpolator::read(NIFStream* nif) diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index 4b46840d4a..24d5b17465 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -344,10 +344,8 @@ namespace Nif struct NiTransformInterpolator : public NiInterpolator { - osg::Vec3f defaultPos; - osg::Quat defaultRot; - float defaultScale; - NiKeyframeDataPtr data; + NiQuatTransform mDefaultTransform; + NiKeyframeDataPtr mData; void read(NIFStream* nif) override; void post(Reader& nif) override; diff --git a/components/nifosg/controller.cpp b/components/nifosg/controller.cpp index 8e9efba8a9..88a88f46be 100644 --- a/components/nifosg/controller.cpp +++ b/components/nifosg/controller.cpp @@ -90,21 +90,23 @@ namespace NifOsg { const Nif::NiTransformInterpolator* interp = static_cast(keyctrl->mInterpolator.getPtr()); - if (!interp->data.empty()) + const Nif::NiQuatTransform& defaultTransform = interp->mDefaultTransform; + if (!interp->mData.empty()) { - mRotations = QuaternionInterpolator(interp->data->mRotations, interp->defaultRot); - mXRotations = FloatInterpolator(interp->data->mXRotations); - mYRotations = FloatInterpolator(interp->data->mYRotations); - mZRotations = FloatInterpolator(interp->data->mZRotations); - mTranslations = Vec3Interpolator(interp->data->mTranslations, interp->defaultPos); - mScales = FloatInterpolator(interp->data->mScales, interp->defaultScale); - mAxisOrder = interp->data->mAxisOrder; + mRotations = QuaternionInterpolator(interp->mData->mRotations, defaultTransform.mRotation); + mXRotations = FloatInterpolator(interp->mData->mXRotations); + mYRotations = FloatInterpolator(interp->mData->mYRotations); + mZRotations = FloatInterpolator(interp->mData->mZRotations); + mTranslations = Vec3Interpolator(interp->mData->mTranslations, defaultTransform.mTranslation); + mScales = FloatInterpolator(interp->mData->mScales, defaultTransform.mScale); + + mAxisOrder = interp->mData->mAxisOrder; } else { - mRotations = QuaternionInterpolator(Nif::QuaternionKeyMapPtr(), interp->defaultRot); - mTranslations = Vec3Interpolator(Nif::Vector3KeyMapPtr(), interp->defaultPos); - mScales = FloatInterpolator(Nif::FloatKeyMapPtr(), interp->defaultScale); + mRotations = QuaternionInterpolator(Nif::QuaternionKeyMapPtr(), defaultTransform.mRotation); + mTranslations = Vec3Interpolator(Nif::Vector3KeyMapPtr(), defaultTransform.mTranslation); + mScales = FloatInterpolator(Nif::FloatKeyMapPtr(), defaultTransform.mScale); } } } @@ -117,6 +119,7 @@ namespace NifOsg mZRotations = FloatInterpolator(keydata->mZRotations); mTranslations = Vec3Interpolator(keydata->mTranslations); mScales = FloatInterpolator(keydata->mScales, 1.f); + mAxisOrder = keydata->mAxisOrder; } } @@ -177,11 +180,12 @@ namespace NifOsg else node->setRotation(node->mRotationScale); + if (!mTranslations.empty()) + node->setTranslation(mTranslations.interpKey(time)); + if (!mScales.empty()) node->setScale(mScales.interpKey(time)); - if (!mTranslations.empty()) - node->setTranslation(mTranslations.interpKey(time)); } traverse(node, nv); From 19d1f6f3f5a6b7610fed2843ebbd735921035c59 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 14 Sep 2023 00:15:02 +0300 Subject: [PATCH 06/15] Rewrite typed NiInterpolator loading --- components/nif/controller.cpp | 55 -------------------------------- components/nif/controller.hpp | 53 +++++++++++------------------- components/nif/data.cpp | 2 +- components/nif/data.hpp | 5 +-- components/nif/nifkey.hpp | 4 +-- components/nifosg/controller.cpp | 9 +++--- components/nifosg/controller.hpp | 14 ++++---- 7 files changed, 36 insertions(+), 106 deletions(-) diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index 7d6706aeae..7a8bb31152 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -470,61 +470,6 @@ namespace Nif mObjectPalette.post(nif); } - void NiPoint3Interpolator::read(NIFStream* nif) - { - defaultVal = nif->getVector3(); - data.read(nif); - } - - void NiPoint3Interpolator::post(Reader& nif) - { - data.post(nif); - } - - void NiBoolInterpolator::read(NIFStream* nif) - { - defaultVal = nif->getBoolean(); - data.read(nif); - } - - void NiBoolInterpolator::post(Reader& nif) - { - data.post(nif); - } - - void NiFloatInterpolator::read(NIFStream* nif) - { - defaultVal = nif->getFloat(); - data.read(nif); - } - - void NiFloatInterpolator::post(Reader& nif) - { - data.post(nif); - } - - void NiTransformInterpolator::read(NIFStream* nif) - { - nif->read(mDefaultTransform); - mData.read(nif); - } - - void NiTransformInterpolator::post(Reader& nif) - { - mData.post(nif); - } - - void NiColorInterpolator::read(NIFStream* nif) - { - defaultVal = nif->getVector4(); - data.read(nif); - } - - void NiColorInterpolator::post(Reader& nif) - { - data.post(nif); - } - void NiBlendInterpolator::read(NIFStream* nif) { if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 112)) diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index 24d5b17465..1a6847a5b7 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -318,46 +318,29 @@ namespace Nif { }; - struct NiPoint3Interpolator : public NiInterpolator + template + struct TypedNiInterpolator : public NiInterpolator { - osg::Vec3f defaultVal; - NiPosDataPtr data; - void read(NIFStream* nif) override; - void post(Reader& nif) override; - }; - - struct NiBoolInterpolator : public NiInterpolator - { - char defaultVal; - NiBoolDataPtr data; - void read(NIFStream* nif) override; - void post(Reader& nif) override; - }; - - struct NiFloatInterpolator : public NiInterpolator - { - float defaultVal; - NiFloatDataPtr data; - void read(NIFStream* nif) override; - void post(Reader& nif) override; - }; + T mDefaultValue; + DataPtr mData; - struct NiTransformInterpolator : public NiInterpolator - { - NiQuatTransform mDefaultTransform; - NiKeyframeDataPtr mData; + void read(NIFStream* nif) override + { + nif->read(mDefaultValue); + mData.read(nif); + } - void read(NIFStream* nif) override; - void post(Reader& nif) override; + void post(Reader& nif) override + { + mData.post(nif); + } }; - struct NiColorInterpolator : public NiInterpolator - { - osg::Vec4f defaultVal; - NiColorDataPtr data; - void read(NIFStream* nif) override; - void post(Reader& nif) override; - }; + using NiPoint3Interpolator = TypedNiInterpolator; + using NiBoolInterpolator = TypedNiInterpolator; + using NiFloatInterpolator = TypedNiInterpolator; + using NiTransformInterpolator = TypedNiInterpolator; + using NiColorInterpolator = TypedNiInterpolator; // Abstract struct NiBlendInterpolator : public NiInterpolator diff --git a/components/nif/data.cpp b/components/nif/data.cpp index a07f66d43f..528256c49b 100644 --- a/components/nif/data.cpp +++ b/components/nif/data.cpp @@ -528,7 +528,7 @@ namespace Nif void NiBoolData::read(NIFStream* nif) { - mKeyList = std::make_shared(); + mKeyList = std::make_shared(); mKeyList->read(nif); } diff --git a/components/nif/data.hpp b/components/nif/data.hpp index 849cbde7bd..6ec09c2f42 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -219,7 +219,7 @@ namespace Nif struct NiVisData : public Record { - // TODO: investigate possible use of ByteKeyMap + // TODO: investigate possible use of BoolKeyMap std::shared_ptr> mKeys; void read(NIFStream* nif) override; @@ -357,7 +357,8 @@ namespace Nif struct NiBoolData : public Record { - ByteKeyMapPtr mKeyList; + BoolKeyMapPtr mKeyList; + void read(NIFStream* nif) override; }; diff --git a/components/nif/nifkey.hpp b/components/nif/nifkey.hpp index bbd06cb048..604cf92c33 100644 --- a/components/nif/nifkey.hpp +++ b/components/nif/nifkey.hpp @@ -152,13 +152,13 @@ namespace Nif using Vector3KeyMap = KeyMapT>; using Vector4KeyMap = KeyMapT>; using QuaternionKeyMap = KeyMapT>; - using ByteKeyMap = KeyMapT>; + using BoolKeyMap = KeyMapT>; using FloatKeyMapPtr = std::shared_ptr; using Vector3KeyMapPtr = std::shared_ptr; using Vector4KeyMapPtr = std::shared_ptr; using QuaternionKeyMapPtr = std::shared_ptr; - using ByteKeyMapPtr = std::shared_ptr; + using BoolKeyMapPtr = std::shared_ptr; } // Namespace #endif //#ifndef OPENMW_COMPONENTS_NIF_NIFKEY_HPP diff --git a/components/nifosg/controller.cpp b/components/nifosg/controller.cpp index 88a88f46be..018b650dbd 100644 --- a/components/nifosg/controller.cpp +++ b/components/nifosg/controller.cpp @@ -90,7 +90,7 @@ namespace NifOsg { const Nif::NiTransformInterpolator* interp = static_cast(keyctrl->mInterpolator.getPtr()); - const Nif::NiQuatTransform& defaultTransform = interp->mDefaultTransform; + const Nif::NiQuatTransform& defaultTransform = interp->mDefaultValue; if (!interp->mData.empty()) { mRotations = QuaternionInterpolator(interp->mData->mRotations, defaultTransform.mRotation); @@ -318,9 +318,10 @@ namespace NifOsg { if (!ctrl->mInterpolator.empty()) { - if (ctrl->mInterpolator->recType == Nif::RC_NiBoolInterpolator) - mInterpolator - = ByteInterpolator(static_cast(ctrl->mInterpolator.getPtr())); + if (ctrl->mInterpolator->recType != Nif::RC_NiBoolInterpolator) + return; + + mInterpolator = { static_cast(ctrl->mInterpolator.getPtr()) }; } else if (!ctrl->mData.empty()) mData = ctrl->mData->mKeys; diff --git a/components/nifosg/controller.hpp b/components/nifosg/controller.hpp index 1025f1988e..613aa7dc16 100644 --- a/components/nifosg/controller.hpp +++ b/components/nifosg/controller.hpp @@ -66,15 +66,15 @@ namespace NifOsg typename = std::enable_if_t, std::is_same, std::is_same, - std::is_same, std::is_same>, - std::is_same>, + std::is_same>, + std::is_same>, T>> ValueInterpolator(const T* interpolator) - : mDefaultVal(interpolator->defaultVal) + : mDefaultVal(interpolator->mDefaultValue) { - if (interpolator->data.empty()) + if (interpolator->mData.empty()) return; - mKeys = interpolator->data->mKeyList; + mKeys = interpolator->mData->mKeyList; if (mKeys) { mLastLowKey = mKeys->mKeys.end(); @@ -182,7 +182,7 @@ namespace NifOsg using FloatInterpolator = ValueInterpolator; using Vec3Interpolator = ValueInterpolator; using Vec4Interpolator = ValueInterpolator; - using ByteInterpolator = ValueInterpolator; + using BoolInterpolator = ValueInterpolator; class ControllerFunction : public SceneUtil::ControllerFunction { @@ -283,7 +283,7 @@ namespace NifOsg { private: std::shared_ptr> mData; - ByteInterpolator mInterpolator; + BoolInterpolator mInterpolator; unsigned int mMask{ 0u }; bool calculate(float time) const; From 05d8975ed1a78dcf858c5a8c2c03b3552656119a Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 14 Sep 2023 01:21:21 +0300 Subject: [PATCH 07/15] Revise various NIF controller records Mostly those that don't require external changes --- apps/openmw_test_suite/nif/node.hpp | 2 +- components/nif/base.hpp | 2 +- components/nif/controller.cpp | 164 ++++++++++++++++------------ components/nif/controller.hpp | 39 ++++--- components/nif/property.hpp | 2 +- 5 files changed, 122 insertions(+), 87 deletions(-) diff --git a/apps/openmw_test_suite/nif/node.hpp b/apps/openmw_test_suite/nif/node.hpp index b39729c876..c606fe67e5 100644 --- a/apps/openmw_test_suite/nif/node.hpp +++ b/apps/openmw_test_suite/nif/node.hpp @@ -63,7 +63,7 @@ namespace Nif::Testing value.phase = 0; value.timeStart = 0; value.timeStop = 0; - value.target = NiObjectNETPtr(nullptr); + value.mTarget = NiObjectNETPtr(nullptr); } } diff --git a/components/nif/base.hpp b/components/nif/base.hpp index 6b4d5710b4..a24359772d 100644 --- a/components/nif/base.hpp +++ b/components/nif/base.hpp @@ -40,7 +40,7 @@ namespace Nif int flags; float frequency, phase; float timeStart, timeStop; - NiObjectNETPtr target; + NiObjectNETPtr mTarget; void read(NIFStream* nif) override; void post(Reader& nif) override; diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index 7a8bb31152..a3c81f96da 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -1,6 +1,7 @@ #include "controller.hpp" #include "data.hpp" +#include "exception.hpp" #include "node.hpp" #include "particle.hpp" #include "texture.hpp" @@ -13,20 +14,17 @@ namespace Nif next.read(nif); flags = nif->getUShort(); - frequency = nif->getFloat(); phase = nif->getFloat(); timeStart = nif->getFloat(); timeStop = nif->getFloat(); - - target.read(nif); + mTarget.read(nif); } void Controller::post(Reader& nif) { - Record::post(nif); next.post(nif); - target.post(nif); + mTarget.post(nif); } void ControlledBlock::read(NIFStream* nif) @@ -44,28 +42,28 @@ namespace Nif if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 110)) { mBlendInterpolator.read(nif); - mBlendIndex = nif->getUShort(); + nif->read(mBlendIndex); } if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 106) && nif->getBethVersion() > 0) - mPriority = nif->getChar(); + nif->read(mPriority); if (nif->getVersion() >= NIFStream::generateVersion(10, 2, 0, 0) && nif->getVersion() <= NIFStream::generateVersion(20, 1, 0, 0)) { mStringPalette.read(nif); - mNodeNameOffset = nif->getUInt(); - mPropertyTypeOffset = nif->getUInt(); - mControllerTypeOffset = nif->getUInt(); - mControllerIdOffset = nif->getUInt(); - mInterpolatorIdOffset = nif->getUInt(); + nif->read(mNodeNameOffset); + nif->read(mPropertyTypeOffset); + nif->read(mControllerTypeOffset); + nif->read(mControllerIdOffset); + nif->read(mInterpolatorIdOffset); } else { - mNodeName = nif->getString(); - mPropertyType = nif->getString(); - mControllerType = nif->getString(); - mControllerId = nif->getString(); - mInterpolatorId = nif->getString(); + nif->read(mNodeName); + nif->read(mPropertyType); + nif->read(mControllerType); + nif->read(mControllerId); + nif->read(mInterpolatorId); } } @@ -80,16 +78,17 @@ namespace Nif void NiSequence::read(NIFStream* nif) { - mName = nif->getString(); + nif->read(mName); if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103)) { - mAccumRootName = nif->getString(); + nif->read(mAccumRootName); mTextKeys.read(nif); } - size_t numControlledBlocks = nif->getUInt(); + uint32_t numBlocks; + nif->read(numBlocks); if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 106)) - mArrayGrowBy = nif->getUInt(); - mControlledBlocks.resize(numControlledBlocks); + nif->read(mArrayGrowBy); + mControlledBlocks.resize(numBlocks); for (ControlledBlock& block : mControlledBlocks) block.read(nif); } @@ -104,28 +103,30 @@ namespace Nif void NiControllerSequence::read(NIFStream* nif) { NiSequence::read(nif); + if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103)) return; - mWeight = nif->getFloat(); + nif->read(mWeight); mTextKeys.read(nif); mExtrapolationMode = static_cast(nif->getUInt()); mFrequency = nif->getFloat(); if (nif->getVersion() <= NIFStream::generateVersion(10, 4, 0, 1)) - mPhase = nif->getFloat(); - mStartTime = nif->getFloat(); - mStopTime = nif->getFloat(); - mPlayBackwards = nif->getVersion() == NIFStream::generateVersion(10, 1, 0, 106) && nif->getBoolean(); + nif->read(mPhase); + nif->read(mStartTime); + nif->read(mStopTime); + if (nif->getVersion() == NIFStream::generateVersion(10, 1, 0, 106)) + nif->read(mPlayBackwards); mManager.read(nif); - mAccumRootName = nif->getString(); + nif->read(mAccumRootName); if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 113) && nif->getVersion() <= NIFStream::generateVersion(20, 1, 0, 0)) mStringPalette.read(nif); else if (nif->getVersion() >= NIFFile::NIFVersion::VER_BGS && nif->getBethVersion() >= 24) { - size_t numAnimNotes = 1; + uint16_t numAnimNotes = 1; if (nif->getBethVersion() >= 29) - numAnimNotes = nif->getUShort(); + nif->read(numAnimNotes); nif->skip(4 * numAnimNotes); // BSAnimNotes links } @@ -134,6 +135,7 @@ namespace Nif void NiControllerSequence::post(Reader& nif) { NiSequence::post(nif); + mManager.post(nif); mStringPalette.post(nif); } @@ -141,14 +143,16 @@ namespace Nif void NiInterpController::read(NIFStream* nif) { Controller::read(nif); + if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 104) && nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 108)) - mManagerControlled = nif->getBoolean(); + nif->read(mManagerControlled); } void NiSingleInterpController::read(NIFStream* nif) { NiInterpController::read(nif); + if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 104)) mInterpolator.read(nif); } @@ -156,6 +160,7 @@ namespace Nif void NiSingleInterpController::post(Reader& nif) { NiInterpController::post(nif); + mInterpolator.post(nif); } @@ -216,6 +221,7 @@ namespace Nif void NiParticleSystemController::post(Reader& nif) { Controller::post(nif); + emitter.post(nif); affectors.post(nif); colliders.post(nif); @@ -244,15 +250,17 @@ namespace Nif void NiLookAtController::read(NIFStream* nif) { Controller::read(nif); + if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0)) - lookAtFlags = nif->getUShort(); - target.read(nif); + nif->read(mLookAtFlags); + mLookAt.read(nif); } void NiLookAtController::post(Reader& nif) { Controller::post(nif); - target.post(nif); + + mLookAt.post(nif); } void NiPathController::read(NIFStream* nif) @@ -286,6 +294,7 @@ namespace Nif void NiUVController::post(Reader& nif) { Controller::post(nif); + data.post(nif); } @@ -323,6 +332,7 @@ namespace Nif void NiAlphaController::read(NIFStream* nif) { NiFloatInterpController::read(nif); + if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103)) mData.read(nif); } @@ -330,12 +340,14 @@ namespace Nif void NiAlphaController::post(Reader& nif) { NiFloatInterpController::post(nif); + mData.post(nif); } void NiRollController::read(NIFStream* nif) { NiSingleInterpController::read(nif); + if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103)) mData.read(nif); } @@ -343,49 +355,47 @@ namespace Nif void NiRollController::post(Reader& nif) { NiSingleInterpController::post(nif); + mData.post(nif); } void NiGeomMorpherController::read(NIFStream* nif) { NiInterpController::read(nif); + if (nif->getVersion() >= NIFFile::NIFVersion::VER_OB_OLD) - mUpdateNormals = nif->getUShort() & 1; + mUpdateNormals = nif->get() & 1; mData.read(nif); - if (nif->getVersion() >= NIFFile::NIFVersion::VER_MW) + + if (nif->getVersion() < NIFFile::NIFVersion::VER_MW) + return; + + mAlwaysActive = nif->get() != 0; + + if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 105)) + return; + + if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB) { - mAlwaysActive = nif->getChar(); - if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 106)) - { - if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB) - { - readRecordList(nif, mInterpolators); - if (nif->getVersion() >= NIFStream::generateVersion(10, 2, 0, 0) && nif->getBethVersion() > 9) - { - unsigned int numUnknown = nif->getUInt(); - nif->skip(4 * numUnknown); - } - } - else - { - 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; - } - } + readRecordList(nif, mInterpolators); + if (nif->getVersion() >= NIFStream::generateVersion(10, 2, 0, 0) && nif->getBethVersion() >= 10) + nif->skip(4 * nif->get()); // Unknown + return; + } + + mInterpolators.resize(nif->get()); + mWeights.resize(mInterpolators.size()); + for (size_t i = 0; i < mInterpolators.size(); i++) + { + mInterpolators[i].read(nif); + nif->read(mWeights[i]); } } void NiGeomMorpherController::post(Reader& nif) { NiInterpController::post(nif); + mData.post(nif); postRecordList(nif, mInterpolators); } @@ -393,6 +403,7 @@ namespace Nif void NiVisController::read(NIFStream* nif) { NiBoolInterpController::read(nif); + if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103)) mData.read(nif); } @@ -400,17 +411,19 @@ namespace Nif void NiVisController::post(Reader& nif) { NiBoolInterpController::post(nif); + mData.post(nif); } void NiFlipController::read(NIFStream* nif) { NiFloatInterpController::read(nif); - mTexSlot = nif->getUInt(); + + mTexSlot = static_cast(nif->get()); if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103)) { - timeStart = nif->getFloat(); - mDelta = nif->getFloat(); + nif->read(timeStart); + nif->read(mDelta); } readRecordList(nif, mSources); } @@ -418,14 +431,16 @@ namespace Nif void NiFlipController::post(Reader& nif) { NiFloatInterpController::post(nif); + postRecordList(nif, mSources); } void NiTextureTransformController::read(NIFStream* nif) { NiFloatInterpController::read(nif); - mShaderMap = nif->getBoolean(); - nif->read(mTexSlot); + + nif->read(mShaderMap); + mTexSlot = static_cast(nif->get()); nif->read(mTransformMember); if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103)) mData.read(nif); @@ -434,31 +449,41 @@ namespace Nif void NiTextureTransformController::post(Reader& nif) { NiFloatInterpController::post(nif); + mData.post(nif); } void bhkBlendController::read(NIFStream* nif) { Controller::read(nif); - nif->getUInt(); // Zero + + uint32_t numKeys; + nif->read(numKeys); + // Is this possible? + if (numKeys != 0) + throw Nif::Exception( + "Unsupported keys in bhkBlendController " + std::to_string(recIndex), nif->getFile().getFilename()); } void BSEffectShaderPropertyFloatController::read(NIFStream* nif) { NiFloatInterpController::read(nif); + nif->read(mControlledVariable); } void BSEffectShaderPropertyColorController::read(NIFStream* nif) { NiPoint3InterpController::read(nif); + nif->read(mControlledColor); } void NiControllerManager::read(NIFStream* nif) { Controller::read(nif); - mCumulative = nif->getBoolean(); + + nif->read(mCumulative); readRecordList(nif, mSequences); mObjectPalette.read(nif); } @@ -466,6 +491,7 @@ namespace Nif void NiControllerManager::post(Reader& nif) { Controller::post(nif); + postRecordList(nif, mSequences); mObjectPalette.post(nif); } diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index 1a6847a5b7..730cda5bd6 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -14,14 +14,14 @@ namespace Nif NiInterpolatorPtr mInterpolator; ControllerPtr mController; NiBlendInterpolatorPtr mBlendInterpolator; - unsigned short mBlendIndex; - unsigned char mPriority; + uint16_t mBlendIndex; + uint8_t mPriority; NiStringPalettePtr mStringPalette; - size_t mNodeNameOffset; - size_t mPropertyTypeOffset; - size_t mControllerTypeOffset; - size_t mControllerIdOffset; - size_t mInterpolatorIdOffset; + uint32_t mNodeNameOffset; + uint32_t mPropertyTypeOffset; + uint32_t mControllerTypeOffset; + uint32_t mControllerIdOffset; + uint32_t mInterpolatorIdOffset; std::string mNodeName; std::string mPropertyType; std::string mControllerType; @@ -38,7 +38,7 @@ namespace Nif std::string mName; std::string mAccumRootName; ExtraPtr mTextKeys; - unsigned int mArrayGrowBy; + uint32_t mArrayGrowBy; std::vector mControlledBlocks; void read(NIFStream* nif) override; @@ -197,8 +197,15 @@ namespace Nif struct NiLookAtController : public Controller { - NiAVObjectPtr target; - unsigned short lookAtFlags{ 0 }; + enum Flags + { + Flag_Flip = 0x1, + Flag_LookYAxis = 0x2, + Flag_LookZAxis = 0x4, + }; + + uint16_t mLookAtFlags{ 0 }; + NiAVObjectPtr mLookAt; void read(NIFStream* nif) override; void post(Reader& nif) override; @@ -267,7 +274,7 @@ namespace Nif struct NiFlipController : public NiFloatInterpController { - int mTexSlot; // NiTexturingProperty::TextureType + NiTexturingProperty::TextureType mTexSlot; float mDelta; // Time between two flips. delta = (start_time - stop_time) / num_sources NiSourceTextureList mSources; @@ -278,8 +285,8 @@ namespace Nif struct NiTextureTransformController : public NiFloatInterpController { bool mShaderMap; - int mTexSlot; // NiTexturingProperty::TextureType - unsigned int mTransformMember; + NiTexturingProperty::TextureType mTexSlot; + uint32_t mTransformMember; NiFloatDataPtr mData; void read(NIFStream* nif) override; @@ -293,14 +300,14 @@ namespace Nif struct BSEffectShaderPropertyFloatController : public NiFloatInterpController { - unsigned int mControlledVariable; + uint32_t mControlledVariable; void read(NIFStream* nif) override; }; struct BSEffectShaderPropertyColorController : public NiPoint3InterpController { - unsigned int mControlledColor; + uint32_t mControlledColor; void read(NIFStream* nif) override; }; @@ -310,10 +317,12 @@ namespace Nif bool mCumulative; NiControllerSequenceList mSequences; NiDefaultAVObjectPalettePtr mObjectPalette; + void read(NIFStream* nif) override; void post(Reader& nif) override; }; + // Abstract struct NiInterpolator : public Record { }; diff --git a/components/nif/property.hpp b/components/nif/property.hpp index 90f1e9ffb5..d9574f31d6 100644 --- a/components/nif/property.hpp +++ b/components/nif/property.hpp @@ -79,7 +79,7 @@ namespace Nif * 5 - Bump map texture * 6 - Decal texture */ - enum TextureType + enum TextureType : uint32_t { BaseTexture = 0, DarkTexture = 1, From b0dfd7456210ea52e98fc9c809c8865fa5eaa045 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 14 Sep 2023 01:54:27 +0300 Subject: [PATCH 08/15] NIFStream: remove getBoolean, getString --- components/nif/nifstream.hpp | 2 -- components/nif/node.cpp | 8 ++++---- components/nif/property.cpp | 4 ++-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/components/nif/nifstream.hpp b/components/nif/nifstream.hpp index c1f7cfdf12..8a4ec847fc 100644 --- a/components/nif/nifstream.hpp +++ b/components/nif/nifstream.hpp @@ -156,8 +156,6 @@ namespace Nif osg::Vec2f getVector2() { return get(); } osg::Vec3f getVector3() { return get(); } osg::Vec4f getVector4() { return get(); } - bool getBoolean() { return get(); } - std::string getString() { return get(); } }; template <> diff --git a/components/nif/node.cpp b/components/nif/node.cpp index ad966097b0..a9e4f183b2 100644 --- a/components/nif/node.cpp +++ b/components/nif/node.cpp @@ -153,8 +153,8 @@ namespace Nif if (nif->getVersion() < NIFStream::generateVersion(10, 0, 1, 0)) return; unsigned int num = 0; - if (nif->getVersion() <= NIFStream::generateVersion(20, 1, 0, 3)) - num = nif->getBoolean(); // Has Shader + if (nif->getVersion() <= NIFStream::generateVersion(20, 1, 0, 3) && nif->get()) + num = 1; else if (nif->getVersion() >= NIFStream::generateVersion(20, 2, 0, 5)) num = nif->getUInt(); @@ -163,7 +163,7 @@ namespace Nif if (nif->getVersion() >= NIFStream::generateVersion(20, 2, 0, 5)) active = nif->getUInt(); if (nif->getVersion() >= NIFFile::NIFVersion::VER_BGS) - needsUpdate = nif->getBoolean(); + nif->read(needsUpdate); } void NiGeometry::read(NIFStream* nif) @@ -210,7 +210,7 @@ namespace Nif nearDist = nif->getFloat(); farDist = nif->getFloat(); if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0)) - orthographic = nif->getBoolean(); + nif->read(orthographic); vleft = nif->getFloat(); vright = nif->getFloat(); vtop = nif->getFloat(); diff --git a/components/nif/property.cpp b/components/nif/property.cpp index 39a7cbff23..3569fd55cc 100644 --- a/components/nif/property.cpp +++ b/components/nif/property.cpp @@ -8,7 +8,7 @@ namespace Nif void NiTexturingProperty::Texture::read(NIFStream* nif) { - inUse = nif->getBoolean(); + nif->read(inUse); if (!inUse) return; @@ -36,7 +36,7 @@ namespace Nif nif->skip(2); // Unknown short else if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0)) { - if (nif->getBoolean()) // Has texture transform + if (nif->get()) // Has texture transform { nif->getVector2(); // UV translation nif->getVector2(); // UV scale From ca8582043169a960a61909ae56204d2a6b980f40 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 14 Sep 2023 02:00:05 +0300 Subject: [PATCH 09/15] Refactor NiUVController --- components/nif/controller.cpp | 6 +++--- components/nif/controller.hpp | 4 ++-- components/nifosg/controller.cpp | 8 +++----- components/nifosg/controller.hpp | 6 +++--- components/nifosg/nifloader.cpp | 11 +++++------ 5 files changed, 16 insertions(+), 19 deletions(-) diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index a3c81f96da..84c43bafcf 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -287,15 +287,15 @@ namespace Nif { Controller::read(nif); - uvSet = nif->getUShort(); - data.read(nif); + nif->read(mUvSet); + mData.read(nif); } void NiUVController::post(Reader& nif) { Controller::post(nif); - data.post(nif); + mData.post(nif); } void NiKeyframeController::read(NIFStream* nif) diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index 730cda5bd6..87bfe615a0 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -213,8 +213,8 @@ namespace Nif struct NiUVController : public Controller { - NiUVDataPtr data; - unsigned int uvSet; + NiUVDataPtr mData; + uint16_t mUvSet; void read(NIFStream* nif) override; void post(Reader& nif) override; diff --git a/components/nifosg/controller.cpp b/components/nifosg/controller.cpp index 018b650dbd..d424d7f56b 100644 --- a/components/nifosg/controller.cpp +++ b/components/nifosg/controller.cpp @@ -255,9 +255,7 @@ namespace NifOsg } } - UVController::UVController() {} - - UVController::UVController(const Nif::NiUVData* data, const std::set& textureUnits) + UVController::UVController(const Nif::NiUVData* data, const std::set& textureUnits) : mUTrans(data->mKeyList[0], 0.f) , mVTrans(data->mKeyList[1], 0.f) , mUScale(data->mKeyList[2], 1.f) @@ -281,8 +279,8 @@ namespace NifOsg void UVController::setDefaults(osg::StateSet* stateset) { osg::ref_ptr texMat(new osg::TexMat); - for (std::set::const_iterator it = mTextureUnits.begin(); it != mTextureUnits.end(); ++it) - stateset->setTextureAttributeAndModes(*it, texMat, osg::StateAttribute::ON); + for (unsigned int unit : mTextureUnits) + stateset->setTextureAttributeAndModes(unit, texMat, osg::StateAttribute::ON); } void UVController::apply(osg::StateSet* stateset, osg::NodeVisitor* nv) diff --git a/components/nifosg/controller.hpp b/components/nifosg/controller.hpp index 613aa7dc16..f830cf1c4c 100644 --- a/components/nifosg/controller.hpp +++ b/components/nifosg/controller.hpp @@ -262,9 +262,9 @@ namespace NifOsg class UVController : public SceneUtil::StateSetUpdater, public SceneUtil::Controller { public: - UVController(); + UVController() = default; UVController(const UVController&, const osg::CopyOp&); - UVController(const Nif::NiUVData* data, const std::set& textureUnits); + UVController(const Nif::NiUVData* data, const std::set& textureUnits); META_Object(NifOsg, UVController) @@ -276,7 +276,7 @@ namespace NifOsg FloatInterpolator mVTrans; FloatInterpolator mUScale; FloatInterpolator mVScale; - std::set mTextureUnits; + std::set mTextureUnits; }; class VisController : public SceneUtil::NodeCallback, public SceneUtil::Controller diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 8a4a62b017..76dfd7a315 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -865,18 +865,17 @@ namespace NifOsg if (ctrl->recType == Nif::RC_NiUVController) { const Nif::NiUVController* niuvctrl = static_cast(ctrl.getPtr()); - if (niuvctrl->data.empty()) + if (niuvctrl->mData.empty()) continue; - const unsigned int uvSet = niuvctrl->uvSet; - std::set texUnits; - // UVController should work only for textures which use a given UV Set, usually 0. + std::set texUnits; + // UVController should only work for textures which use the given UV Set. for (unsigned int i = 0; i < boundTextures.size(); ++i) { - if (boundTextures[i] == uvSet) + if (boundTextures[i] == niuvctrl->mUvSet) texUnits.insert(i); } - osg::ref_ptr uvctrl = new UVController(niuvctrl->data.getPtr(), texUnits); + osg::ref_ptr uvctrl = new UVController(niuvctrl->mData.getPtr(), texUnits); setupController(niuvctrl, uvctrl, animflags); composite->addController(uvctrl); } From 04d3f6a42d13a600fe62bd08b9b92dcd8eea2a76 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 14 Sep 2023 02:20:18 +0300 Subject: [PATCH 10/15] Update NiPathController Support 10.1.0.0+ NiPathController loading --- components/nif/controller.cpp | 21 +++++++++++++-------- components/nif/controller.hpp | 26 ++++++++++++++------------ components/nifosg/controller.cpp | 6 +++--- components/nifosg/nifloader.cpp | 2 +- 4 files changed, 31 insertions(+), 24 deletions(-) diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index 84c43bafcf..d9e6d657d7 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -267,20 +267,25 @@ namespace Nif { Controller::read(nif); - bankDir = nif->getInt(); - maxBankAngle = nif->getFloat(); - smoothing = nif->getFloat(); - nif->read(followAxis); - posData.read(nif); - floatData.read(nif); + if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0)) + nif->read(mPathFlags); + else + mPathFlags = (flags >> 16); + + nif->read(mBankDirection); + nif->read(mMaxBankAngle); + nif->read(mSmoothing); + nif->read(mFollowAxis); + mPathData.read(nif); + mPercentData.read(nif); } void NiPathController::post(Reader& nif) { Controller::post(nif); - posData.post(nif); - floatData.post(nif); + mPathData.post(nif); + mPercentData.post(nif); } void NiUVController::read(NIFStream* nif) diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index 87bfe615a0..046ddc2e5c 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -174,22 +174,24 @@ namespace Nif struct NiPathController : public Controller { - NiPosDataPtr posData; - NiFloatDataPtr floatData; - enum Flags { - Flag_OpenCurve = 0x020, - Flag_AllowFlip = 0x040, - Flag_Bank = 0x080, - Flag_ConstVelocity = 0x100, - Flag_Follow = 0x200, - Flag_FlipFollowAxis = 0x400 + Flag_CVDataNeedsUpdate = 0x01, + Flag_OpenCurve = 0x02, + Flag_AllowFlip = 0x04, + Flag_Bank = 0x08, + Flag_ConstVelocity = 0x10, + Flag_Follow = 0x20, + Flag_FlipFollowAxis = 0x40, }; - int bankDir; - float maxBankAngle, smoothing; - uint16_t followAxis; + uint16_t mPathFlags; + int32_t mBankDirection; + float mMaxBankAngle; + float mSmoothing; + uint16_t mFollowAxis; + NiPosDataPtr mPathData; + NiFloatDataPtr mPercentData; void read(NIFStream* nif) override; void post(Reader& nif) override; diff --git a/components/nifosg/controller.cpp b/components/nifosg/controller.cpp index d424d7f56b..3d83c63721 100644 --- a/components/nifosg/controller.cpp +++ b/components/nifosg/controller.cpp @@ -598,9 +598,9 @@ namespace NifOsg } PathController::PathController(const Nif::NiPathController* ctrl) - : mPath(ctrl->posData->mKeyList, osg::Vec3f()) - , mPercent(ctrl->floatData->mKeyList, 1.f) - , mFlags(ctrl->flags) + : mPath(ctrl->mPathData->mKeyList, osg::Vec3f()) + , mPercent(ctrl->mPercentData->mKeyList, 1.f) + , mFlags(ctrl->mPathFlags) { } diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 76dfd7a315..96740b8dd3 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -907,7 +907,7 @@ namespace NifOsg else if (ctrl->recType == Nif::RC_NiPathController) { const Nif::NiPathController* path = static_cast(ctrl.getPtr()); - if (path->posData.empty() || path->floatData.empty()) + if (path->mPathData.empty() || path->mPercentData.empty()) continue; osg::ref_ptr callback(new PathController(path)); setupController(path, callback, animflags); From 0fe095303fed16d3ea91172988e79243bc3370db Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 14 Sep 2023 02:46:20 +0300 Subject: [PATCH 11/15] Rename Controller->NiTimeController, update NiTimeController and related code --- apps/openmw_test_suite/nif/node.hpp | 16 +++--- .../nifloader/testbulletnifloader.cpp | 10 ++-- components/nif/base.hpp | 16 +++--- components/nif/controller.cpp | 54 +++++++++---------- components/nif/controller.hpp | 20 +++---- components/nif/particle.hpp | 2 +- components/nif/recordptr.hpp | 4 +- components/nifbullet/bulletnifloader.cpp | 2 +- components/nifosg/controller.cpp | 16 +++--- components/nifosg/controller.hpp | 4 +- components/nifosg/nifloader.cpp | 22 ++++---- 11 files changed, 83 insertions(+), 83 deletions(-) diff --git a/apps/openmw_test_suite/nif/node.hpp b/apps/openmw_test_suite/nif/node.hpp index c606fe67e5..e05a056b79 100644 --- a/apps/openmw_test_suite/nif/node.hpp +++ b/apps/openmw_test_suite/nif/node.hpp @@ -20,7 +20,7 @@ namespace Nif::Testing { value.mExtra = ExtraPtr(nullptr); value.mExtraList = ExtraList(); - value.mController = ControllerPtr(nullptr); + value.mController = NiTimeControllerPtr(nullptr); } inline void init(NiAVObject& value) @@ -55,14 +55,14 @@ namespace Nif::Testing value.mRoot = NiAVObjectPtr(nullptr); } - inline void init(Controller& value) + inline void init(NiTimeController& value) { - value.next = ControllerPtr(nullptr); - value.flags = 0; - value.frequency = 0; - value.phase = 0; - value.timeStart = 0; - value.timeStop = 0; + value.mNext = NiTimeControllerPtr(nullptr); + value.mFlags = 0; + value.mFrequency = 0; + value.mPhase = 0; + value.mTimeStart = 0; + value.mTimeStop = 0; value.mTarget = NiObjectNETPtr(nullptr); } } diff --git a/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp b/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp index fc6a21f62c..1971895936 100644 --- a/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp +++ b/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp @@ -300,7 +300,7 @@ namespace Nif::NiStringExtraData mNiStringExtraData; Nif::NiStringExtraData mNiStringExtraData2; Nif::NiIntegerExtraData mNiIntegerExtraData; - Nif::Controller mController; + Nif::NiTimeController mController; btTransform mTransform{ btMatrix3x3(btQuaternion(btVector3(1, 0, 0), 0.5f)), btVector3(1, 2, 3) }; btTransform mTransformScale2{ btMatrix3x3(btQuaternion(btVector3(1, 0, 0), 0.5f)), btVector3(2, 4, 6) }; btTransform mTransformScale3{ btMatrix3x3(btQuaternion(btVector3(1, 0, 0), 0.5f)), btVector3(3, 6, 9) }; @@ -817,11 +817,11 @@ namespace TEST_F(TestBulletNifLoader, for_tri_shape_child_node_with_controller_should_return_animated_shape) { mController.recType = Nif::RC_NiKeyframeController; - mController.flags |= Nif::Controller::Flag_Active; + mController.mFlags |= Nif::NiTimeController::Flag_Active; copy(mTransform, mNiTriShape.mTransform); mNiTriShape.mTransform.mScale = 3; mNiTriShape.mParents.push_back(&mNiNode); - mNiTriShape.mController = Nif::ControllerPtr(&mController); + mNiTriShape.mController = Nif::NiTimeControllerPtr(&mController); mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape) }; mNiNode.mTransform.mScale = 4; @@ -847,14 +847,14 @@ namespace TEST_F(TestBulletNifLoader, for_two_tri_shape_children_nodes_where_one_with_controller_should_return_animated_shape) { mController.recType = Nif::RC_NiKeyframeController; - mController.flags |= Nif::Controller::Flag_Active; + mController.mFlags |= Nif::NiTimeController::Flag_Active; copy(mTransform, mNiTriShape.mTransform); mNiTriShape.mTransform.mScale = 3; mNiTriShape.mParents.push_back(&mNiNode); copy(mTransform, mNiTriShape2.mTransform); mNiTriShape2.mTransform.mScale = 3; mNiTriShape2.mParents.push_back(&mNiNode); - mNiTriShape2.mController = Nif::ControllerPtr(&mController); + mNiTriShape2.mController = Nif::NiTimeControllerPtr(&mController); mNiNode.mChildren = Nif::NiAVObjectList{ Nif::NiAVObjectPtr(&mNiTriShape), Nif::NiAVObjectPtr(&mNiTriShape2), diff --git a/components/nif/base.hpp b/components/nif/base.hpp index a24359772d..ae4bda7753 100644 --- a/components/nif/base.hpp +++ b/components/nif/base.hpp @@ -21,7 +21,7 @@ namespace Nif void post(Reader& nif) override { mNext.post(nif); } }; - struct Controller : public Record + struct NiTimeController : public Record { enum Flags { @@ -36,17 +36,17 @@ namespace Nif Mask = 6 }; - ControllerPtr next; - int flags; - float frequency, phase; - float timeStart, timeStop; + NiTimeControllerPtr mNext; + uint16_t mFlags; + float mFrequency, mPhase; + float mTimeStart, mTimeStop; NiObjectNETPtr mTarget; void read(NIFStream* nif) override; void post(Reader& nif) override; - bool isActive() const { return flags & Flag_Active; } - ExtrapolationMode extrapolationMode() const { return static_cast(flags & Mask); } + bool isActive() const { return mFlags & Flag_Active; } + ExtrapolationMode extrapolationMode() const { return static_cast(mFlags & Mask); } }; /// Abstract object that has a name, extra data and controllers @@ -55,7 +55,7 @@ namespace Nif std::string mName; ExtraPtr mExtra; ExtraList mExtraList; - ControllerPtr mController; + NiTimeControllerPtr mController; void read(NIFStream* nif) override; void post(Reader& nif) override; diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index d9e6d657d7..17937b61af 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -9,21 +9,21 @@ namespace Nif { - void Controller::read(NIFStream* nif) + void NiTimeController::read(NIFStream* nif) { - next.read(nif); - - flags = nif->getUShort(); - frequency = nif->getFloat(); - phase = nif->getFloat(); - timeStart = nif->getFloat(); - timeStop = nif->getFloat(); - mTarget.read(nif); + mNext.read(nif); + nif->read(mFlags); + nif->read(mFrequency); + nif->read(mPhase); + nif->read(mTimeStart); + nif->read(mTimeStop); + if (nif->getVersion() >= NIFStream::generateVersion(3, 3, 0, 13)) + mTarget.read(nif); } - void Controller::post(Reader& nif) + void NiTimeController::post(Reader& nif) { - next.post(nif); + mNext.post(nif); mTarget.post(nif); } @@ -109,7 +109,7 @@ namespace Nif nif->read(mWeight); mTextKeys.read(nif); - mExtrapolationMode = static_cast(nif->getUInt()); + mExtrapolationMode = static_cast(nif->getUInt()); mFrequency = nif->getFloat(); if (nif->getVersion() <= NIFStream::generateVersion(10, 4, 0, 1)) nif->read(mPhase); @@ -142,7 +142,7 @@ namespace Nif void NiInterpController::read(NIFStream* nif) { - Controller::read(nif); + NiTimeController::read(nif); if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 104) && nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 108)) @@ -166,7 +166,7 @@ namespace Nif void NiParticleSystemController::read(NIFStream* nif) { - Controller::read(nif); + NiTimeController::read(nif); velocity = nif->getFloat(); velocityRandom = nif->getFloat(); @@ -220,7 +220,7 @@ namespace Nif void NiParticleSystemController::post(Reader& nif) { - Controller::post(nif); + NiTimeController::post(nif); emitter.post(nif); affectors.post(nif); @@ -234,7 +234,7 @@ namespace Nif if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0)) mTargetColor = static_cast(nif->get() & 3); else - mTargetColor = static_cast((flags >> 4) & 3); + mTargetColor = static_cast((mFlags >> 4) & 3); if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103)) mData.read(nif); @@ -249,7 +249,7 @@ namespace Nif void NiLookAtController::read(NIFStream* nif) { - Controller::read(nif); + NiTimeController::read(nif); if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0)) nif->read(mLookAtFlags); @@ -258,19 +258,19 @@ namespace Nif void NiLookAtController::post(Reader& nif) { - Controller::post(nif); + NiTimeController::post(nif); mLookAt.post(nif); } void NiPathController::read(NIFStream* nif) { - Controller::read(nif); + NiTimeController::read(nif); if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0)) nif->read(mPathFlags); else - mPathFlags = (flags >> 16); + mPathFlags = (mFlags >> 16); nif->read(mBankDirection); nif->read(mMaxBankAngle); @@ -282,7 +282,7 @@ namespace Nif void NiPathController::post(Reader& nif) { - Controller::post(nif); + NiTimeController::post(nif); mPathData.post(nif); mPercentData.post(nif); @@ -290,7 +290,7 @@ namespace Nif void NiUVController::read(NIFStream* nif) { - Controller::read(nif); + NiTimeController::read(nif); nif->read(mUvSet); mData.read(nif); @@ -298,7 +298,7 @@ namespace Nif void NiUVController::post(Reader& nif) { - Controller::post(nif); + NiTimeController::post(nif); mData.post(nif); } @@ -427,7 +427,7 @@ namespace Nif mTexSlot = static_cast(nif->get()); if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103)) { - nif->read(timeStart); + nif->read(mTimeStart); nif->read(mDelta); } readRecordList(nif, mSources); @@ -460,7 +460,7 @@ namespace Nif void bhkBlendController::read(NIFStream* nif) { - Controller::read(nif); + NiTimeController::read(nif); uint32_t numKeys; nif->read(numKeys); @@ -486,7 +486,7 @@ namespace Nif void NiControllerManager::read(NIFStream* nif) { - Controller::read(nif); + NiTimeController::read(nif); nif->read(mCumulative); readRecordList(nif, mSequences); @@ -495,7 +495,7 @@ namespace Nif void NiControllerManager::post(Reader& nif) { - Controller::post(nif); + NiTimeController::post(nif); postRecordList(nif, mSequences); mObjectPalette.post(nif); diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index 046ddc2e5c..5449e19f8d 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -12,7 +12,7 @@ namespace Nif { std::string mTargetName; NiInterpolatorPtr mInterpolator; - ControllerPtr mController; + NiTimeControllerPtr mController; NiBlendInterpolatorPtr mBlendInterpolator; uint16_t mBlendIndex; uint8_t mPriority; @@ -49,7 +49,7 @@ namespace Nif struct NiControllerSequence : public NiSequence { float mWeight{ 1.f }; - Controller::ExtrapolationMode mExtrapolationMode{ Controller::ExtrapolationMode::Constant }; + NiTimeController::ExtrapolationMode mExtrapolationMode{ NiTimeController::ExtrapolationMode::Constant }; float mFrequency{ 1.f }; float mPhase{ 1.f }; float mStartTime, mStopTime; @@ -62,7 +62,7 @@ namespace Nif }; // Base class for controllers that use NiInterpolators to animate objects. - struct NiInterpController : public Controller + struct NiInterpController : public NiTimeController { // Usually one of the flags. bool mManagerControlled{ false }; @@ -94,7 +94,7 @@ namespace Nif { }; - struct NiParticleSystemController : public Controller + struct NiParticleSystemController : public NiTimeController { enum BSPArrayController { @@ -151,7 +151,7 @@ namespace Nif void post(Reader& nif) override; bool noAutoAdjust() const { return emitFlags & EmitFlag_NoAutoAdjust; } - bool emitAtVertex() const { return flags & BSPArrayController_AtVertex; } + bool emitAtVertex() const { return mFlags & BSPArrayController_AtVertex; } }; using NiBSPArrayController = NiParticleSystemController; @@ -172,7 +172,7 @@ namespace Nif void post(Reader& nif) override; }; - struct NiPathController : public Controller + struct NiPathController : public NiTimeController { enum Flags { @@ -197,7 +197,7 @@ namespace Nif void post(Reader& nif) override; }; - struct NiLookAtController : public Controller + struct NiLookAtController : public NiTimeController { enum Flags { @@ -213,7 +213,7 @@ namespace Nif void post(Reader& nif) override; }; - struct NiUVController : public Controller + struct NiUVController : public NiTimeController { NiUVDataPtr mData; uint16_t mUvSet; @@ -295,7 +295,7 @@ namespace Nif void post(Reader& nif) override; }; - struct bhkBlendController : public Controller + struct bhkBlendController : public NiTimeController { void read(NIFStream* nif) override; }; @@ -314,7 +314,7 @@ namespace Nif void read(NIFStream* nif) override; }; - struct NiControllerManager : public Controller + struct NiControllerManager : public NiTimeController { bool mCumulative; NiControllerSequenceList mSequences; diff --git a/components/nif/particle.hpp b/components/nif/particle.hpp index 5590877294..328498210a 100644 --- a/components/nif/particle.hpp +++ b/components/nif/particle.hpp @@ -9,7 +9,7 @@ namespace Nif struct NiParticleModifier : public Record { NiParticleModifierPtr mNext; - ControllerPtr mController; + NiTimeControllerPtr mController; void read(NIFStream* nif) override; void post(Reader& nif) override; diff --git a/components/nif/recordptr.hpp b/components/nif/recordptr.hpp index 9f75b31d74..627e59cf0d 100644 --- a/components/nif/recordptr.hpp +++ b/components/nif/recordptr.hpp @@ -116,7 +116,7 @@ namespace Nif struct NiUVData; struct NiPosData; struct NiVisData; - struct Controller; + struct NiTimeController; struct NiObjectNET; struct NiSkinData; struct NiFloatData; @@ -157,7 +157,7 @@ namespace Nif using NiUVDataPtr = RecordPtrT; using NiPosDataPtr = RecordPtrT; using NiVisDataPtr = RecordPtrT; - using ControllerPtr = RecordPtrT; + using NiTimeControllerPtr = RecordPtrT; using NiObjectNETPtr = RecordPtrT; using NiSkinDataPtr = RecordPtrT; using NiMorphDataPtr = RecordPtrT; diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index bc207e52bf..59d5cd61d8 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -255,7 +255,7 @@ namespace NifBullet if (node.recType == Nif::RC_NiCollisionSwitch && !node.collisionActive()) return; - for (Nif::ControllerPtr ctrl = node.mController; !ctrl.empty(); ctrl = ctrl->next) + for (Nif::NiTimeControllerPtr ctrl = node.mController; !ctrl.empty(); ctrl = ctrl->mNext) { if (args.mAnimated) break; diff --git a/components/nifosg/controller.cpp b/components/nifosg/controller.cpp index 3d83c63721..45082d969a 100644 --- a/components/nifosg/controller.cpp +++ b/components/nifosg/controller.cpp @@ -15,11 +15,11 @@ namespace NifOsg { - ControllerFunction::ControllerFunction(const Nif::Controller* ctrl) - : mFrequency(ctrl->frequency) - , mPhase(ctrl->phase) - , mStartTime(ctrl->timeStart) - , mStopTime(ctrl->timeStop) + ControllerFunction::ControllerFunction(const Nif::NiTimeController* ctrl) + : mFrequency(ctrl->mFrequency) + , mPhase(ctrl->mPhase) + , mStartTime(ctrl->mTimeStart) + , mStopTime(ctrl->mTimeStop) , mExtrapolationMode(ctrl->extrapolationMode()) { } @@ -31,7 +31,7 @@ namespace NifOsg return time; switch (mExtrapolationMode) { - case Nif::Controller::ExtrapolationMode::Cycle: + case Nif::NiTimeController::ExtrapolationMode::Cycle: { float delta = mStopTime - mStartTime; if (delta <= 0) @@ -40,7 +40,7 @@ namespace NifOsg float remainder = (cycles - std::floor(cycles)) * delta; return mStartTime + remainder; } - case Nif::Controller::ExtrapolationMode::Reverse: + case Nif::NiTimeController::ExtrapolationMode::Reverse: { float delta = mStopTime - mStartTime; if (delta <= 0) @@ -55,7 +55,7 @@ namespace NifOsg return mStopTime - remainder; } - case Nif::Controller::ExtrapolationMode::Constant: + case Nif::NiTimeController::ExtrapolationMode::Constant: default: return std::clamp(time, mStartTime, mStopTime); } diff --git a/components/nifosg/controller.hpp b/components/nifosg/controller.hpp index f830cf1c4c..2f9d58c6b1 100644 --- a/components/nifosg/controller.hpp +++ b/components/nifosg/controller.hpp @@ -191,10 +191,10 @@ namespace NifOsg float mPhase; float mStartTime; float mStopTime; - Nif::Controller::ExtrapolationMode mExtrapolationMode; + Nif::NiTimeController::ExtrapolationMode mExtrapolationMode; public: - ControllerFunction(const Nif::Controller* ctrl); + ControllerFunction(const Nif::NiTimeController* ctrl); float calculate(float value) const override; diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 96740b8dd3..f1492b9d0b 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -293,8 +293,8 @@ namespace NifOsg auto textKeyExtraData = static_cast(extraList[0].getPtr()); extractTextKeys(textKeyExtraData, target.mTextKeys); - Nif::ControllerPtr ctrl = seq->mController; - for (size_t i = 1; i < extraList.size() && !ctrl.empty(); i++, (ctrl = ctrl->next)) + Nif::NiTimeControllerPtr ctrl = seq->mController; + for (size_t i = 1; i < extraList.size() && !ctrl.empty(); i++, (ctrl = ctrl->mNext)) { Nif::ExtraPtr extra = extraList[i]; if (extra->recType != Nif::RC_NiStringExtraData || ctrl->recType != Nif::RC_NiKeyframeController) @@ -449,7 +449,7 @@ namespace NifOsg animflags, hasStencilProperty); } - static void setupController(const Nif::Controller* ctrl, SceneUtil::Controller* toSetup, int animflags) + static void setupController(const Nif::NiTimeController* ctrl, SceneUtil::Controller* toSetup, int animflags) { bool autoPlay = animflags & Nif::NiNode::AnimFlag_AutoPlay; if (autoPlay) @@ -725,7 +725,7 @@ namespace NifOsg if (nifNode->isHidden()) { bool hasVisController = false; - for (Nif::ControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->next) + for (Nif::NiTimeControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->mNext) { hasVisController |= (ctrl->recType == Nif::RC_NiVisController); if (hasVisController) @@ -858,7 +858,7 @@ namespace NifOsg SceneUtil::CompositeStateSetUpdater* composite, const std::vector& boundTextures, int animflags) { - for (Nif::ControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->next) + for (Nif::NiTimeControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->mNext) { if (!ctrl->isActive()) continue; @@ -884,7 +884,7 @@ namespace NifOsg void handleNodeControllers(const Nif::NiAVObject* nifNode, osg::Node* node, int animflags, bool& isAnimated) { - for (Nif::ControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->next) + for (Nif::NiTimeControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->mNext) { if (!ctrl->isActive()) continue; @@ -962,7 +962,7 @@ namespace NifOsg void handleMaterialControllers(const Nif::Property* materialProperty, SceneUtil::CompositeStateSetUpdater* composite, int animflags, const osg::Material* baseMaterial) { - for (Nif::ControllerPtr ctrl = materialProperty->mController; !ctrl.empty(); ctrl = ctrl->next) + for (Nif::NiTimeControllerPtr ctrl = materialProperty->mController; !ctrl.empty(); ctrl = ctrl->mNext) { if (!ctrl->isActive()) continue; @@ -1012,7 +1012,7 @@ namespace NifOsg void handleTextureControllers(const Nif::Property* texProperty, SceneUtil::CompositeStateSetUpdater* composite, Resource::ImageManager* imageManager, osg::StateSet* stateset, int animflags) { - for (Nif::ControllerPtr ctrl = texProperty->mController; !ctrl.empty(); ctrl = ctrl->next) + for (Nif::NiTimeControllerPtr ctrl = texProperty->mController; !ctrl.empty(); ctrl = ctrl->mNext) { if (!ctrl->isActive()) continue; @@ -1200,7 +1200,7 @@ namespace NifOsg partctrl->horizontalAngle, partctrl->verticalDir, partctrl->verticalAngle, partctrl->lifetime, partctrl->lifetimeRandom); emitter->setShooter(shooter); - emitter->setFlags(partctrl->flags); + emitter->setFlags(partctrl->mFlags); if (partctrl->recType == Nif::RC_NiBSPArrayController && partctrl->emitAtVertex()) { @@ -1252,7 +1252,7 @@ namespace NifOsg partsys->setSortMode(osgParticle::ParticleSystem::SORT_BACK_TO_FRONT); const Nif::NiParticleSystemController* partctrl = nullptr; - for (Nif::ControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->next) + for (Nif::NiTimeControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->mNext) { if (!ctrl->isActive()) continue; @@ -1483,7 +1483,7 @@ namespace NifOsg if (geom->empty()) return; osg::ref_ptr drawable; - for (Nif::ControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->next) + for (Nif::NiTimeControllerPtr ctrl = nifNode->mController; !ctrl.empty(); ctrl = ctrl->mNext) { if (!ctrl->isActive()) continue; From d55ba0cfa2638953cee4dc6edd1bd9105db16bfd Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 14 Sep 2023 03:08:07 +0300 Subject: [PATCH 12/15] Cleanup --- components/nif/controller.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index 17937b61af..f909d94da5 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -84,11 +84,9 @@ namespace Nif nif->read(mAccumRootName); mTextKeys.read(nif); } - uint32_t numBlocks; - nif->read(numBlocks); + mControlledBlocks.resize(nif->get()); if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 106)) nif->read(mArrayGrowBy); - mControlledBlocks.resize(numBlocks); for (ControlledBlock& block : mControlledBlocks) block.read(nif); } @@ -109,8 +107,8 @@ namespace Nif nif->read(mWeight); mTextKeys.read(nif); - mExtrapolationMode = static_cast(nif->getUInt()); - mFrequency = nif->getFloat(); + mExtrapolationMode = static_cast(nif->get()); + nif->read(mFrequency); if (nif->getVersion() <= NIFStream::generateVersion(10, 4, 0, 1)) nif->read(mPhase); nif->read(mStartTime); From 8856dff3db838e8806ea0f766b81944731614f37 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 14 Sep 2023 04:24:37 +0300 Subject: [PATCH 13/15] Refactor NiParticleSystemController and update definitions --- components/nif/controller.cpp | 102 ++++++++++++++++--------------- components/nif/controller.hpp | 81 ++++++++++++------------ components/nifosg/controller.cpp | 10 +-- components/nifosg/controller.hpp | 6 +- components/nifosg/nifloader.cpp | 94 ++++++++++++++-------------- 5 files changed, 148 insertions(+), 145 deletions(-) diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index f909d94da5..1875488143 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -162,67 +162,71 @@ namespace Nif mInterpolator.post(nif); } + void NiParticleInfo::read(NIFStream* nif) + { + nif->read(mVelocity); + if (nif->getVersion() <= NIFStream::generateVersion(10, 4, 0, 1)) + nif->read(mRotationAxis); + nif->read(mAge); + nif->read(mLifespan); + nif->read(mLastUpdate); + nif->read(mSpawnGeneration); + nif->read(mCode); + } + void NiParticleSystemController::read(NIFStream* nif) { NiTimeController::read(nif); - velocity = nif->getFloat(); - velocityRandom = nif->getFloat(); - verticalDir = nif->getFloat(); - verticalAngle = nif->getFloat(); - horizontalDir = nif->getFloat(); - horizontalAngle = nif->getFloat(); - /*normal?*/ nif->getVector3(); - color = nif->getVector4(); - size = nif->getFloat(); - startTime = nif->getFloat(); - stopTime = nif->getFloat(); - nif->getChar(); - emitRate = nif->getFloat(); - lifetime = nif->getFloat(); - lifetimeRandom = nif->getFloat(); - - emitFlags = nif->getUShort(); - offsetRandom = nif->getVector3(); - - emitter.read(nif); - - /* Unknown Short, 0? - * Unknown Float, 1.0? - * Unknown Int, 1? - * Unknown Int, 0? - * Unknown Short, 0? - */ - nif->skip(16); - - numParticles = nif->getUShort(); - activeCount = nif->getUShort(); - - particles.resize(numParticles); - for (size_t i = 0; i < particles.size(); i++) + if (nif->getVersion() >= NIFStream::generateVersion(3, 3, 0, 13)) + nif->read(mSpeed); + nif->read(mSpeedVariation); + nif->read(mDeclination); + nif->read(mDeclinationVariation); + nif->read(mPlanarAngle); + nif->read(mPlanarAngleVariation); + nif->read(mInitialNormal); + nif->read(mInitialColor); + nif->read(mInitialSize); + nif->read(mEmitStartTime); + nif->read(mEmitStopTime); + if (nif->getVersion() >= NIFStream::generateVersion(3, 3, 0, 13)) { - particles[i].velocity = nif->getVector3(); - nif->getVector3(); /* unknown */ - particles[i].lifetime = nif->getFloat(); - particles[i].lifespan = nif->getFloat(); - particles[i].timestamp = nif->getFloat(); - nif->getUShort(); /* unknown */ - particles[i].vertex = nif->getUShort(); + mResetParticleSystem = nif->get() != 0; + nif->read(mBirthRate); } - - nif->getUInt(); /* -1? */ - affectors.read(nif); - colliders.read(nif); - nif->getChar(); + nif->read(mLifetime); + nif->read(mLifetimeVariation); + if (nif->getVersion() >= NIFStream::generateVersion(3, 3, 0, 13)) + nif->read(mEmitFlags); + nif->read(mEmitterDimensions); + mEmitter.read(nif); + if (nif->getVersion() >= NIFStream::generateVersion(3, 3, 0, 13)) + { + nif->read(mNumSpawnGenerations); + nif->read(mPercentageSpawned); + nif->read(mSpawnMultiplier); + nif->read(mSpawnSpeedChaos); + nif->read(mSpawnDirChaos); + mParticles.resize(nif->get()); + nif->read(mNumValid); + for (NiParticleInfo& particle : mParticles) + particle.read(nif); + nif->skip(4); // NiEmitterModifier link + } + mModifier.read(nif); + mCollider.read(nif); + if (nif->getVersion() >= NIFStream::generateVersion(3, 3, 0, 15)) + nif->read(mStaticTargetBound); } void NiParticleSystemController::post(Reader& nif) { NiTimeController::post(nif); - emitter.post(nif); - affectors.post(nif); - colliders.post(nif); + mEmitter.post(nif); + mModifier.post(nif); + mCollider.post(nif); } void NiMaterialColorController::read(NIFStream* nif) diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index 5449e19f8d..a05ff247c5 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -94,6 +94,19 @@ namespace Nif { }; + struct NiParticleInfo + { + osg::Vec3f mVelocity; + osg::Vec3f mRotationAxis; + float mAge; + float mLifespan; + float mLastUpdate; + uint16_t mSpawnGeneration; + uint16_t mCode; + + void read(NIFStream* nif); + }; + struct NiParticleSystemController : public NiTimeController { enum BSPArrayController @@ -102,55 +115,47 @@ namespace Nif BSPArrayController_AtVertex = 0x10 }; - struct Particle - { - osg::Vec3f velocity; - float lifetime; - float lifespan; - float timestamp; - unsigned short vertex; - }; - - float velocity; - float velocityRandom; - - float verticalDir; // 0=up, pi/2=horizontal, pi=down - float verticalAngle; - float horizontalDir; - float horizontalAngle; - - osg::Vec4f color; - float size; - float startTime; - float stopTime; - - float emitRate; - float lifetime; - float lifetimeRandom; - enum EmitFlags { EmitFlag_NoAutoAdjust = 0x1 // If this flag is set, we use the emitRate value. Otherwise, // we calculate an emit rate so that the maximum number of particles // in the system (numParticles) is never exceeded. }; - int emitFlags; - - osg::Vec3f offsetRandom; - - NiAVObjectPtr emitter; - - int numParticles; - int activeCount; - std::vector particles; - NiParticleModifierPtr affectors; - NiParticleModifierPtr colliders; + float mSpeed; + float mSpeedVariation; + float mDeclination; + float mDeclinationVariation; + float mPlanarAngle; + float mPlanarAngleVariation; + osg::Vec3f mInitialNormal; + osg::Vec4f mInitialColor; + float mInitialSize; + float mEmitStartTime; + float mEmitStopTime; + bool mResetParticleSystem{ false }; + float mBirthRate; + float mLifetime; + float mLifetimeVariation; + uint16_t mEmitFlags{ 0 }; + osg::Vec3f mEmitterDimensions; + NiAVObjectPtr mEmitter; + uint16_t mNumSpawnGenerations; + float mPercentageSpawned; + uint16_t mSpawnMultiplier; + float mSpawnSpeedChaos; + float mSpawnDirChaos; + uint16_t mNumParticles; + uint16_t mNumValid; + std::vector mParticles; + NiParticleModifierPtr mModifier; + NiParticleModifierPtr mCollider; + uint8_t mStaticTargetBound; void read(NIFStream* nif) override; void post(Reader& nif) override; - bool noAutoAdjust() const { return emitFlags & EmitFlag_NoAutoAdjust; } + bool noAutoAdjust() const { return mEmitFlags & EmitFlag_NoAutoAdjust; } bool emitAtVertex() const { return mFlags & BSPArrayController_AtVertex; } }; using NiBSPArrayController = NiParticleSystemController; diff --git a/components/nifosg/controller.cpp b/components/nifosg/controller.cpp index 45082d969a..c5511141a2 100644 --- a/components/nifosg/controller.cpp +++ b/components/nifosg/controller.cpp @@ -556,14 +556,8 @@ namespace NifOsg } ParticleSystemController::ParticleSystemController(const Nif::NiParticleSystemController* ctrl) - : mEmitStart(ctrl->startTime) - , mEmitStop(ctrl->stopTime) - { - } - - ParticleSystemController::ParticleSystemController() - : mEmitStart(0.f) - , mEmitStop(0.f) + : mEmitStart(ctrl->mEmitStartTime) + , mEmitStop(ctrl->mEmitStopTime) { } diff --git a/components/nifosg/controller.hpp b/components/nifosg/controller.hpp index 2f9d58c6b1..7ac34d61ed 100644 --- a/components/nifosg/controller.hpp +++ b/components/nifosg/controller.hpp @@ -379,7 +379,7 @@ namespace NifOsg { public: ParticleSystemController(const Nif::NiParticleSystemController* ctrl); - ParticleSystemController(); + ParticleSystemController() = default; ParticleSystemController(const ParticleSystemController& copy, const osg::CopyOp& copyop); META_Object(NifOsg, ParticleSystemController) @@ -387,8 +387,8 @@ namespace NifOsg void operator()(osgParticle::ParticleProcessor* node, osg::NodeVisitor* nv); private: - float mEmitStart; - float mEmitStop; + float mEmitStart{ 0.f }; + float mEmitStop{ 0.f }; }; class PathController : public SceneUtil::NodeCallback, diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index f1492b9d0b..0e1d4091a9 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -1061,7 +1061,7 @@ namespace NifOsg } } - void handleParticlePrograms(Nif::NiParticleModifierPtr affectors, Nif::NiParticleModifierPtr colliders, + void handleParticlePrograms(Nif::NiParticleModifierPtr modifier, Nif::NiParticleModifierPtr collider, osg::Group* attachTo, osgParticle::ParticleSystem* partsys, osgParticle::ParticleProcessor::ReferenceFrame rf) { @@ -1069,50 +1069,50 @@ namespace NifOsg attachTo->addChild(program); program->setParticleSystem(partsys); program->setReferenceFrame(rf); - for (; !affectors.empty(); affectors = affectors->mNext) + for (; !modifier.empty(); modifier = modifier->mNext) { - if (affectors->recType == Nif::RC_NiParticleGrowFade) + if (modifier->recType == Nif::RC_NiParticleGrowFade) { - const Nif::NiParticleGrowFade* gf = static_cast(affectors.getPtr()); + const Nif::NiParticleGrowFade* gf = static_cast(modifier.getPtr()); program->addOperator(new GrowFadeAffector(gf->mGrowTime, gf->mFadeTime)); } - else if (affectors->recType == Nif::RC_NiGravity) + else if (modifier->recType == Nif::RC_NiGravity) { - const Nif::NiGravity* gr = static_cast(affectors.getPtr()); + const Nif::NiGravity* gr = static_cast(modifier.getPtr()); program->addOperator(new GravityAffector(gr)); } - else if (affectors->recType == Nif::RC_NiParticleColorModifier) + else if (modifier->recType == Nif::RC_NiParticleColorModifier) { const Nif::NiParticleColorModifier* cl - = static_cast(affectors.getPtr()); + = static_cast(modifier.getPtr()); if (cl->mData.empty()) continue; const Nif::NiColorData* clrdata = cl->mData.getPtr(); program->addOperator(new ParticleColorAffector(clrdata)); } - else if (affectors->recType == Nif::RC_NiParticleRotation) + else if (modifier->recType == Nif::RC_NiParticleRotation) { // unused } else - Log(Debug::Info) << "Unhandled particle modifier " << affectors->recName << " in " << mFilename; + Log(Debug::Info) << "Unhandled particle modifier " << modifier->recName << " in " << mFilename; } - for (; !colliders.empty(); colliders = colliders->mNext) + for (; !collider.empty(); collider = collider->mNext) { - if (colliders->recType == Nif::RC_NiPlanarCollider) + if (collider->recType == Nif::RC_NiPlanarCollider) { const Nif::NiPlanarCollider* planarcollider - = static_cast(colliders.getPtr()); + = static_cast(collider.getPtr()); program->addOperator(new PlanarCollider(planarcollider)); } - else if (colliders->recType == Nif::RC_NiSphericalCollider) + else if (collider->recType == Nif::RC_NiSphericalCollider) { const Nif::NiSphericalCollider* sphericalcollider - = static_cast(colliders.getPtr()); + = static_cast(collider.getPtr()); program->addOperator(new SphericalCollider(sphericalcollider)); } else - Log(Debug::Info) << "Unhandled particle collider " << colliders->recName << " in " << mFilename; + Log(Debug::Info) << "Unhandled particle collider " << collider->recName << " in " << mFilename; } } @@ -1124,7 +1124,7 @@ namespace NifOsg auto particleNode = static_cast(nifNode); if (particleNode->data.empty() || particleNode->data->recType != Nif::RC_NiParticlesData) { - partsys->setQuota(partctrl->numParticles); + partsys->setQuota(partctrl->mParticles.size()); return; } @@ -1134,35 +1134,35 @@ namespace NifOsg osg::BoundingBox box; int i = 0; - for (const auto& particle : partctrl->particles) + for (const auto& particle : partctrl->mParticles) { if (i++ >= particledata->mActiveCount) break; - if (particle.lifespan <= 0) + if (particle.mLifespan <= 0) continue; - if (particle.vertex >= particledata->mVertices.size()) + if (particle.mCode >= particledata->mVertices.size()) continue; - ParticleAgeSetter particletemplate(std::max(0.f, particle.lifetime)); + ParticleAgeSetter particletemplate(std::max(0.f, particle.mAge)); osgParticle::Particle* created = partsys->createParticle(&particletemplate); - created->setLifeTime(particle.lifespan); + created->setLifeTime(particle.mLifespan); // Note this position and velocity is not correct for a particle system with absolute reference frame, // which can not be done in this loader since we are not attached to the scene yet. Will be fixed up // post-load in the SceneManager. - created->setVelocity(particle.velocity); - const osg::Vec3f& position = particledata->mVertices[particle.vertex]; + created->setVelocity(particle.mVelocity); + const osg::Vec3f& position = particledata->mVertices[particle.mCode]; created->setPosition(position); - created->setColorRange(osgParticle::rangev4(partctrl->color, partctrl->color)); + created->setColorRange(osgParticle::rangev4(partctrl->mInitialColor, partctrl->mInitialColor)); created->setAlphaRange(osgParticle::rangef(1.f, 1.f)); - float size = partctrl->size; - if (particle.vertex < particledata->mSizes.size()) - size *= particledata->mSizes[particle.vertex]; + float size = partctrl->mInitialSize; + if (particle.mCode < particledata->mSizes.size()) + size *= particledata->mSizes[particle.mCode]; created->setSizeRange(osgParticle::rangef(size, size)); box.expandBy(osg::BoundingSphere(position, size)); @@ -1179,39 +1179,39 @@ namespace NifOsg std::vector targets; if (partctrl->recType == Nif::RC_NiBSPArrayController && !partctrl->emitAtVertex()) { - getAllNiNodes(partctrl->emitter.getPtr(), targets); + getAllNiNodes(partctrl->mEmitter.getPtr(), targets); } osg::ref_ptr emitter = new Emitter(targets); osgParticle::ConstantRateCounter* counter = new osgParticle::ConstantRateCounter; if (partctrl->noAutoAdjust()) - counter->setNumberOfParticlesPerSecondToCreate(partctrl->emitRate); - else if (partctrl->lifetime == 0 && partctrl->lifetimeRandom == 0) + counter->setNumberOfParticlesPerSecondToCreate(partctrl->mBirthRate); + else if (partctrl->mLifetime == 0 && partctrl->mLifetimeVariation == 0) counter->setNumberOfParticlesPerSecondToCreate(0); else counter->setNumberOfParticlesPerSecondToCreate( - partctrl->numParticles / (partctrl->lifetime + partctrl->lifetimeRandom / 2)); + partctrl->mParticles.size() / (partctrl->mLifetime + partctrl->mLifetimeVariation / 2)); emitter->setCounter(counter); - ParticleShooter* shooter = new ParticleShooter(partctrl->velocity - partctrl->velocityRandom * 0.5f, - partctrl->velocity + partctrl->velocityRandom * 0.5f, partctrl->horizontalDir, - partctrl->horizontalAngle, partctrl->verticalDir, partctrl->verticalAngle, partctrl->lifetime, - partctrl->lifetimeRandom); + ParticleShooter* shooter = new ParticleShooter(partctrl->mSpeed - partctrl->mSpeedVariation * 0.5f, + partctrl->mSpeed + partctrl->mSpeedVariation * 0.5f, partctrl->mPlanarAngle, + partctrl->mPlanarAngleVariation, partctrl->mDeclination, partctrl->mDeclinationVariation, + partctrl->mLifetime, partctrl->mLifetimeVariation); emitter->setShooter(shooter); emitter->setFlags(partctrl->mFlags); if (partctrl->recType == Nif::RC_NiBSPArrayController && partctrl->emitAtVertex()) { - emitter->setGeometryEmitterTarget(partctrl->emitter->recIndex); + emitter->setGeometryEmitterTarget(partctrl->mEmitter->recIndex); } else { osgParticle::BoxPlacer* placer = new osgParticle::BoxPlacer; - placer->setXRange(-partctrl->offsetRandom.x() / 2.f, partctrl->offsetRandom.x() / 2.f); - placer->setYRange(-partctrl->offsetRandom.y() / 2.f, partctrl->offsetRandom.y() / 2.f); - placer->setZRange(-partctrl->offsetRandom.z() / 2.f, partctrl->offsetRandom.z() / 2.f); + placer->setXRange(-partctrl->mEmitterDimensions.x() / 2.f, partctrl->mEmitterDimensions.x() / 2.f); + placer->setYRange(-partctrl->mEmitterDimensions.y() / 2.f, partctrl->mEmitterDimensions.y() / 2.f); + placer->setZRange(-partctrl->mEmitterDimensions.z() / 2.f, partctrl->mEmitterDimensions.z() / 2.f); emitter->setPlacer(placer); } @@ -1280,11 +1280,11 @@ namespace NifOsg handleParticleInitialState(nifNode, partsys, partctrl); - partsys->getDefaultParticleTemplate().setSizeRange(osgParticle::rangef(partctrl->size, partctrl->size)); - partsys->getDefaultParticleTemplate().setColorRange(osgParticle::rangev4(partctrl->color, partctrl->color)); + partsys->getDefaultParticleTemplate().setSizeRange(osgParticle::rangef(partctrl->mInitialSize, partctrl->mInitialSize)); + partsys->getDefaultParticleTemplate().setColorRange(osgParticle::rangev4(partctrl->mInitialColor, partctrl->mInitialColor)); partsys->getDefaultParticleTemplate().setAlphaRange(osgParticle::rangef(1.f, 1.f)); - if (!partctrl->emitter.empty()) + if (!partctrl->mEmitter.empty()) { osg::ref_ptr emitter = handleParticleEmitter(partctrl); emitter->setParticleSystem(partsys); @@ -1293,7 +1293,7 @@ namespace NifOsg // The emitter node may not actually be handled yet, so let's delay attaching the emitter to a later // moment. If the emitter node is placed later than the particle node, it'll have a single frame delay // in particle processing. But that shouldn't be a game-breaking issue. - mEmitterQueue.emplace_back(partctrl->emitter->recIndex, emitter); + mEmitterQueue.emplace_back(partctrl->mEmitter->recIndex, emitter); osg::ref_ptr callback(new ParticleSystemController(partctrl)); setupController(partctrl, callback, animflags); @@ -1310,16 +1310,16 @@ namespace NifOsg partsys->update(0.0, nv); } - // affectors should be attached *after* the emitter in the scene graph for correct update order + // modifiers should be attached *after* the emitter in the scene graph for correct update order // attach to same node as the ParticleSystem, we need osgParticle Operators to get the correct // localToWorldMatrix for transforming to particle space - handleParticlePrograms(partctrl->affectors, partctrl->colliders, parentNode, partsys.get(), rf); + handleParticlePrograms(partctrl->mModifier, partctrl->mCollider, parentNode, partsys.get(), rf); std::vector drawableProps; collectDrawableProperties(nifNode, parent, drawableProps); applyDrawableProperties(parentNode, drawableProps, composite, true, animflags); - // particle system updater (after the emitters and affectors in the scene graph) + // particle system updater (after the emitters and modifiers in the scene graph) // I think for correct culling needs to be *before* the ParticleSystem, though osg examples do it the other // way osg::ref_ptr updater = new osgParticle::ParticleSystemUpdater; From f271c4305ade0f117b31ccfb536b1ebb7a857947 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 14 Sep 2023 05:11:40 +0300 Subject: [PATCH 14/15] Fix formatting --- components/nif/controller.hpp | 7 ++----- components/nifosg/controller.cpp | 1 - components/nifosg/controller.hpp | 9 ++++----- components/nifosg/nifloader.cpp | 11 ++++++----- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index a05ff247c5..afca97d885 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -334,7 +334,7 @@ namespace Nif { }; - template + template struct TypedNiInterpolator : public NiInterpolator { T mDefaultValue; @@ -346,10 +346,7 @@ namespace Nif mData.read(nif); } - void post(Reader& nif) override - { - mData.post(nif); - } + void post(Reader& nif) override { mData.post(nif); } }; using NiPoint3Interpolator = TypedNiInterpolator; diff --git a/components/nifosg/controller.cpp b/components/nifosg/controller.cpp index c5511141a2..54e9e2bb16 100644 --- a/components/nifosg/controller.cpp +++ b/components/nifosg/controller.cpp @@ -185,7 +185,6 @@ namespace NifOsg if (!mScales.empty()) node->setScale(mScales.interpKey(time)); - } traverse(node, nv); diff --git a/components/nifosg/controller.hpp b/components/nifosg/controller.hpp index 7ac34d61ed..df6fdb2a24 100644 --- a/components/nifosg/controller.hpp +++ b/components/nifosg/controller.hpp @@ -63,11 +63,10 @@ namespace NifOsg ValueInterpolator() = default; template , - std::is_same, std::is_same, - std::is_same>, - std::is_same>, + typename = std::enable_if_t< + std::conjunction_v, std::is_same, + std::is_same, std::is_same>, + std::is_same>, T>> ValueInterpolator(const T* interpolator) : mDefaultVal(interpolator->mDefaultValue) diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 0e1d4091a9..fc8da57dbd 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -995,9 +995,8 @@ namespace NifOsg continue; if (!interp.empty() && interp->recType != Nif::RC_NiPoint3Interpolator) { - Log(Debug::Error) - << "Unsupported interpolator type for NiMaterialColorController " << matctrl->recIndex - << " in " << mFilename << ": " << interp->recName; + Log(Debug::Error) << "Unsupported interpolator type for NiMaterialColorController " + << matctrl->recIndex << " in " << mFilename << ": " << interp->recName; continue; } osg::ref_ptr osgctrl = new MaterialColorController(matctrl, baseMaterial); @@ -1280,8 +1279,10 @@ namespace NifOsg handleParticleInitialState(nifNode, partsys, partctrl); - partsys->getDefaultParticleTemplate().setSizeRange(osgParticle::rangef(partctrl->mInitialSize, partctrl->mInitialSize)); - partsys->getDefaultParticleTemplate().setColorRange(osgParticle::rangev4(partctrl->mInitialColor, partctrl->mInitialColor)); + partsys->getDefaultParticleTemplate().setSizeRange( + osgParticle::rangef(partctrl->mInitialSize, partctrl->mInitialSize)); + partsys->getDefaultParticleTemplate().setColorRange( + osgParticle::rangev4(partctrl->mInitialColor, partctrl->mInitialColor)); partsys->getDefaultParticleTemplate().setAlphaRange(osgParticle::rangef(1.f, 1.f)); if (!partctrl->mEmitter.empty()) From 2f8229a54d2cee921fc86cca5f31dfbf23a7ad6e Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 14 Sep 2023 07:01:12 +0300 Subject: [PATCH 15/15] Fix bit shift --- components/nif/controller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index 1875488143..99317cda57 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -272,7 +272,7 @@ namespace Nif if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0)) nif->read(mPathFlags); else - mPathFlags = (mFlags >> 16); + mPathFlags = (mFlags >> 4); nif->read(mBankDirection); nif->read(mMaxBankAngle);