rodecomp/Source/Contents/Models/ModelQuaternion.cpp
ragnarok-clanker 9f93b02c69 Decompile 2 functions in Source/Contents/Models/ModelQuaternion.cpp
Batch #16371 by youko: 0 byte-identical, 2 confirmed by peer review.

- fn_02029 QuaternionMatrix: logic confirmed by peer review
- fn_02030 QuaternionMatrix: logic confirmed by peer review

Peer-reviewed-by: Yommy, kyoshi, Toshiro
Accepted without human review: peers confirmed the logic ("same" ahead by at least 3, with 70% of the votes).
2026-11-10 19:54:38 +00:00

69 lines
2.6 KiB
C++

#include "Contents/Models/ModelAnimation.h"
#include <bit>
#include <cmath>
// OFFSET: 0x00554CD0
// FUNCTION: fn_02030
// OFFSET: 0x00554B90
// FUNCTION: fn_02029
void QuaternionMatrix(const ModelRotationKey& key, matrix& output) {
const float x2 = key.rotation[0] + key.rotation[0];
const float y2 = key.rotation[1] + key.rotation[1];
const float z2 = key.rotation[2] + key.rotation[2];
const float wx = key.rotation[3] * x2;
const float wy = key.rotation[3] * y2;
const float wz = key.rotation[3] * z2;
const float xx = key.rotation[0] * x2;
const float xy = key.rotation[0] * y2;
const float xz = key.rotation[0] * z2;
const float yy = key.rotation[1] * y2;
const float yz = key.rotation[1] * z2;
const float zz = key.rotation[2] * z2;
output.values[0] = 1.0f - (yy + zz);
output.values[1] = xy + wz;
output.values[2] = xz - wy;
output.values[3] = xy - wz;
output.values[4] = 1.0f - (xx + zz);
output.values[5] = yz + wx;
output.values[6] = xz + wy;
output.values[7] = yz - wx;
output.values[8] = 1.0f - (xx + yy);
output.values[9] = 0.0f;
output.values[10] = 0.0f;
output.values[11] = 0.0f;
}
// OFFSET: 0x00541B30
// FUNCTION: fn_01736
void InterpolateModelRotation(float amount, const ModelRotationKey& first, const ModelRotationKey& second, int spins, ModelRotationKey& output) {
const float dot = ((second.rotation[1] * first.rotation[1] + second.rotation[0] * first.rotation[0]) + first.rotation[2] * second.rotation[2]) +
first.rotation[3] * second.rotation[3];
const bool flip = dot < 0.0f;
const float magnitude = flip ? -dot : dot;
constexpr double epsilon = 0.000001;
float firstWeight;
float secondWeight;
if (!(epsilon > 1.0 - static_cast<double>(magnitude))) {
const float angle = static_cast<float>(std::acos(static_cast<double>(magnitude)));
const float denominator = ClientSin(angle);
const float phase = (static_cast<float>(spins) * 3.141592f + angle) * amount;
firstWeight = ClientSin(angle - phase) / denominator;
secondWeight = ClientSin(phase) / denominator;
} else {
firstWeight = static_cast<float>(1.0 - static_cast<double>(amount));
secondWeight = amount;
}
if (flip) {
secondWeight = -secondWeight;
}
output.rotation[0] = first.rotation[0] * firstWeight + second.rotation[0] * secondWeight;
output.rotation[1] = secondWeight * second.rotation[1] + firstWeight * first.rotation[1];
output.rotation[2] = firstWeight * first.rotation[2] + secondWeight * second.rotation[2];
output.rotation[3] = firstWeight * first.rotation[3] + secondWeight * second.rotation[3];
}