Decompile 4 functions in Source/Contents/Models/ModelAnimation.cpp, Source/Contents/Models/ModelAnimation.h, ...

Batch #14054 by Yommy: 4 byte-identical, 0 confirmed by peer review.

- fn_01725 LegacyScaleTrack::Sample: byte-identical
- fn_17465 C3dNodeV1::C3dNodeV1: byte-identical (already on main)
- fn_17466 C3dNodeV2::C3dNodeV2: byte-identical (already on main)
- fn_17507 C3dNodeV1::Animate: byte-identical

Merged automatically: every function is byte-identical to the original.
This commit is contained in:
ragnarok-clanker 2026-11-07 04:50:11 +00:00
commit be2cf07140
4 changed files with 94 additions and 51 deletions

View file

@ -1,6 +1,7 @@
#include "Contents/Models/ModelAnimation.h"
#include <cmath>
#include <cstring>
namespace {
__declspec(noinline) ModelRotationKey MatrixQuaternion(const matrix& matrix);
@ -24,11 +25,12 @@ namespace {
// OFFSET: 0x00540370
// FUNCTION: fn_01721
void SampleLegacyPosition(const std::vector<ModelPositionKey>& keys, int frame, matrix& output) {
void LegacyPositionTrack::Sample(int frame, matrix& output) const {
const std::vector<ModelPositionKey>& keys = *this;
const unsigned count = keys.size();
if (count == 0) {
output.Identity();
std::memcpy(output.values, g_identityMatrix, sizeof(g_identityMatrix));
return;
}
@ -53,11 +55,12 @@ void SampleLegacyPosition(const std::vector<ModelPositionKey>& keys, int frame,
// OFFSET: 0x00540670
// FUNCTION: fn_01723
void SampleLegacyRotation(const std::vector<ModelRotationKey>& keys, int frame, matrix& output) {
void LegacyRotationTrack::Sample(int frame, matrix& output) const {
const std::vector<ModelRotationKey>& keys = *this;
const unsigned count = keys.size();
if (count == 0) {
output.Identity();
std::memcpy(output.values, g_identityMatrix, sizeof(g_identityMatrix));
return;
}
@ -82,7 +85,7 @@ void SampleLegacyRotation(const std::vector<ModelRotationKey>& keys, int frame,
const auto& b = keys[next];
if (a.rotation[3] == 1.0f && b.rotation[3] == 1.0f) {
output.Identity();
std::memcpy(output.values, g_identityMatrix, sizeof(g_identityMatrix));
return;
}
@ -94,11 +97,12 @@ void SampleLegacyRotation(const std::vector<ModelRotationKey>& keys, int frame,
// OFFSET: 0x00540BF0
// FUNCTION: fn_01725
void SampleLegacyScale(const std::vector<ModelScaleKey>& keys, int, matrix& output) {
void LegacyScaleTrack::Sample(int, matrix& output) const {
const std::vector<ModelScaleKey>& keys = *this;
const unsigned count = keys.size();
if (count == 0) {
output.Identity();
std::memcpy(output.values, g_identityMatrix, sizeof(g_identityMatrix));
} else if (count == 1) {
output.SetScale(keys[0].scale[0], keys[0].scale[1], keys[0].scale[2]);
}
@ -106,11 +110,12 @@ void SampleLegacyScale(const std::vector<ModelScaleKey>& keys, int, matrix& outp
// OFFSET: 0x00540C60
// FUNCTION: fn_01726
void SampleModelScale(const std::vector<ModelRotationKey>& keys, float frame, matrix& output) {
void ModelScaleTrack::Sample(float frame, matrix& output) const {
const std::vector<ModelRotationKey>& keys = *this;
const unsigned count = keys.size();
if (count == 0) {
output.Identity();
std::memcpy(output.values, g_identityMatrix, sizeof(g_identityMatrix));
return;
}
@ -127,7 +132,7 @@ void SampleModelScale(const std::vector<ModelRotationKey>& keys, float frame, ma
}
matrix scale;
scale.Identity();
std::memcpy(scale.values, g_identityMatrix, sizeof(g_identityMatrix));
ModelRotationKey first{0, {1, 1, 1, 1}};
ModelRotationKey second{0, {1, 1, 1, 1}};
@ -152,7 +157,8 @@ void SampleModelScale(const std::vector<ModelRotationKey>& keys, float frame, ma
// OFFSET: 0x005404A0
// FUNCTION: fn_01722
void SampleModelPosition(const std::vector<ModelRotationKey>& keys, float frame, const matrix& base, matrix& output) {
void ModelPositionTrack::Sample(float frame, const matrix& base, matrix& output) const {
const std::vector<ModelRotationKey>& keys = *this;
const unsigned count = keys.size();
if (count == 0) {
@ -176,13 +182,18 @@ void SampleModelPosition(const std::vector<ModelRotationKey>& keys, float frame,
return;
}
ModelRotationKey first;
ModelRotationKey second;
ModelPositionKey first;
ModelPositionKey second;
for (unsigned next = 0; next < count; ++next) {
if (static_cast<float>(keys[next].frame) > frame) {
first = next ? keys[next - 1] : ModelRotationKey{0, {base.values[9], base.values[10], base.values[11], 0}};
second = keys[next];
if (next == 0) {
first = ModelPositionKey{0, {base.values[9], base.values[10], base.values[11]}};
} else {
std::memcpy(&first, &keys[next - 1], sizeof(first));
}
std::memcpy(&second, &keys[next], sizeof(second));
break;
}
}
@ -190,16 +201,17 @@ void SampleModelPosition(const std::vector<ModelRotationKey>& keys, float frame,
const float amount = (frame - static_cast<float>(first.frame)) / static_cast<float>((second.frame - first.frame));
const float previous = 1.0f - amount;
output.values[9] = first.rotation[0] * previous + second.rotation[0] * amount;
output.values[10] = first.rotation[1] * previous + second.rotation[1] * amount;
output.values[11] = first.rotation[2] * previous + second.rotation[2] * amount;
output.values[9] = first.position[0] * previous + second.position[0] * amount;
output.values[10] = first.position[1] * previous + second.position[1] * amount;
output.values[11] = first.position[2] * previous + second.position[2] * amount;
}
// OFFSET: 0x005407A0
// FUNCTION: fn_01724
void SampleModelRotation(const std::vector<ModelRotationKey>& keys, float frame, const matrix& base, matrix& output) {
void ModelRotationTrack::Sample(float frame, const matrix& base, matrix& output) const {
const std::vector<ModelRotationKey>& keys = *this;
matrix rotation;
rotation.Identity();
std::memcpy(rotation.values, g_identityMatrix, sizeof(g_identityMatrix));
const unsigned count = keys.size();
if (count == 0) {
@ -239,21 +251,23 @@ void SampleModelRotation(const std::vector<ModelRotationKey>& keys, float frame,
float firstWeight;
float secondWeight;
if (!(dot > -0.95f)) {
if (dot > -0.95f) {
if (dot <= 0.95f) {
const float angle = static_cast<float>(std::acos(static_cast<double>(dot)));
const float denominator = ClientSin(angle);
firstWeight = ClientSin((1.0f - amount) * angle) / denominator;
secondWeight = ClientSin(angle * amount) / denominator;
} else {
firstWeight = 1.0f - amount;
secondWeight = amount;
}
} else {
b.rotation[0] = -a.rotation[1];
b.rotation[1] = a.rotation[0];
b.rotation[2] = -a.rotation[3];
b.rotation[3] = a.rotation[2];
firstWeight = ClientSin((0.5f - amount) * 3.141592f);
secondWeight = ClientSin(amount * 3.141592f);
} else if (dot > 0.95f) {
firstWeight = 1.0f - amount;
secondWeight = amount;
} else {
const float angle = static_cast<float>(std::acos(static_cast<double>(dot)));
const float denominator = ClientSin(angle);
firstWeight = ClientSin((1.0f - amount) * angle) / denominator;
secondWeight = ClientSin(angle * amount) / denominator;
}
ModelRotationKey result{0, {}};

View file

@ -6,12 +6,41 @@
#include <vector>
void SampleLegacyPosition(const std::vector<ModelPositionKey>& keys, int frame, matrix& output);
void SampleLegacyRotation(const std::vector<ModelRotationKey>& keys, int frame, matrix& output);
void SampleLegacyScale(const std::vector<ModelScaleKey>& keys, int frame, matrix& output);
void SampleModelScale(const std::vector<ModelRotationKey>& keys, float frame, matrix& output);
void SampleModelPosition(const std::vector<ModelRotationKey>& keys, float frame, const matrix& base, matrix& output);
void SampleModelRotation(const std::vector<ModelRotationKey>& keys, float frame, const matrix& base, matrix& output);
class LegacyPositionTrack : public std::vector<ModelPositionKey> {
public:
using std::vector<ModelPositionKey>::operator=;
void Sample(int frame, matrix& output) const;
};
class LegacyRotationTrack : public std::vector<ModelRotationKey> {
public:
using std::vector<ModelRotationKey>::operator=;
void Sample(int frame, matrix& output) const;
};
class LegacyScaleTrack : public std::vector<ModelScaleKey> {
public:
using std::vector<ModelScaleKey>::operator=;
void Sample(int frame, matrix& output) const;
};
class ModelScaleTrack : public std::vector<ModelRotationKey> {
public:
using std::vector<ModelRotationKey>::operator=;
void Sample(float frame, matrix& output) const;
};
class ModelPositionTrack : public std::vector<ModelRotationKey> {
public:
using std::vector<ModelRotationKey>::operator=;
void Sample(float frame, const matrix& base, matrix& output) const;
};
class ModelRotationTrack : public std::vector<ModelRotationKey> {
public:
using std::vector<ModelRotationKey>::operator=;
void Sample(float frame, const matrix& base, matrix& output) const;
};
void QuaternionMatrix(const ModelRotationKey& key, matrix& output);
void InterpolateModelRotation(float amount, const ModelRotationKey& first, const ModelRotationKey& second, int spins, ModelRotationKey& output);

View file

@ -127,12 +127,12 @@ void C3dNodeV1::Animate(double frame) {
matrix position;
matrix scale;
matrix rotation;
position.Identity();
scale.Identity();
rotation.Identity();
SampleLegacyPosition(this->positionKeys, selected, position);
SampleLegacyRotation(this->rotationKeys, selected, rotation);
SampleLegacyScale(this->scaleKeys, selected, scale);
std::memcpy(position.values, g_identityMatrix, sizeof(g_identityMatrix));
std::memcpy(scale.values, g_identityMatrix, sizeof(g_identityMatrix));
std::memcpy(rotation.values, g_identityMatrix, sizeof(g_identityMatrix));
this->positionKeys.Sample(selected, position);
this->rotationKeys.Sample(selected, rotation);
this->scaleKeys.Sample(selected, scale);
matrix combined;
combined.Compose(scale, rotation);
this->transform.Compose(combined, position);
@ -145,11 +145,11 @@ void C3dNodeV1::Animate(double frame) {
// OFFSET: 0x00AB9210
// FUNCTION: fn_17508
void C3dNodeV2::Animate(double frame) {
this->transform.Identity();
std::memcpy(this->transform.values, g_identityMatrix, sizeof(g_identityMatrix));
const float selected = static_cast<float>(frame);
SampleModelScale(this->scaleKeys, selected, this->transform);
SampleModelRotation(this->rotationKeys, selected, this->localTransform, this->transform);
SampleModelPosition(this->positionKeys, selected, this->localTransform, this->transform);
this->scaleKeys.Sample(selected, this->transform);
this->rotationKeys.Sample(selected, this->localTransform, this->transform);
this->positionKeys.Sample(selected, this->localTransform, this->transform);
this->textureTransforms.clear();
for (auto it = this->textureKeys.begin(); it != this->textureKeys.end(); ++it) {

View file

@ -51,9 +51,9 @@ public:
void Animate(double frame) override;
void Draw(const float* matrix, unsigned char reversed, bool clip, unsigned char commandMode) override;
/* 008C */ std::vector<ModelScaleKey> scaleKeys;
/* 0098 */ std::vector<ModelRotationKey> rotationKeys;
/* 00A4 */ std::vector<ModelPositionKey> positionKeys;
/* 008C */ LegacyScaleTrack scaleKeys;
/* 0098 */ LegacyRotationTrack rotationKeys;
/* 00A4 */ LegacyPositionTrack positionKeys;
};
class C3dNodeV2 : public C3dNode {
@ -66,9 +66,9 @@ public:
/* 008C */ matrix resourceTransform;
/* 00BC */ matrix localTransform;
/* 00EC */ std::vector<ModelRotationKey> scaleKeys;
/* 00F8 */ std::vector<ModelRotationKey> rotationKeys;
/* 0104 */ std::vector<ModelRotationKey> positionKeys;
/* 00EC */ ModelScaleTrack scaleKeys;
/* 00F8 */ ModelRotationTrack rotationKeys;
/* 0104 */ ModelPositionTrack positionKeys;
/* 0110 */ std::map<int, ModelTextureChannels> textureKeys;
/* 0118 */ std::map<int, ModelTextureTransform> textureTransforms;
};