diff --git a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp index bb23e5d7..4b9d78ea 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp @@ -1388,7 +1388,7 @@ void LegoCarBuild::SetPartColor(MxS32 p_objectId) m_Paint_Sound->Enable(FALSE); m_Paint_Sound->Enable(TRUE); - m_selectedPart->FUN_100a93b0(color); + m_selectedPart->SetColorByName(color); sprintf(buffer, "c_%s", m_selectedPart->GetName()); VariableTable()->SetVariable(buffer, color); } diff --git a/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp b/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp index 60356a0b..3afd211f 100644 --- a/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp @@ -502,7 +502,7 @@ inline MxU32 LegoExtraActor::VTable0x6c( } } else { - if (roi->FUN_100a9410(p_v1, p_v2, p_f1, p_f2, p_v3, m_collideBox && actor->GetCollideBox())) { + if (roi->Intersect(p_v1, p_v2, p_f1, p_f2, p_v3, m_collideBox && actor->GetCollideBox())) { if (HitActor(actor, TRUE) < 0) { return 0; } diff --git a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp index 1cf40934..0b1c0c2f 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp @@ -487,7 +487,7 @@ MxU32 LegoPathActor::VTable0x6c( LegoROI* roi = actor->GetROI(); if (roi != NULL && (roi->GetVisibility() || actor->GetCameraFlag())) { - if (roi->FUN_100a9410(p_v1, p_v2, p_f1, p_f2, p_v3, m_collideBox && actor->m_collideBox)) { + if (roi->Intersect(p_v1, p_v2, p_f1, p_f2, p_v3, m_collideBox && actor->m_collideBox)) { HitActor(actor, TRUE); actor->HitActor(this, FALSE); return 2; diff --git a/LEGO1/lego/legoomni/src/race/legoracespecial.cpp b/LEGO1/lego/legoomni/src/race/legoracespecial.cpp index 45a6d664..72099caf 100644 --- a/LEGO1/lego/legoomni/src/race/legoracespecial.cpp +++ b/LEGO1/lego/legoomni/src/race/legoracespecial.cpp @@ -456,14 +456,8 @@ inline MxU32 LegoCarRaceActor::VTable0x6c( LegoROI* firstROI = (LegoROI*) co->front(); - if (firstROI->FUN_100a9410( - p_v1, - p_v2, - p_f1, - p_f2, - p_v3, - m_collideBox && actor->GetCollideBox() - )) { + if (firstROI + ->Intersect(p_v1, p_v2, p_f1, p_f2, p_v3, m_collideBox && actor->GetCollideBox())) { HitActor(actor, TRUE); if (actor->HitActor(this, FALSE) < 0) { @@ -476,14 +470,8 @@ inline MxU32 LegoCarRaceActor::VTable0x6c( LegoROI* lastROI = (LegoROI*) co->back(); - if (lastROI->FUN_100a9410( - p_v1, - p_v2, - p_f1, - p_f2, - p_v3, - m_collideBox && actor->GetCollideBox() - )) { + if (lastROI + ->Intersect(p_v1, p_v2, p_f1, p_f2, p_v3, m_collideBox && actor->GetCollideBox())) { HitActor(actor, TRUE); if (actor->HitActor(this, FALSE) < 0) { @@ -496,7 +484,7 @@ inline MxU32 LegoCarRaceActor::VTable0x6c( } } else { - if (roi->FUN_100a9410(p_v1, p_v2, p_f1, p_f2, p_v3, m_collideBox && actor->GetCollideBox())) { + if (roi->Intersect(p_v1, p_v2, p_f1, p_f2, p_v3, m_collideBox && actor->GetCollideBox())) { HitActor(actor, TRUE); if (actor->HitActor(this, FALSE) < 0) { @@ -544,7 +532,7 @@ inline MxU32 LegoJetskiRaceActor::VTable0x6c( LegoROI* roi = actor->GetROI(); if (roi != NULL && (roi->GetVisibility() || actor->GetCameraFlag())) { - if (roi->FUN_100a9410(p_v1, p_v2, p_f1, p_f2, p_v3, m_collideBox && actor->GetCollideBox())) { + if (roi->Intersect(p_v1, p_v2, p_f1, p_f2, p_v3, m_collideBox && actor->GetCollideBox())) { HitActor(actor, TRUE); if (actor->HitActor(this, FALSE) < 0) { diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index 138a9c68..3b26b126 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -1198,7 +1198,7 @@ MxU32 LegoAnimPresenter::VTable0x94(Vector3& p_v1, Vector3& p_v2, float p_f1, fl len = sqrt(len); if (len <= m_unk0xa4 + p_f2 && m_roiMapSize != 0 && m_roiMap != NULL) { for (MxU32 i = 1; i <= m_roiMapSize; i++) { - if (m_roiMap[i]->GetLODCount() != 0 && m_roiMap[i]->FUN_100a9410(p_v1, p_v2, p_f1, p_f2, p_v3, FALSE)) { + if (m_roiMap[i]->GetLODCount() != 0 && m_roiMap[i]->Intersect(p_v1, p_v2, p_f1, p_f2, p_v3, FALSE)) { return TRUE; } } diff --git a/LEGO1/lego/sources/roi/legoroi.cpp b/LEGO1/lego/sources/roi/legoroi.cpp index 4f7814ce..fd1b6de6 100644 --- a/LEGO1/lego/sources/roi/legoroi.cpp +++ b/LEGO1/lego/sources/roi/legoroi.cpp @@ -61,7 +61,7 @@ TextureHandler g_textureHandler = NULL; // FUNCTION: LEGO1 0x100a81b0 // FUNCTION: BETA10 0x101898c0 // FUNCTION: ALPHA 0x100bb1c0 -void LegoROI::FUN_100a81b0(const LegoChar* p_error, ...) +void LegoROI::ReportError(const LegoChar* p_error, ...) { // Probably a printf-like debug function that was removed early. // No known implementation in any of the binaries. @@ -418,7 +418,7 @@ LegoResult LegoROI::ApplyChildAnimationTransformation( } } else { - FUN_100a81b0("%s ROI Not found\n", name); + ReportError("%s ROI Not found\n", name); #ifdef BETA10 _RPT1(_CRT_ASSERT, "%s ROI Not Found", name); // Note that the macro inserts an INT3, which breaks the assumption that INT3 @@ -582,7 +582,7 @@ LegoResult LegoROI::GetTextureInfo(LegoTextureInfo*& p_textureInfo) // FUNCTION: LEGO1 0x100a9330 // FUNCTION: BETA10 0x1018b22c -LegoResult LegoROI::FUN_100a9330(LegoFloat p_red, LegoFloat p_green, LegoFloat p_blue, LegoFloat p_alpha) +LegoResult LegoROI::SetColor(LegoFloat p_red, LegoFloat p_green, LegoFloat p_blue, LegoFloat p_alpha) { return SetLodColor(p_red, p_green, p_blue, p_alpha); } @@ -601,11 +601,11 @@ LegoResult LegoROI::SetLodColor(const LegoChar* p_name) // FUNCTION: LEGO1 0x100a93b0 // FUNCTION: BETA10 0x1018b2c0 -LegoResult LegoROI::FUN_100a93b0(const LegoChar* p_name) +LegoResult LegoROI::SetColorByName(const LegoChar* p_name) { MxFloat red, green, blue, alpha; if (ColorAliasLookup(p_name, red, green, blue, alpha)) { - return FUN_100a9330(red, green, blue, alpha); + return SetColor(red, green, blue, alpha); } return 0; @@ -613,83 +613,85 @@ LegoResult LegoROI::FUN_100a93b0(const LegoChar* p_name) // FUNCTION: LEGO1 0x100a9410 // FUNCTION: BETA10 0x1018b324 -LegoU32 LegoROI::FUN_100a9410( - Vector3& p_v1, - Vector3& p_v2, - float p_f1, - float p_f2, - Vector3& p_v3, +LegoU32 LegoROI::Intersect( + Vector3& p_rayOrigin, + Vector3& p_rayDirection, + float p_rayLength, + float p_unused, + Vector3& p_intersectionPoint, LegoBool p_collideBox ) { if (p_collideBox) { - Mx3DPointFloat v2(p_v2); - v2 *= p_f1; - v2 += p_v1; + Mx3DPointFloat v2(p_rayDirection); + v2 *= p_rayLength; + v2 += p_rayOrigin; - Mx4DPointFloat localc0; - Mx4DPointFloat local9c; - Mx4DPointFloat local168; - Mx4DPointFloat local70; - Mx4DPointFloat local150[6]; + Mx4DPointFloat minPoint; + Mx4DPointFloat maxPoint; + Mx4DPointFloat centerPoint; + Mx4DPointFloat untransformedPoint; + Mx4DPointFloat boxFacePlanes[6]; - Vector3 local58(&localc0[0]); - Vector3 locala8(&local9c[0]); - Vector3 local38(&local168[0]); + Vector3 boundingBoxMin(&minPoint[0]); + Vector3 boundingBoxMax(&maxPoint[0]); + Vector3 boundingBoxCenter(¢erPoint[0]); - Mx3DPointFloat local4c(p_v1); + Mx3DPointFloat rayOrigin(p_rayOrigin); - local58 = m_bounding_box.Min(); - locala8 = m_bounding_box.Max(); + boundingBoxMin = m_bounding_box.Min(); + boundingBoxMax = m_bounding_box.Max(); - localc0[3] = local9c[3] = local168[3] = 1.0f; + minPoint[3] = maxPoint[3] = centerPoint[3] = 1.0f; - local38 = local58; - local38 += locala8; - local38 *= 0.5f; + boundingBoxCenter = boundingBoxMin; + boundingBoxCenter += boundingBoxMax; + boundingBoxCenter *= 0.5f; - local70 = localc0; - localc0.SetMatrixProduct(local70, (float*) m_local2world.GetData()); + untransformedPoint = minPoint; + minPoint.SetMatrixProduct(untransformedPoint, (float*) m_local2world.GetData()); - local70 = local9c; - local9c.SetMatrixProduct(local70, (float*) m_local2world.GetData()); + untransformedPoint = maxPoint; + maxPoint.SetMatrixProduct(untransformedPoint, (float*) m_local2world.GetData()); - local70 = local168; - local168.SetMatrixProduct(local70, (float*) m_local2world.GetData()); + untransformedPoint = centerPoint; + centerPoint.SetMatrixProduct(untransformedPoint, (float*) m_local2world.GetData()); - p_v3 = m_local2world[3]; + p_intersectionPoint = m_local2world[3]; LegoS32 i; for (i = 0; i < 6; i++) { - local150[i] = m_local2world[i % 3]; + boxFacePlanes[i] = m_local2world[i % 3]; if (i > 2) { - local150[i][3] = -local58.Dot(local58, local150[i]); + boxFacePlanes[i][3] = -boundingBoxMin.Dot(boundingBoxMin, boxFacePlanes[i]); } else { - local150[i][3] = -locala8.Dot(locala8, local150[i]); + boxFacePlanes[i][3] = -boundingBoxMax.Dot(boundingBoxMax, boxFacePlanes[i]); } - if (local150[i][3] + local38.Dot(local38, local150[i]) < 0.0f) { - local150[i] *= -1.0f; + if (boxFacePlanes[i][3] + boundingBoxCenter.Dot(boundingBoxCenter, boxFacePlanes[i]) < 0.0f) { + boxFacePlanes[i] *= -1.0f; } } for (i = 0; i < 6; i++) { - float local50 = p_v2.Dot(p_v2, local150[i]); + float intersectionDistance = p_rayDirection.Dot(p_rayDirection, boxFacePlanes[i]); - if (local50 >= 0.01 || local50 < -0.01) { - local50 = -((local150[i][3] + local4c.Dot(local4c, local150[i])) / local50); + if (intersectionDistance >= 0.01 || intersectionDistance < -0.01) { + intersectionDistance = + -((boxFacePlanes[i][3] + rayOrigin.Dot(rayOrigin, boxFacePlanes[i])) / intersectionDistance); - if (local50 >= 0.0f && local50 <= p_f1) { - Mx3DPointFloat local17c(p_v2); - local17c *= local50; - local17c += local4c; + if (intersectionDistance >= 0.0f && intersectionDistance <= p_rayLength) { + Mx3DPointFloat intersectionPoint(p_rayDirection); + intersectionPoint *= intersectionDistance; + intersectionPoint += rayOrigin; LegoS32 j; for (j = 0; j < 6; j++) { if (i != j && i - j != 3 && j - i != 3) { - if (local150[j][3] + local17c.Dot(local17c, local150[j]) < 0.0f) { + if (boxFacePlanes[j][3] + intersectionPoint.Dot(intersectionPoint, boxFacePlanes[j]) < + 0.0f) { break; } } @@ -703,45 +705,46 @@ LegoU32 LegoROI::FUN_100a9410( } } else { - Mx3DPointFloat v1(p_v1); + Mx3DPointFloat v1(p_rayOrigin); v1 -= GetWorldBoundingSphere().Center(); - float local10 = GetWorldBoundingSphere().Radius(); - float local8 = p_v2.Dot(p_v2, p_v2); - float localc = p_v2.Dot(p_v2, v1) * 2.0f; - float local14 = v1.Dot(v1, v1) - (local10 * local10); + float radius = GetWorldBoundingSphere().Radius(); + // Quadratic equation to solve for ray-sphere intersection: at^2 + bt + c = 0 + float a = p_rayDirection.Dot(p_rayDirection, p_rayDirection); + float b = p_rayDirection.Dot(p_rayDirection, v1) * 2.0f; + float c = v1.Dot(v1, v1) - (radius * radius); - if (local8 >= 0.001 || local8 <= -0.001) { - float local1c = -1.0f; - float local18 = (localc * localc) - (local14 * local8 * 4.0f); + if (a >= 0.001 || a <= -0.001) { + float distance = -1.0f; + float discriminant = (b * b) - (c * a * 4.0f); - if (local18 >= -0.001) { - local8 *= 2.0f; - localc = -localc; + if (discriminant >= -0.001) { + a *= 2.0f; + b = -b; - if (local18 > 0.0f) { - local18 = sqrt(local18); - float local184 = (localc + local18) / local8; - float local188 = (localc - local18) / local8; + if (discriminant > 0.0f) { + discriminant = sqrt(discriminant); + float root1 = (b + discriminant) / a; + float root2 = (b - discriminant) / a; - if (local184 > 0.0f && local188 > local184) { - local1c = local184; + if (root1 > 0.0f && root2 > root1) { + distance = root1; } - else if (local188 > 0.0f) { - local1c = local188; + else if (root2 > 0.0f) { + distance = root2; } else { return 0; } } else { - local1c = localc / local8; + distance = b / a; } - if (local1c >= 0.0f && p_f1 >= local1c) { - p_v3 = p_v2; - p_v3 *= local1c; - p_v3 += p_v1; + if (distance >= 0.0f && p_rayLength >= distance) { + p_intersectionPoint = p_rayDirection; + p_intersectionPoint *= distance; + p_intersectionPoint += p_rayOrigin; return 1; } } diff --git a/LEGO1/lego/sources/roi/legoroi.h b/LEGO1/lego/sources/roi/legoroi.h index 7f475680..500a52a7 100644 --- a/LEGO1/lego/sources/roi/legoroi.h +++ b/LEGO1/lego/sources/roi/legoroi.h @@ -50,10 +50,17 @@ class LegoROI : public ViewROI { LegoResult SetLodColor(LegoFloat p_red, LegoFloat p_green, LegoFloat p_blue, LegoFloat p_alpha); LegoResult SetTextureInfo(LegoTextureInfo* p_textureInfo); LegoResult GetTextureInfo(LegoTextureInfo*& p_textureInfo); - LegoResult FUN_100a9330(LegoFloat p_red, LegoFloat p_green, LegoFloat p_blue, LegoFloat p_alpha); + LegoResult SetColor(LegoFloat p_red, LegoFloat p_green, LegoFloat p_blue, LegoFloat p_alpha); LegoResult SetLodColor(const LegoChar* p_name); - LegoResult FUN_100a93b0(const LegoChar* p_name); - LegoU32 FUN_100a9410(Vector3& p_v1, Vector3& p_v2, float p_f1, float p_f2, Vector3& p_v3, LegoBool p_collideBox); + LegoResult SetColorByName(const LegoChar* p_name); + LegoU32 Intersect( + Vector3& p_rayOrigin, + Vector3& p_rayDirection, + float p_rayLength, + float p_unused, + Vector3& p_intersectionPoint, + LegoBool p_collideBox + ); void SetName(const LegoChar* p_name); float IntrinsicImportance() const override; // vtable+0x04 @@ -63,7 +70,7 @@ class LegoROI : public ViewROI { void SetDisplayBB(int p_displayBB); static LegoResult CreateLocalTransform(LegoAnimNodeData* p_data, LegoTime p_time, Matrix4& p_matrix); - static void FUN_100a81b0(const LegoChar* p_error, ...); + static void ReportError(const LegoChar* p_error, ...); static void configureLegoROI(int p_roi); static void SetColorOverride(ColorOverride p_colorOverride); static LegoBool GetRGBAColor(const LegoChar* p_name, float& p_red, float& p_green, float& p_blue, float& p_alpha);