rodecomp/Source/Contents/Models/ModelActorBounds.cpp
ragnarok-clanker 99698b5fd7 Confirm 2 functions in Source/Contents/Models/ModelActorBounds.cpp
Batch #11481 by kyoshi: 0 byte-identical, 2 confirmed by peer review.

- fn_17512 C3dActorV1::UpdateBounds: logic confirmed by peer review (already on main)
- fn_17513 C3dActorV2::UpdateBounds: logic confirmed by peer review (already on main)

Peer-reviewed-by: Yommy, dori, cremane
Accepted without human review: peers confirmed the logic ("same" ahead by at least 3, with 70% of the votes).
2026-11-05 03:09:25 +00:00

179 lines
6.2 KiB
C++

#include "Contents/Models/ModelActor.h"
#include "Utility/Math/AffineMatrix.h"
#include <cmath>
#include <cstring>
namespace {
// INLINED
float Absolute(float value) {
return std::fabs(value);
}
// INLINED
float Radians(float degrees) {
return (degrees / 180.0f) * 3.141592f;
}
// INLINED
float InverseLength(float squared) {
return 1.0f / SquareRoot(squared);
}
// INLINED
__forceinline void TransformCorner(float* corner, float x, float y, float z, const float* matrix) {
corner[0] = ((x * matrix[0] + y * matrix[3]) + z * matrix[6]) + matrix[9];
corner[1] = ((x * matrix[1] + y * matrix[4]) + z * matrix[7]) + matrix[10];
corner[2] = ((x * matrix[2] + y * matrix[5]) + z * matrix[8]) + matrix[11];
}
// INLINED
__forceinline void SetAxis(float* direction, const float* row) {
direction[0] = row[0];
direction[1] = row[1];
direction[2] = row[2];
const float inverse = InverseLength((direction[0] * direction[0] + direction[1] * direction[1]) + direction[2] * direction[2]);
direction[0] = inverse * direction[0];
direction[1] = inverse * direction[1];
direction[2] = inverse * direction[2];
}
struct BoundsCorner {
float values[3];
// INLINED
BoundsCorner() {
values[0] = 0.0f;
values[1] = 0.0f;
values[2] = 0.0f;
}
// INLINED
__forceinline void Set(float x, float y, float z) {
values[0] = x;
values[1] = y;
values[2] = z;
}
};
// INLINED
float Coordinate(const float* point, const float* matrix, unsigned axis) {
return ((point[0] * matrix[axis] + point[1] * matrix[axis + 3]) + point[2] * matrix[axis + 6]) + matrix[axis + 9];
}
}
// INLINED
__forceinline void C3dActor::FinishBounds(const float* bounds, bool modern) {
for (unsigned axis = 0; axis < 3; ++axis) {
this->minimum[axis] = 100000;
}
for (unsigned axis = 0; axis < 3; ++axis) {
this->maximum[axis] = -100000;
}
BoundsCorner points[8];
points[0].Set(bounds[0], bounds[1], bounds[2]);
points[1].Set(bounds[3], bounds[1], bounds[2]);
points[2].Set(bounds[0], bounds[4], bounds[2]);
points[3].Set(bounds[3], bounds[4], bounds[2]);
points[4].Set(bounds[0], bounds[1], bounds[5]);
points[5].Set(bounds[3], bounds[1], bounds[5]);
points[6].Set(bounds[0], bounds[4], bounds[5]);
points[7].Set(bounds[3], bounds[4], bounds[5]);
for (unsigned corner = 0; corner < 8; ++corner) {
float* stored = this->corners[corner];
stored[0] = Coordinate(points[corner].values, this->transform.values, 0);
stored[1] = Coordinate(points[corner].values, this->transform.values, 1);
stored[2] = Coordinate(points[corner].values, this->transform.values, 2);
for (unsigned axis = 0; axis < 3; ++axis) {
if (this->minimum[axis] > stored[axis]) {
this->minimum[axis] = stored[axis];
}
}
for (unsigned axis = 0; axis < 3; ++axis) {
if (stored[axis] > this->maximum[axis]) {
this->maximum[axis] = stored[axis];
}
}
}
for (unsigned axis = 0; axis < 3; ++axis) {
const float low = Coordinate(bounds, this->transform.values, axis);
const float high = Coordinate(bounds + 3, this->transform.values, axis);
this->oriented.center[axis] = (modern || axis == 2 ? high + low : low + high) * 0.5f;
}
for (unsigned axis = 0; axis < 3; ++axis) {
this->oriented.halfSize[axis] = Absolute((bounds[axis + 3] - bounds[axis]) * this->scale[axis]) * 0.5f;
}
matrix axes;
axes.SetScale(this->scale[0], this->scale[1], this->scale[2]);
axes.AppendYRotation(Radians(this->rotation[1]));
axes.AppendXRotation(Radians(this->rotation[0]));
axes.AppendZRotation(Radians(this->rotation[2]));
SetAxis(this->oriented.axes[0], axes.values);
SetAxis(this->oriented.axes[1], axes.values + 3);
SetAxis(this->oriented.axes[2], axes.values + 6);
for (ModelVolume* volume : this->volumes) {
volume->transform.MakeXRotation(Radians(volume->rotation[0]));
volume->transform.AppendYRotation(Radians(volume->rotation[1]));
volume->transform.AppendZRotation(Radians(volume->rotation[2]));
volume->transform.AppendTranslate(volume->position);
volume->inverseTransform.MakeInverse(volume->transform);
matrix combined;
combined.Compose(volume->transform, this->transform);
const float* size = volume->size;
TransformCorner(volume->corners[0], -size[0], -size[1], -size[2], combined.values);
TransformCorner(volume->corners[1], size[0], -size[1], -size[2], combined.values);
TransformCorner(volume->corners[2], size[0], size[1], -size[2], combined.values);
TransformCorner(volume->corners[3], -size[0], size[1], -size[2], combined.values);
TransformCorner(volume->corners[4], -size[0], -size[1], size[2], combined.values);
TransformCorner(volume->corners[5], size[0], -size[1], size[2], combined.values);
TransformCorner(volume->corners[6], size[0], size[1], size[2], combined.values);
TransformCorner(volume->corners[7], -size[0], size[1], size[2], combined.values);
}
this->dirty = 1;
}
// OFFSET: 0x00AB9660
// FUNCTION: fn_17512
void C3dActorV1::UpdateBounds() {
float bounds[6] = {100000, 100000, 100000, -100000, -100000, -100000};
matrix identity;
std::memcpy(identity.values, g_identityMatrix, sizeof(identity.values));
this->root->AccumulateBounds(bounds, identity.values);
this->offset[0] = -(bounds[3] + bounds[0]) * 0.5f;
this->offset[1] = -bounds[4];
this->offset[2] = -(bounds[5] + bounds[2]) * 0.5f;
this->transform.MakeTranslate(this->offset[0], this->offset[1], this->offset[2]);
this->transform.AppendScale(this->scale[0], this->scale[1], this->scale[2]);
this->transform.AppendYRotation(Radians(this->rotation[1]));
this->transform.AppendXRotation(Radians(this->rotation[0]));
this->transform.AppendZRotation(Radians(this->rotation[2]));
this->transform.AppendTranslate(this->position);
this->FinishBounds(bounds, false);
}
// OFFSET: 0x00ABA520
// FUNCTION: fn_17513
void C3dActorV2::UpdateBounds() {
float bounds[6] = {100000, 100000, 100000, -100000, -100000, -100000};
matrix identity;
std::memcpy(identity.values, g_identityMatrix, sizeof(identity.values));
for (C3dNodeV2* root : this->roots) {
root->AccumulateBounds(bounds, identity.values);
}
this->UpdateMatrix();
this->FinishBounds(bounds, true);
}