diff --git a/Source/Contents/Models/ModelAnimation.cpp b/Source/Contents/Models/ModelAnimation.cpp index 0802e4eb..84b6659e 100644 --- a/Source/Contents/Models/ModelAnimation.cpp +++ b/Source/Contents/Models/ModelAnimation.cpp @@ -24,51 +24,60 @@ namespace { // OFFSET: 0x00540370 // FUNCTION: fn_01721 -void SampleLegacyPosition(std::span keys, int frame, matrix& output) { - if (keys.empty()) { +void SampleLegacyPosition(const std::vector& keys, int frame, matrix& output) { + const unsigned count = keys.size(); + + if (count == 0) { output.Identity(); - } else if (keys.size() == 1) { + return; + } + + if (count == 1) { output.MakeTranslate(keys[0].position[0], keys[0].position[1], keys[0].position[2]); - } else { - unsigned next = 1; + return; + } - while (keys[next].frame <= frame) { - if (++next >= keys.size()) { - return; - } + for (unsigned next = 1; next < count; ++next) { + if (keys[next].frame > frame) { + const auto& a = keys[next - 1]; + const auto& b = keys[next]; + const float amount = static_cast((frame - a.frame)) / static_cast((b.frame - a.frame)); + const float previous = static_cast(1.0 - static_cast(amount)); + output.MakeTranslate( + previous * a.position[0] + amount * b.position[0], previous * a.position[1] + amount * b.position[1], previous * a.position[2] + amount * b.position[2] + ); + return; } - - const auto& a = keys[next - 1]; - const auto& b = keys[next]; - const float amount = static_cast((frame - a.frame)) / static_cast((b.frame - a.frame)); - const float previous = static_cast(1.0 - static_cast(amount)); - output.MakeTranslate( - previous * a.position[0] + amount * b.position[0], previous * a.position[1] + amount * b.position[1], previous * a.position[2] + amount * b.position[2] - ); } } // OFFSET: 0x00540670 // FUNCTION: fn_01723 -void SampleLegacyRotation(std::span keys, int frame, matrix& output) { - if (keys.empty()) { +void SampleLegacyRotation(const std::vector& keys, int frame, matrix& output) { + const unsigned count = keys.size(); + + if (count == 0) { output.Identity(); return; } - if (keys.size() == 1) { + if (count == 1) { QuaternionMatrix(keys[0], output); return; } unsigned next = 1; - while (keys[next].frame <= frame) { - if (++next >= keys.size()) { - return; + for (; next < count; ++next) { + if (keys[next].frame > frame) { + break; } } + if (next >= count) { + return; + } + const auto& a = keys[next - 1]; const auto& b = keys[next]; @@ -85,74 +94,99 @@ void SampleLegacyRotation(std::span keys, int frame, mat // OFFSET: 0x00540BF0 // FUNCTION: fn_01725 -void SampleLegacyScale(std::span keys, int, matrix& output) { - if (keys.empty()) { +void SampleLegacyScale(const std::vector& keys, int, matrix& output) { + const unsigned count = keys.size(); + + if (count == 0) { output.Identity(); - } else if (keys.size() == 1) { + } else if (count == 1) { output.SetScale(keys[0].scale[0], keys[0].scale[1], keys[0].scale[2]); } } // OFFSET: 0x00540C60 // FUNCTION: fn_01726 -void SampleModelScale(std::span keys, float frame, matrix& output) { - if (keys.empty()) { +void SampleModelScale(const std::vector& keys, float frame, matrix& output) { + const unsigned count = keys.size(); + + if (count == 0) { output.Identity(); return; } - if (keys.size() == 1 || frame >= static_cast(keys.back().frame)) { - const auto& key = keys.size() == 1 ? keys[0] : keys.back(); - output.SetScale(key.rotation[0], key.rotation[1], key.rotation[2]); + if (count == 1) { + output.SetScale(keys[0].rotation[0], keys[0].rotation[1], keys[0].rotation[2]); return; } - unsigned next = 0; + const auto& last = keys[count - 1]; - while (!(static_cast(keys[next].frame) > frame)) { - if (++next >= keys.size()) { - output.SetScale(1, 1, 1); - return; + if (frame >= static_cast(last.frame)) { + output.SetScale(last.rotation[0], last.rotation[1], last.rotation[2]); + return; + } + + matrix scale; + scale.Identity(); + ModelRotationKey first{0, {1, 1, 1, 1}}; + ModelRotationKey second{0, {1, 1, 1, 1}}; + + for (unsigned next = 0; next < count; ++next) { + if (static_cast(keys[next].frame) > frame) { + if (next != 0) { + first = keys[next - 1]; + } + + second = keys[next]; + break; } } - const ModelRotationKey first = next ? keys[next - 1] : ModelRotationKey{0, {1, 1, 1, 1}}; - const auto& second = keys[next]; const float amount = second.frame != first.frame ? (frame - static_cast(first.frame)) / static_cast((second.frame - first.frame)) : 0.0f; - output.SetScale( + scale.SetScale( (1.0f - amount) * first.rotation[0] + second.rotation[0] * amount, (1.0f - amount) * first.rotation[1] + second.rotation[1] * amount, first.rotation[2] * (1.0f - amount) + second.rotation[2] * amount ); + output = scale; } // OFFSET: 0x005404A0 // FUNCTION: fn_01722 -void SampleModelPosition(std::span keys, float frame, const matrix& base, matrix& output) { - if (keys.empty()) { +void SampleModelPosition(const std::vector& keys, float frame, const matrix& base, matrix& output) { + const unsigned count = keys.size(); + + if (count == 0) { output.values[9] = base.values[9]; output.values[10] = base.values[10]; output.values[11] = base.values[11]; - return; } - if (keys.size() == 1 || !(frame < static_cast(keys.back().frame))) { - const auto& key = keys.size() == 1 ? keys[0] : keys.back(); - output.values[9] = key.rotation[0]; - output.values[10] = key.rotation[1]; - output.values[11] = key.rotation[2]; - + if (count == 1) { + output.values[9] = keys[0].rotation[0]; + output.values[10] = keys[0].rotation[1]; + output.values[11] = keys[0].rotation[2]; return; } - unsigned next = 0; - - while (!(static_cast(keys[next].frame) > frame)) { - ++next; + if (frame >= static_cast(keys[count - 1].frame)) { + output.values[9] = keys[keys.size() - 1].rotation[0]; + output.values[10] = keys[keys.size() - 1].rotation[1]; + output.values[11] = keys[keys.size() - 1].rotation[2]; + return; + } + + ModelRotationKey first; + ModelRotationKey second; + + for (unsigned next = 0; next < count; ++next) { + if (static_cast(keys[next].frame) > frame) { + first = next ? keys[next - 1] : ModelRotationKey{0, {base.values[9], base.values[10], base.values[11], 0}}; + second = keys[next]; + break; + } } - const ModelRotationKey first = next ? keys[next - 1] : ModelRotationKey{0, {base.values[9], base.values[10], base.values[11], 0}}; - const auto& second = keys[next]; const float amount = (frame - static_cast(first.frame)) / static_cast((second.frame - first.frame)); const float previous = 1.0f - amount; @@ -163,24 +197,34 @@ void SampleModelPosition(std::span keys, float frame, co // OFFSET: 0x005407A0 // FUNCTION: fn_01724 -void SampleModelRotation(std::span keys, float frame, const matrix& base, matrix& output) { +void SampleModelRotation(const std::vector& keys, float frame, const matrix& base, matrix& output) { matrix rotation; + rotation.Identity(); + const unsigned count = keys.size(); - if (keys.empty()) { + if (count == 0) { rotation = base; - } else if (keys.size() == 1 || frame >= static_cast(keys.back().frame)) { - QuaternionMatrix(keys.size() == 1 ? keys[0] : keys.back(), rotation); + } else if (count == 1) { + QuaternionMatrix(keys[0], rotation); + } else if (frame >= static_cast(keys[count - 1].frame)) { + QuaternionMatrix(keys[count - 1], rotation); } else { - unsigned next = 0; + ModelRotationKey a{0, {0, 0, 0, 1}}; + ModelRotationKey b{0, {0, 0, 0, 1}}; - while (!(static_cast(keys[next].frame) > frame)) { - if (++next >= keys.size()) { + for (unsigned next = 0; next < count; ++next) { + if (static_cast(keys[next].frame) > frame) { + if (next == 0) { + a = MatrixQuaternion(base); + } else { + a = keys[next - 1]; + } + + b = keys[next]; break; } } - ModelRotationKey a = next < keys.size() ? (next ? keys[next - 1] : MatrixQuaternion(base)) : ModelRotationKey{0, {0, 0, 0, 1}}; - ModelRotationKey b = next < keys.size() ? keys[next] : ModelRotationKey{0, {0, 0, 0, 1}}; const float amount = b.frame != a.frame ? (frame - static_cast(a.frame)) / static_cast((b.frame - a.frame)) : 0.0f; float dot = ((b.rotation[0] * a.rotation[0] + b.rotation[1] * a.rotation[1]) + b.rotation[2] * a.rotation[2]) + b.rotation[3] * a.rotation[3]; diff --git a/Source/Contents/Models/ModelAnimation.h b/Source/Contents/Models/ModelAnimation.h index 434dedc4..cd2e9ccf 100644 --- a/Source/Contents/Models/ModelAnimation.h +++ b/Source/Contents/Models/ModelAnimation.h @@ -4,14 +4,14 @@ #include "Resource/Models/ModelResource.h" #include "Utility/Math/AffineMatrix.h" -#include +#include -void SampleLegacyPosition(std::span keys, int frame, matrix& output); -void SampleLegacyRotation(std::span keys, int frame, matrix& output); -void SampleLegacyScale(std::span keys, int frame, matrix& output); -void SampleModelScale(std::span keys, float frame, matrix& output); -void SampleModelPosition(std::span keys, float frame, const matrix& base, matrix& output); -void SampleModelRotation(std::span keys, float frame, const matrix& base, matrix& output); +void SampleLegacyPosition(const std::vector& keys, int frame, matrix& output); +void SampleLegacyRotation(const std::vector& keys, int frame, matrix& output); +void SampleLegacyScale(const std::vector& keys, int frame, matrix& output); +void SampleModelScale(const std::vector& keys, float frame, matrix& output); +void SampleModelPosition(const std::vector& keys, float frame, const matrix& base, matrix& output); +void SampleModelRotation(const std::vector& keys, float frame, const matrix& base, matrix& output); void QuaternionMatrix(const ModelRotationKey& key, matrix& output); void InterpolateModelRotation(float amount, const ModelRotationKey& first, const ModelRotationKey& second, int spins, ModelRotationKey& output);