rodecomp/Source/Utility/Math/AffineMatrix.cpp
ragnarok-clanker 8268da4030 Decompile 4 functions in Source/Utility/Math/AffineMatrix.cpp, Source/Utility/Math/AffineMatrix.h
Batch #848 by ragnarok-clanker: 0 byte-identical, 4 confirmed by peer review.

- fn_02026 AffineMatrix::IsIdentity: logic confirmed by peer review
- fn_02028 AffineMatrix::SetScale: logic confirmed by peer review
- fn_02031 AffineMatrix::SetAxisRotation: logic confirmed by peer review
- fn_02032 AffineMatrix::SetTranslation: logic confirmed by peer review

Reviewed-by: ragnarok-clanker
2026-10-26 22:52:27 +00:00

234 lines
7.4 KiB
C++

#include "Utility/Math/AffineMatrix.h"
#include <bit>
#include <cstring>
// STATIC: 0x01312438
// GLOBAL: gl_21913
const float g_identityMatrix[12] = {1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0};
namespace {
// INLINED
void Rotate(float* values, const float* rotation) {
for (unsigned row = 0; row < 4; ++row) {
const float x = values[row * 3];
const float y = values[row * 3 + 1];
const float z = values[row * 3 + 2];
const float first = (x * rotation[0] + y * rotation[3]) + z * rotation[6];
const float second = (x * rotation[1] + y * rotation[4]) + z * rotation[7];
const float third = (x * rotation[2] + y * rotation[5]) + z * rotation[8];
values[row * 3] = row == 3 ? first + rotation[9] : first;
values[row * 3 + 1] = row == 3 ? second + rotation[10] : second;
values[row * 3 + 2] = row == 3 ? third + rotation[11] : third;
}
}
}
// INLINED
void AffineMatrix::Identity() {
std::memcpy(this->values, g_identityMatrix, sizeof(g_identityMatrix));
}
// OFFSET: 0x00555360
// FUNCTION: fn_02034
void AffineMatrix::SetXRotation(float radians) {
this->Identity();
const float sine = ClientSin(radians);
const float cosine = ClientCos(radians);
this->values[4] = cosine;
this->values[8] = cosine;
this->values[5] = sine;
this->values[7] = -sine;
}
// OFFSET: 0x005553D0
// FUNCTION: fn_02035
void AffineMatrix::SetYRotation(float radians) {
this->Identity();
const float sine = ClientSin(radians);
const float cosine = ClientCos(radians);
this->values[0] = cosine;
this->values[8] = cosine;
this->values[2] = -sine;
this->values[6] = sine;
}
// OFFSET: 0x00555440
// FUNCTION: fn_02036
void AffineMatrix::SetZRotation(float radians) {
this->Identity();
const float sine = ClientSin(radians);
const float cosine = ClientCos(radians);
this->values[0] = cosine;
this->values[4] = cosine;
this->values[3] = -sine;
this->values[1] = sine;
}
// OFFSET: 0x00552F70
// FUNCTION: fn_02016
void AffineMatrix::RotateX(float radians) {
AffineMatrix rotation;
rotation.SetXRotation(radians);
Rotate(this->values, rotation.values);
}
// OFFSET: 0x00553270
// FUNCTION: fn_02017
void AffineMatrix::RotateY(float radians) {
AffineMatrix rotation;
rotation.SetYRotation(radians);
Rotate(this->values, rotation.values);
}
// OFFSET: 0x00553570
// FUNCTION: fn_02018
void AffineMatrix::RotateZ(float radians) {
AffineMatrix rotation;
rotation.SetZRotation(radians);
Rotate(this->values, rotation.values);
}
// OFFSET: 0x005550C0
// FUNCTION: fn_02032
void AffineMatrix::SetTranslation(float x, float y, float z) {
std::memcpy(this->values, g_identityMatrix, sizeof(g_identityMatrix));
this->values[9] = x;
this->values[10] = y;
this->values[11] = z;
}
// OFFSET: 0x00554B40
// FUNCTION: fn_02028
void AffineMatrix::SetScale(float x, float y, float z) {
std::memcpy(this->values, g_identityMatrix, sizeof(g_identityMatrix));
this->values[0] = x;
this->values[4] = y;
this->values[8] = z;
}
// OFFSET: 0x005529C0
// FUNCTION: fn_02014
void AffineMatrix::Scale(float x, float y, float z) {
AffineMatrix scale;
scale.SetScale(x, y, z);
Rotate(this->values, scale.values);
}
// OFFSET: 0x00552CA0
// FUNCTION: fn_02015
void AffineMatrix::Translate(const float* position) {
AffineMatrix translation;
translation.SetTranslation(position[0], position[1], position[2]);
Rotate(this->values, translation.values);
}
// OFFSET: 0x005554B0
// FUNCTION: fn_02037
void AffineMatrix::Compose(const AffineMatrix& first, const AffineMatrix& second) {
const float* a = first.values;
const float* b = second.values;
float* output = this->values;
output[0] = (a[0] * b[0] + b[3] * a[1]) + b[6] * a[2];
output[3] = (a[4] * b[3] + a[3] * b[0]) + a[5] * b[6];
output[6] = (a[7] * b[3] + a[6] * b[0]) + a[8] * b[6];
output[9] = ((a[10] * b[3] + a[9] * b[0]) + a[11] * b[6]) + b[9];
output[1] = (b[4] * a[1] + b[1] * a[0]) + b[7] * a[2];
output[4] = (a[4] * b[4] + a[3] * b[1]) + a[5] * b[7];
output[7] = (a[7] * b[4] + a[6] * b[1]) + a[8] * b[7];
output[10] = ((a[10] * b[4] + a[9] * b[1]) + a[11] * b[7]) + b[10];
output[2] = (b[5] * a[1] + b[2] * a[0]) + a[2] * b[8];
output[5] = (b[5] * a[4] + b[2] * a[3]) + a[5] * b[8];
output[8] = (b[5] * a[7] + b[2] * a[6]) + a[8] * b[8];
output[11] = ((b[5] * a[10] + b[2] * a[9]) + a[11] * b[8]) + b[11];
}
// OFFSET: 0x00554920
// FUNCTION: fn_02027
void AffineMatrix::Inverse(const AffineMatrix& source) {
const float* a = source.values;
float* output = this->values;
const float minor = a[4] * a[8] - a[5] * a[7];
const float inverse = 1.0f / ((minor * a[0] - (a[3] * a[8] - a[6] * a[5]) * a[1]) + (a[3] * a[7] - a[6] * a[4]) * a[2]);
const float negative = -inverse;
output[0] = minor * inverse;
const float firstY = (a[1] * a[8] - a[7] * a[2]) * negative;
output[1] = firstY;
const float firstZ = (a[1] * a[5] - a[2] * a[4]) * inverse;
output[2] = firstZ;
const float secondX = (a[3] * a[8] - a[6] * a[5]) * negative;
output[3] = secondX;
const float secondY = (a[0] * a[8] - a[2] * a[6]) * inverse;
output[4] = secondY;
const float secondZ = (a[0] * a[5] - a[2] * a[3]) * negative;
output[5] = secondZ;
const float thirdX = (a[7] * a[3] - a[6] * a[4]) * inverse;
output[6] = thirdX;
const float thirdY = (a[7] * a[0] - a[1] * a[6]) * negative;
output[7] = thirdY;
const float thirdZ = (a[4] * a[0] - a[1] * a[3]) * inverse;
output[8] = thirdZ;
output[9] = -((secondX * a[10] + (minor * inverse) * a[9]) + thirdX * a[11]);
output[10] = -((firstY * a[9] + secondY * a[10]) + thirdY * a[11]);
output[11] = -((secondZ * a[10] + firstZ * a[9]) + thirdZ * a[11]);
}
// FUNCTION: fn_02026
int AffineMatrix::IsIdentity() const {
const auto absolute = [](float value) {
return std::bit_cast<float>(std::bit_cast<unsigned>(value) & 0x7FFFFFFFu);
};
const float tolerance = 1.0e-5f;
if (absolute(this->values[0] - 1.0f) > tolerance || absolute(this->values[4] - 1.0f) > tolerance ||
absolute(this->values[8] - 1.0f) > tolerance || absolute(this->values[1]) > tolerance ||
absolute(this->values[2]) > tolerance || absolute(this->values[3]) > tolerance ||
absolute(this->values[5]) > tolerance || absolute(this->values[6]) > tolerance ||
absolute(this->values[7]) > tolerance || absolute(this->values[9]) > tolerance ||
absolute(this->values[10]) > tolerance || absolute(this->values[11]) > tolerance) {
return 0;
}
return 1;
}
// FUNCTION: fn_02031
const float* AffineMatrix::SetAxisRotation(const float* axis, float radians) {
const float halfAngle = radians * 0.5f;
const float sine = ClientSin(halfAngle);
const float x = sine * axis[0];
const float y = sine * axis[1];
const float z = sine * axis[2];
const float cosine = ClientCos(halfAngle);
this->values[9] = 0.0f;
this->values[10] = 0.0f;
this->values[11] = 0.0f;
const float twiceX = x + x;
const float twiceY = y + y;
const float twiceZ = z + z;
const float wz = cosine * twiceZ;
const float wx = cosine * twiceX;
const float wy = cosine * twiceY;
const float xx = twiceX * x;
const float xy = twiceY * x;
const float yy = twiceY * y;
const float xz = twiceZ * x;
const float zz = twiceZ * z;
const float yz = twiceZ * y;
this->values[0] = 1.0f - (zz + yy);
this->values[1] = xy + wz;
this->values[3] = xy - wz;
this->values[2] = xz - wy;
this->values[6] = xz + wy;
this->values[4] = 1.0f - (zz + xx);
this->values[5] = yz + wx;
this->values[7] = yz - wx;
this->values[8] = 1.0f - (yy + xx);
return axis;
}