@@ -36,4 +36,119 @@ void COLL_ProjectPointToEdge(SVec3* out, const SVec3* v1, const SVec3* v2, const
3636 out -> y = coords .y ;
3737 out -> z = coords .z ;
3838 TEST_COLL_ProjectPointToEdge (v1 , v2 , point , out );
39+ }
40+
41+ /* Address: 0x8001f928 */
42+ static s32 _COLL_BarycentricTest (TestVertex * t , const CollVertex * v1 , const CollVertex * v2 , const CollVertex * v3 )
43+ {
44+ Vec2 deltaT ;
45+ Vec2 deltaTri [2 ];
46+ const SVec3 * edgeV2 ;
47+ const SVec3 * edgeV3 ;
48+ u32 firstAxis , secondAxis ;
49+
50+ if (t -> normalDominantAxis == AXIS_X )
51+ {
52+ firstAxis = 1 ; // y
53+ secondAxis = 2 ; // z
54+ }
55+ else if (t -> normalDominantAxis == AXIS_Y )
56+ {
57+ firstAxis = 2 ; // z
58+ secondAxis = 0 ; // x
59+ }
60+ else
61+ {
62+ firstAxis = 0 ; // x
63+ secondAxis = 1 ; // y
64+ }
65+
66+ deltaTri [0 ].x = v2 -> pos .v [firstAxis ] - v1 -> pos .v [firstAxis ];
67+ deltaTri [0 ].y = v3 -> pos .v [firstAxis ] - v1 -> pos .v [firstAxis ];
68+ deltaT .x = t -> interpolationPoint .v [firstAxis ] - v1 -> pos .v [firstAxis ];
69+ edgeV2 = & v2 -> pos ;
70+ edgeV3 = & v3 -> pos ;
71+ if (abs (deltaTri [0 ].x ) < abs (deltaTri [0 ].y ))
72+ {
73+ edgeV2 = & v3 -> pos ;
74+ edgeV3 = & v2 -> pos ;
75+ s32 temp = deltaTri [0 ].x ;
76+ deltaTri [0 ].x = deltaTri [0 ].y ;
77+ deltaTri [0 ].y = temp ;
78+ }
79+ deltaTri [1 ].x = edgeV2 -> v [secondAxis ] - v1 -> pos .v [secondAxis ];
80+ deltaTri [1 ].y = edgeV3 -> v [secondAxis ] - v1 -> pos .v [secondAxis ];
81+ deltaT .y = t -> interpolationPoint .v [secondAxis ] - v1 -> pos .v [secondAxis ];
82+
83+ s32 beta = FP (-1 );
84+ s32 gamma = FP (-1 );
85+ if (deltaTri [0 ].x != 0 )
86+ {
87+ s32 dem = ((deltaTri [1 ].y * deltaTri [0 ].x ) - (deltaTri [0 ].y * deltaTri [1 ].x )) >> 6 ;
88+ if (dem != 0 )
89+ {
90+ beta = (((deltaT .y * deltaTri [0 ].x ) - (deltaT .x * deltaTri [1 ].x )) << 6 ) / dem ;
91+ gamma = ((deltaT .x * FP_ONE ) - (beta * deltaTri [0 ].y )) / deltaTri [0 ].x ;
92+ }
93+ }
94+ else
95+ {
96+ if ((deltaTri [0 ].y != 0 ) && (deltaTri [1 ].x != 0 ))
97+ {
98+ beta = FP_DIV (deltaT .y , deltaTri [0 ].y );
99+ gamma = ((deltaT .y * FP_ONE ) - (beta * deltaTri [1 ].y )) / deltaTri [1 ].x ;
100+ }
101+ }
102+
103+ /* Naughty Dog bug: their hand written assembly code
104+ forgets to check beta == -1, creating false collisions */
105+ #ifdef FIX_CTR_BUGS
106+ if ((beta == FP (-1 )) || (gamma == FP (-1 ))) { return BARYCENTRIC_TEST_INVALID ; }
107+ #else
108+ if (gamma == FP (-1 )) { return BARYCENTRIC_TEST_INVALID ; }
109+ #endif
110+
111+ s32 alpha = beta + gamma + FP (-1 );
112+ if (gamma < 0 )
113+ {
114+ if (beta < 0 )
115+ {
116+ t -> pos = v1 -> pos ;
117+ return BARYCENTRIC_TEST_SNAP_V1 ;
118+ }
119+ if (alpha < 0 )
120+ {
121+ COLL_ProjectPointToEdge (& t -> pos , & v1 -> pos , edgeV3 , & t -> interpolationPoint );
122+ return BARYCENTRIC_TEST_EDGE_V1_V3 ;
123+ }
124+ t -> pos = * edgeV3 ;
125+ return BARYCENTRIC_TEST_SNAP_V3 ;
126+ }
127+ if (beta < 0 )
128+ {
129+ if (alpha < 0 )
130+ {
131+ COLL_ProjectPointToEdge (& t -> pos , & v1 -> pos , edgeV2 , & t -> interpolationPoint );
132+ return BARYCENTRIC_TEST_EDGE_V1_V2 ;
133+ }
134+ t -> pos = * edgeV2 ;
135+ return BARYCENTRIC_TEST_SNAP_V2 ;
136+ }
137+ if (alpha > 0 )
138+ {
139+ COLL_ProjectPointToEdge (& t -> pos , edgeV2 , edgeV3 , & t -> interpolationPoint );
140+ return BARYCENTRIC_TEST_EDGE_V2_V3 ;
141+ }
142+ t -> pos = t -> interpolationPoint ;
143+ return BARYCENTRIC_TEST_INSIDE_TRIANGLE ;
144+ }
145+
146+ s32 COLL_BarycentricTest (TestVertex * t , const CollVertex * v1 , const CollVertex * v2 , const CollVertex * v3 )
147+ {
148+ #ifdef TEST_COLL_IMPL
149+ TestVertex input = * t ;
150+ #endif
151+ const s32 ret = _COLL_BarycentricTest (t , v1 , v2 , v3 );
152+ TEST_COLL_BarycentricTest (& input , v1 , v2 , v3 , & t -> pos , ret );
153+ return ret ;
39154}
0 commit comments