Various matches with BETA functions (#1281)

* Match functions to BETA

* Improve `Matrix4::FromQuaternion`

* Improve `Matrix4::ToQuaternion` match

* Fix bug that was fixed in retail

* Match `Vector4::NormalizeQuaternion`
This commit is contained in:
Christian Semmler
2024-12-25 14:05:28 -07:00
committed by GitHub
parent 70baf8cecc
commit 667ea3ff82
6 changed files with 85 additions and 70 deletions

View File

@@ -30,6 +30,7 @@ DECOMP_SIZE_ASSERT(Matrix4, 0x08)
DECOMP_SIZE_ASSERT(MxMatrix, 0x48) DECOMP_SIZE_ASSERT(MxMatrix, 0x48)
// FUNCTION: LEGO1 0x10001e60 // FUNCTION: LEGO1 0x10001e60
// FUNCTION: BETA10 0x1002a0d0
Helicopter::Helicopter() Helicopter::Helicopter()
{ {
m_maxLinearVel = 60; m_maxLinearVel = 60;
@@ -43,6 +44,7 @@ Helicopter::~Helicopter()
} }
// FUNCTION: LEGO1 0x100032c0 // FUNCTION: LEGO1 0x100032c0
// FUNCTION: BETA10 0x1002a16d
MxResult Helicopter::Create(MxDSAction& p_dsAction) MxResult Helicopter::Create(MxDSAction& p_dsAction)
{ {
MxResult result = IslePathActor::Create(p_dsAction); MxResult result = IslePathActor::Create(p_dsAction);
@@ -52,6 +54,8 @@ MxResult Helicopter::Create(MxDSAction& p_dsAction)
((Act3*) m_world)->SetHelicopter(this); ((Act3*) m_world)->SetHelicopter(this);
} }
assert(m_world);
if (m_world != NULL) { if (m_world != NULL) {
m_world->Add(this); m_world->Add(this);
} }
@@ -61,6 +65,7 @@ MxResult Helicopter::Create(MxDSAction& p_dsAction)
} }
// FUNCTION: LEGO1 0x10003320 // FUNCTION: LEGO1 0x10003320
// FUNCTION: BETA10 0x1002a240
void Helicopter::CreateState() void Helicopter::CreateState()
{ {
m_state = (HelicopterState*) GameState()->GetState("HelicopterState"); m_state = (HelicopterState*) GameState()->GetState("HelicopterState");
@@ -70,8 +75,11 @@ void Helicopter::CreateState()
} }
// FUNCTION: LEGO1 0x10003360 // FUNCTION: LEGO1 0x10003360
// FUNCTION: BETA10 0x1002a29a
void Helicopter::Exit() void Helicopter::Exit()
{ {
assert(UserActor() == this);
if (GameState()->GetCurrentAct() == LegoGameState::e_act1) { if (GameState()->GetCurrentAct() == LegoGameState::e_act1) {
SpawnPlayer( SpawnPlayer(
LegoGameState::e_unk40, LegoGameState::e_unk40,
@@ -110,6 +118,7 @@ void Helicopter::Exit()
} }
// FUNCTION: LEGO1 0x10003480 // FUNCTION: LEGO1 0x10003480
// FUNCTION: BETA10 0x1002a3db
MxLong Helicopter::HandleClick() MxLong Helicopter::HandleClick()
{ {
if (!FUN_1003ef60()) { if (!FUN_1003ef60()) {
@@ -118,6 +127,7 @@ MxLong Helicopter::HandleClick()
if (!m_world) { if (!m_world) {
m_world = CurrentWorld(); m_world = CurrentWorld();
assert(m_world);
} }
AnimationManager()->FUN_1005f6d0(FALSE); AnimationManager()->FUN_1005f6d0(FALSE);
@@ -163,6 +173,8 @@ MxLong Helicopter::HandleClick()
MxLong Helicopter::HandleControl(LegoControlManagerNotificationParam& p_param) MxLong Helicopter::HandleControl(LegoControlManagerNotificationParam& p_param)
{ {
MxLong result = 0; MxLong result = 0;
assert(m_world);
MxAtomId script; MxAtomId script;
switch (GameState()->GetCurrentAct()) { switch (GameState()->GetCurrentAct()) {
@@ -199,9 +211,10 @@ MxLong Helicopter::HandleControl(LegoControlManagerNotificationParam& p_param)
break; break;
} }
Act1State* state = (Act1State*) GameState()->GetState("Act1State"); Act1State* act1State = (Act1State*) GameState()->GetState("Act1State");
assert(act1State);
if (m_state->m_unk0x08 == 0) { if (m_state->m_unk0x08 == 0) {
state->m_unk0x018 = 4; act1State->m_unk0x018 = 4;
m_state->m_unk0x08 = 1; m_state->m_unk0x08 = 1;
m_world->RemoveActor(this); m_world->RemoveActor(this);
InvokeAction(Extra::ActionType::e_start, script, IsleScript::c_HelicopterTakeOff_Anim, NULL); InvokeAction(Extra::ActionType::e_start, script, IsleScript::c_HelicopterTakeOff_Anim, NULL);
@@ -303,9 +316,9 @@ MxLong Helicopter::HandleEndAnim(LegoEndAnimNotificationParam& p_param)
switch (m_state->m_unk0x08) { switch (m_state->m_unk0x08) {
case 1: { case 1: {
if (GameState()->GetCurrentAct() == LegoGameState::e_act1) { if (GameState()->GetCurrentAct() == LegoGameState::e_act1) {
Act1State* act1state = (Act1State*) GameState()->GetState("Act1State"); Act1State* act1State = (Act1State*) GameState()->GetState("Act1State");
assert(act1state); assert(act1State);
act1state->m_unk0x018 = 4; act1State->m_unk0x018 = 4;
SpawnPlayer( SpawnPlayer(
LegoGameState::e_unk42, LegoGameState::e_unk42,
TRUE, TRUE,
@@ -344,9 +357,9 @@ MxLong Helicopter::HandleEndAnim(LegoEndAnimNotificationParam& p_param)
m_world->GetCameraController()->SetWorldTransform(at, dir, up); m_world->GetCameraController()->SetWorldTransform(at, dir, up);
if (GameState()->GetCurrentAct() == LegoGameState::e_act1) { if (GameState()->GetCurrentAct() == LegoGameState::e_act1) {
Act1State* act1state = (Act1State*) GameState()->GetState("Act1State"); Act1State* act1State = (Act1State*) GameState()->GetState("Act1State");
assert(act1state); assert(act1State);
act1state->m_unk0x018 = 0; act1State->m_unk0x018 = 0;
SpawnPlayer( SpawnPlayer(
LegoGameState::e_unk41, LegoGameState::e_unk41,
TRUE, TRUE,
@@ -423,7 +436,7 @@ void Helicopter::Animate(float p_time)
((Act3*) m_world)->FUN_10073430(); ((Act3*) m_world)->FUN_10073430();
} }
LegoPathActor::m_actorState = c_disabled; SetActorState(c_disabled);
} }
} }
else { else {

View File

@@ -716,7 +716,7 @@ MxResult LegoAnimPresenter::FUN_1006b140(LegoROI* p_roi)
for (i = 1; i <= m_roiMapSize; i++) { for (i = 1; i <= m_roiMapSize; i++) {
if (m_roiMap[i] == p_roi) { if (m_roiMap[i] == p_roi) {
if (local5c[i].Unknown(local58) != SUCCESS) { if (local5c[i].BETA_1005a590(local58) != SUCCESS) {
goto done; goto done;
} }

View File

@@ -675,6 +675,9 @@
// LIBRARY: BETA10 0x100f9a50 // LIBRARY: BETA10 0x100f9a50
// _sin // _sin
// LIBRARY: BETA10 0x100f9a5a
// _cos
// LIBRARY: BETA10 0x100f95d0 // LIBRARY: BETA10 0x100f95d0
// _sqrt // _sqrt

View File

@@ -164,10 +164,9 @@ inline int UnknownMx4DPointFloat::BETA_1004aaa0(Matrix4& p_matrix, float p_f)
if (FUN_100040a0(v, p_f) == 0) { if (FUN_100040a0(v, p_f) == 0) {
return p_matrix.FromQuaternion(v); return p_matrix.FromQuaternion(v);
} }
else {
return -1; return -1;
} }
}
// FUNCTION: LEGO1 0x10004520 // FUNCTION: LEGO1 0x10004520
inline long UnknownMx4DPointFloat::FUN_10004520() inline long UnknownMx4DPointFloat::FUN_10004520()
@@ -201,12 +200,14 @@ inline int UnknownMx4DPointFloat::FUN_100040a0(Vector4& p_v, float p_f)
p_v[3] = (float) ((1.0 - p_f) * acos((double) p_v[3]) * 2.0); p_v[3] = (float) ((1.0 - p_f) * acos((double) p_v[3]) * 2.0);
return p_v.NormalizeQuaternion(); return p_v.NormalizeQuaternion();
} }
else if (m_unk0x30 == c_bit2) {
if (m_unk0x30 == c_bit2) {
p_v = m_unk0x18; p_v = m_unk0x18;
p_v[3] = (float) (p_f * acos((double) p_v[3]) * 2.0); p_v[3] = (float) (p_f * acos((double) p_v[3]) * 2.0);
return p_v.NormalizeQuaternion(); return p_v.NormalizeQuaternion();
} }
else if (m_unk0x30 == (c_bit1 | c_bit2)) {
if (m_unk0x30 == (c_bit1 | c_bit2)) {
int i; int i;
double d1 = p_v.Dot(m_unk0x00, m_unk0x18); double d1 = p_v.Dot(m_unk0x00, m_unk0x18);
double a; double a;
@@ -243,9 +244,8 @@ inline int UnknownMx4DPointFloat::FUN_100040a0(Vector4& p_v, float p_f)
return 0; return 0;
} }
else {
return -1; return -1;
} }
}
#endif // MXGEOMETRY3D_H #endif // MXGEOMETRY3D_H

View File

@@ -179,7 +179,7 @@ public:
} }
} }
inline int Unknown(Matrix4& p_mat); inline int BETA_1005a590(Matrix4& p_mat);
// FUNCTION: LEGO1 0x1006b500 // FUNCTION: LEGO1 0x1006b500
void Swap(int p_d1, int p_d2) void Swap(int p_d1, int p_d2)
@@ -202,9 +202,11 @@ protected:
// FUNCTION: BETA10 0x100101c0 // FUNCTION: BETA10 0x100101c0
inline void Matrix4::ToQuaternion(Vector4& p_outQuat) inline void Matrix4::ToQuaternion(Vector4& p_outQuat)
{ {
float trace = m_data[0][0] + m_data[1][1] + m_data[2][2]; float trace;
if (trace > 0) { float localc = m_data[0][0] + m_data[1][1] + m_data[2][2];
trace = (float) sqrt(trace + 1.0);
if (localc > 0) {
trace = (float) sqrt(localc + 1.0);
p_outQuat[3] = trace * 0.5f; p_outQuat[3] = trace * 0.5f;
trace = 0.5f / trace; trace = 0.5f / trace;
p_outQuat[0] = (m_data[2][1] - m_data[1][2]) * trace; p_outQuat[0] = (m_data[2][1] - m_data[1][2]) * trace;
@@ -212,7 +214,6 @@ inline void Matrix4::ToQuaternion(Vector4& p_outQuat)
p_outQuat[2] = (m_data[1][0] - m_data[0][1]) * trace; p_outQuat[2] = (m_data[1][0] - m_data[0][1]) * trace;
} }
else { else {
// GLOBAL: LEGO1 0x100d4090 // GLOBAL: LEGO1 0x100d4090
static int rotateIndex[] = {1, 2, 0}; static int rotateIndex[] = {1, 2, 0};
@@ -228,8 +229,7 @@ inline void Matrix4::ToQuaternion(Vector4& p_outQuat)
int next = rotateIndex[largest]; int next = rotateIndex[largest];
int nextNext = rotateIndex[next]; int nextNext = rotateIndex[next];
float trace = trace = (float) sqrt(*Element(largest, largest) - (*Element(nextNext, nextNext) + *Element(next, next)) + 1.0);
(float) (sqrt(*Element(largest, largest) - (*Element(nextNext, nextNext) + *Element(next, next)) + 1.0));
p_outQuat[largest] = trace * 0.5f; p_outQuat[largest] = trace * 0.5f;
trace = 0.5f / trace; trace = 0.5f / trace;
@@ -244,38 +244,38 @@ inline void Matrix4::ToQuaternion(Vector4& p_outQuat)
// FUNCTION: BETA10 0x10010550 // FUNCTION: BETA10 0x10010550
inline int Matrix4::FromQuaternion(const Vector4& p_vec) inline int Matrix4::FromQuaternion(const Vector4& p_vec)
{ {
float len = p_vec.LenSquared(); float local14 = p_vec.LenSquared();
if (len > 0.0f) { if (local14 > 0.0f) {
float v7 = 2.0f / len; local14 = 2.0f / local14;
float v9 = p_vec[0] * v7; float local24 = p_vec[0] * local14;
float v11 = p_vec[1] * v7; float local34 = p_vec[1] * local14;
float v12 = p_vec[2] * v7; float local10 = p_vec[2] * local14;
float v13 = p_vec[3] * v9; float local28 = p_vec[3] * local24;
float v14 = p_vec[3] * v11; float local2c = p_vec[3] * local34;
float v16 = p_vec[3] * v12; float local30 = p_vec[3] * local10;
float v17 = p_vec[0] * v9; float local38 = p_vec[0] * local24;
float v22 = p_vec[0] * v11; float local8 = p_vec[0] * local34;
float v23 = p_vec[0] * v12; float localc = p_vec[0] * local10;
float v18 = p_vec[1] * v11; float local18 = p_vec[1] * local34;
float v24 = p_vec[1] * v12; float local1c = p_vec[1] * local10;
float v19 = p_vec[2] * v12; float local20 = p_vec[2] * local10;
m_data[0][0] = 1.0f - (v18 + v19); m_data[0][0] = 1.0f - (local18 + local20);
m_data[1][0] = v22 + v16; m_data[1][0] = local8 + local30;
m_data[2][0] = v23 - v14; m_data[2][0] = localc - local2c;
m_data[0][1] = v22 - v16; m_data[0][1] = local8 - local30;
m_data[1][1] = 1.0f - (v17 + v19); m_data[1][1] = 1.0f - (local38 + local20);
m_data[2][1] = v24 + v13; m_data[2][1] = local1c + local28;
m_data[0][2] = v14 + v23; m_data[0][2] = local2c + localc;
m_data[1][2] = v24 - v13; m_data[1][2] = local1c - local28;
m_data[2][2] = 1.0f - (v18 + v17); m_data[2][2] = 1.0f - (local18 + local38);
m_data[3][0] = 0.0f; m_data[3][0] = 0.0f;
m_data[3][1] = 0.0f; m_data[3][1] = 0.0f;
@@ -287,12 +287,13 @@ inline int Matrix4::FromQuaternion(const Vector4& p_vec)
m_data[2][3] = 0.0f; m_data[2][3] = 0.0f;
return 0; return 0;
} }
else {
return -1; return -1;
} }
}
// FUNCTION: BETA10 0x1005a590 // FUNCTION: BETA10 0x1005a590
inline int Matrix4::Unknown(Matrix4& p_mat) inline int Matrix4::BETA_1005a590(Matrix4& p_mat)
{ {
float local5c[4][4]; float local5c[4][4];
Matrix4 localc(local5c); Matrix4 localc(local5c);

View File

@@ -467,38 +467,36 @@ public:
// FUNCTION: BETA10 0x10048ad0 // FUNCTION: BETA10 0x10048ad0
inline int Vector4::NormalizeQuaternion() inline int Vector4::NormalizeQuaternion()
{ {
float* v = m_data; float length = m_data[0] * m_data[0] + m_data[1] * m_data[1] + m_data[2] * m_data[2];
float magnitude = v[0] * v[0] + v[2] * v[2] + v[1] * v[1];
if (magnitude > 0.0f) { if (length > 0.0f) {
float theta = v[3] * 0.5f; float theta = m_data[3] * 0.5f;
v[3] = cos(theta); float magnitude = sin((double) theta);
magnitude = sin(theta) / sqrt(magnitude); m_data[3] = cos((double) theta);
Vector3::MulImpl(magnitude);
magnitude = magnitude / (float) sqrt((double) length);
m_data[0] *= magnitude;
m_data[1] *= magnitude;
m_data[2] *= magnitude;
return 0; return 0;
} }
else {
return -1; return -1;
} }
inline static float QuaternionProductScalarPart(const float* bDat, const float* aDat)
{
// We have no indication from the beta that this function exists,
// but it helps with the stack layout of Vector4::EqualsHamiltonProduct()
return aDat[3] * bDat[3] - (aDat[0] * bDat[0] + aDat[2] * bDat[2] + aDat[1] * bDat[1]);
} }
// FUNCTION: LEGO1 0x10002bf0 // FUNCTION: LEGO1 0x10002bf0
// FUNCTION: BETA10 0x10048c20 // FUNCTION: BETA10 0x10048c20
inline int Vector4::EqualsHamiltonProduct(const Vector4& p_a, const Vector4& p_b) inline int Vector4::EqualsHamiltonProduct(const Vector4& p_a, const Vector4& p_b)
{ {
m_data[3] = QuaternionProductScalarPart(p_a.m_data, p_b.m_data); m_data[3] = p_a.m_data[3] * p_b.m_data[3] -
(p_a.m_data[0] * p_b.m_data[0] + p_a.m_data[2] * p_b.m_data[2] + p_a.m_data[1] * p_b.m_data[1]);
Vector3::EqualsCrossImpl(p_a.m_data, p_b.m_data); Vector3::EqualsCrossImpl(p_a.m_data, p_b.m_data);
m_data[0] = p_b.m_data[3] * p_a.m_data[0] + p_a.m_data[3] * p_b.m_data[0] + m_data[0]; m_data[0] = p_b.m_data[3] * p_a.m_data[0] + p_a.m_data[3] * p_b.m_data[0] + m_data[0];
m_data[1] = p_b.m_data[1] * p_a.m_data[3] + p_a.m_data[1] * p_b.m_data[3] + m_data[1]; m_data[1] = p_b.m_data[1] * p_a.m_data[3] + p_a.m_data[1] * p_b.m_data[3] + m_data[1];
m_data[2] = p_b.m_data[2] * p_a.m_data[3] + p_a.m_data[2] * p_b.m_data[3] + m_data[2]; m_data[2] = p_b.m_data[2] * p_a.m_data[3] + p_a.m_data[2] * p_b.m_data[3] + m_data[2];
return 0; return 0;
} }