MCPcopy Create free account
hub / github.com/TombEngine/TombEngine / GetNearestLedgeAngle

Function GetNearestLedgeAngle

TombEngine/Game/collision/collide_room.cpp:752–1057  ·  view source on GitHub ↗

Determines vertical surfaces and gets nearest ledge angle. Allows to eventually use unconstrained vaults and shimmying.

Source from the content-addressed store, hash-verified

750// Determines vertical surfaces and gets nearest ledge angle.
751// Allows to eventually use unconstrained vaults and shimmying.
752short GetNearestLedgeAngle(ItemInfo* item, CollisionInfo* coll, float& distance)
753{
754 // Calculation ledge angle for non-Lara objects is unnecessary.
755 if (!item->IsLara())
756 return 0;
757
758 // Get item bounds and current rotation.
759 auto bounds = GameBoundingBox(item);
760 float cosForwardAngle = phd_cos(coll->Setup.ForwardAngle);
761 float sinForwardAngle = phd_sin(coll->Setup.ForwardAngle);
762
763 // Origin test position should be slightly in front of origin, because otherwise misfire may occur near block corners for split angles.
764 auto frontalOffset = coll->Setup.Radius * 0.3f;
765 auto x = item->Pose.Position.x + frontalOffset * sinForwardAngle;
766 auto z = item->Pose.Position.z + frontalOffset * cosForwardAngle;
767
768 // Determine two Y points to test (lower and higher).
769 // 1/10 headroom crop is needed to avoid possible issues with tight diagonal headrooms.
770 int headroom = bounds.GetHeight() / 20.0f;
771 int yPoints[2] = { item->Pose.Position.y + bounds.Y1 + headroom,
772 item->Pose.Position.y + bounds.Y2 - headroom };
773
774 // Prepare test data.
775 float finalDistance[2] = { FLT_MAX, FLT_MAX };
776 short finalResult[2] = { 0 };
777 bool hitBridge = false;
778
779 // Do a two-pass surface test for all possible planes in a block.
780 // Two-pass test is needed to resolve different scissor cases with diagonal geometry.
781 for (int h = 0; h < 2; h++)
782 {
783 // Use either bottom or top Y point to test.
784 auto y = yPoints[h];
785
786 // Prepare test data.
787 Ray originRay;
788 Plane closestPlane[3] = { };
789 float closestDistance[3] = { FLT_MAX, FLT_MAX, FLT_MAX };
790 short result[3] = { };
791
792 // If bridge was hit on the first pass, stop checking.
793 if (h == 1 && hitBridge)
794 break;
795
796 for (int p = 0; p < 3; p++)
797 {
798 // Prepare test data.
799 float dist = 0.0f;
800
801 // Determine horizontal probe coordinates.
802 auto eX = x;
803 auto eZ = z;
804
805 // Determine if probe must be shifted (if left or right probe).
806 if (p > 0)
807 {
808 auto s2 = phd_sin(coll->Setup.ForwardAngle + (p == 1 ? ANGLE(90.0f) : -ANGLE(90.0f)));
809 auto c2 = phd_cos(coll->Setup.ForwardAngle + (p == 1 ? ANGLE(90.0f) : -ANGLE(90.0f)));

Callers 2

SnapItemToLedgeFunction · 0.85
GetCollisionInfoFunction · 0.85

Calls 15

phd_cosFunction · 0.85
phd_sinFunction · 0.85
ANGLEFunction · 0.85
floorFunction · 0.85
GetRoomVectorFunction · 0.85
GetPointCollisionFunction · 0.85
GetSurfaceHeightFunction · 0.85
TO_RADFunction · 0.85
RayClass · 0.85
FROM_RADFunction · 0.85
findFunction · 0.85
distanceFunction · 0.85

Tested by

no test coverage detected