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; + + void read(NIFStream* nif) override + { + NiBlendInterpolator::read(nif); + + nif->read(mValue); + } }; - struct NiBlendFloatInterpolator : public NiBlendInterpolator + template <> + struct TypedNiBlendInterpolator : public NiBlendInterpolator { - float mValue; - 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); + } }; - struct NiBlendPoint3Interpolator : public NiBlendInterpolator - { - osg::Vec3f mValue; - void read(NIFStream* nif) override; - }; + using NiBlendBoolInterpolator = TypedNiBlendInterpolator; + using NiBlendFloatInterpolator = TypedNiBlendInterpolator; + using NiBlendPoint3Interpolator = TypedNiBlendInterpolator; + using NiBlendTransformInterpolator = TypedNiBlendInterpolator; - struct NiBlendTransformInterpolator : public NiBlendInterpolator - { - osg::Vec3f mPosValue; - osg::Quat mRotValue; - float mScaleValue; - void read(NIFStream* nif) override; - }; - -} // Namespace +} #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