diff --git a/components/nif/nifkey.hpp b/components/nif/nifkey.hpp index bd362101c6..604cf92c33 100644 --- a/components/nif/nifkey.hpp +++ b/components/nif/nifkey.hpp @@ -3,9 +3,7 @@ #ifndef OPENMW_COMPONENTS_NIF_NIFKEY_HPP #define OPENMW_COMPONENTS_NIF_NIFKEY_HPP -#include #include -#include #include "exception.hpp" #include "niffile.hpp" @@ -19,7 +17,7 @@ namespace Nif InterpolationType_Unknown = 0, InterpolationType_Linear = 1, InterpolationType_Quadratic = 2, - InterpolationType_TCB = 3, + InterpolationType_TBC = 3, InterpolationType_XYZ = 4, InterpolationType_Constant = 5 }; @@ -30,19 +28,18 @@ namespace Nif T mValue; T mInTan; // Only for Quadratic interpolation, and never for QuaternionKeyList T mOutTan; // Only for Quadratic interpolation, and never for QuaternionKeyList - }; - template - struct TCBKey - { - float mTime; - T mValue{}; - T mInTan{}; - T mOutTan{}; - float mTension; - float mContinuity; - float mBias; + // FIXME: Implement TBC interpolation + /* + float mTension; // Only for TBC interpolation + float mBias; // Only for TBC interpolation + float mContinuity; // Only for TBC interpolation + */ }; + using FloatKey = KeyT; + using Vector3Key = KeyT; + using Vector4Key = KeyT; + using QuaternionKey = KeyT; template struct KeyMapT @@ -104,20 +101,15 @@ namespace Nif mKeys[time] = key; } } - else if (mInterpolationType == InterpolationType_TCB) + else if (mInterpolationType == InterpolationType_TBC) { - std::vector> tcbKeys(count); - for (TCBKey& key : tcbKeys) + for (size_t i = 0; i < count; i++) { - nif->read(key.mTime); - key.mValue = ((*nif).*getValue)(); - nif->read(key.mTension); - nif->read(key.mContinuity); - nif->read(key.mBias); + float time; + nif->read(time); + readTBC(*nif, key); + mKeys[time] = key; } - generateTCBTangents(tcbKeys); - for (TCBKey& key : tcbKeys) - mKeys[key.mTime] = KeyType{ std::move(key.mValue), std::move(key.mInTan), std::move(key.mOutTan) }; } else if (mInterpolationType == InterpolationType_XYZ) { @@ -148,52 +140,12 @@ namespace Nif static void readQuadratic(NIFStream& nif, KeyT& key) { readValue(nif, key); } - template - static void generateTCBTangents(std::vector>& keys) + static void readTBC(NIFStream& nif, KeyT& key) { - if (keys.size() <= 1) - return; - - std::sort(keys.begin(), keys.end(), [](const auto& a, const auto& b) { return a.mTime < b.mTime; }); - for (size_t i = 0; i < keys.size(); ++i) - { - TCBKey& curr = keys[i]; - const TCBKey& prev = (i == 0) ? curr : keys[i - 1]; - const TCBKey& next = (i == keys.size() - 1) ? curr : keys[i + 1]; - const float prevLen = curr.mTime - prev.mTime; - const float nextLen = next.mTime - curr.mTime; - if (prevLen + nextLen <= 0.f) - continue; - - const U prevDelta = curr.mValue - prev.mValue; - const U nextDelta = next.mValue - curr.mValue; - const float t = curr.mTension; - const float c = curr.mContinuity; - const float b = curr.mBias; - - U x{}, y{}, z{}, w{}; - if (prevLen > 0.f) - x = prevDelta / prevLen * (1 - t) * (1 - c) * (1 + b); - if (nextLen > 0.f) - y = nextDelta / nextLen * (1 - t) * (1 + c) * (1 - b); - if (prevLen > 0.f) - z = prevDelta / prevLen * (1 - t) * (1 + c) * (1 + b); - if (nextLen > 0.f) - w = nextDelta / nextLen * (1 - t) * (1 - c) * (1 - b); - - curr.mInTan = (x + y) * prevLen / (prevLen + nextLen); - curr.mOutTan = (z + w) * nextLen / (prevLen + nextLen); - } - } - - static void generateTCBTangents(std::vector>& keys) - { - // TODO: is this even legal? - } - - static void generateTCBTangents(std::vector>& keys) - { - // TODO: implement TCB interpolation for quaternions + readValue(nif, key); + /*key.mTension = */ nif.get(); + /*key.mBias = */ nif.get(); + /*key.mContinuity = */ nif.get(); } }; using FloatKeyMap = KeyMapT>; diff --git a/components/nifosg/controller.hpp b/components/nifosg/controller.hpp index 468668ce76..99d3df9545 100644 --- a/components/nifosg/controller.hpp +++ b/components/nifosg/controller.hpp @@ -131,7 +131,6 @@ namespace NifOsg case Nif::InterpolationType_Constant: return fraction > 0.5f ? b.mValue : a.mValue; case Nif::InterpolationType_Quadratic: - case Nif::InterpolationType_TCB: { // Using a cubic Hermite spline. // b1(t) = 2t^3 - 3t^2 + 1 @@ -148,6 +147,7 @@ namespace NifOsg const float b4 = t3 - t2; return a.mValue * b1 + b.mValue * b2 + a.mOutTan * b3 + b.mInTan * b4; } + // TODO: Implement TBC interpolation default: return a.mValue + ((b.mValue - a.mValue) * fraction); }