11#include <ctr/coll.h>
22#include <ctr/gte.h>
3+ #include <ctr/driver.h>
34#include <ctr/test.h>
45
56/* Address: 0x8001ede4 */
@@ -31,7 +32,7 @@ void COLL_ProjectPointToEdge(SVec3* out, const SVec3* v1, const SVec3* v2, const
3132 gte_loadVec (V1 .v , GTE_VECTOR_MAC );
3233
3334 Vec3 coords ;
34- gte_interpolate (coords .v , GTE_CALC_FLOATING_POINT );
35+ gte_interpolateBase (coords .v , GTE_CALC_FLOATING_POINT );
3536 out -> x = coords .x ;
3637 out -> y = coords .y ;
3738 out -> z = coords .z ;
@@ -244,12 +245,150 @@ static s32 _COLL_BarycentricTest(TestVertex* t, const CollVertex* v1, const Coll
244245 return BARYCENTRIC_TEST_INSIDE_TRIANGLE ;
245246}
246247
247- s32 COLL_BarycentricTest (TestVertex * t , const CollVertex * v1 , const CollVertex * v2 , const CollVertex * v3 )
248+ static s32 COLL_BarycentricTest (TestVertex * t , const CollVertex * v1 , const CollVertex * v2 , const CollVertex * v3 )
248249{
249250#ifdef TEST_COLL_IMPL
250251 TestVertex input = * t ;
251252#endif
252253 const s32 ret = _COLL_BarycentricTest (t , v1 , v2 , v3 );
253254 TEST_COLL_BarycentricTest (& input , v1 , v2 , v3 , & t -> pos , ret );
254255 return ret ;
256+ }
257+
258+ static void _COLL_TestTriangle (CollDCache * cache , const CollVertex * v1 , const CollVertex * v2 , const CollVertex * v3 )
259+ {
260+ cache -> numVerticesTested ++ ;
261+ cache -> collIntersection .triNormal = v1 -> triNormal ;
262+ cache -> collIntersection .planeDist = v1 -> planeDist ;
263+ cache -> collIntersection .normalDominantAxis = v1 -> normalDominantAxis ;
264+
265+ const u16 quadFlags = cache -> currQuadblock -> flags ;
266+ if ((quadFlags & QUADFLAGS_TIGER_TEMPLE_DOOR ) && (cache -> currQuadblock -> terrain & e_ignoreCollisionDoorFlagTerrain )) { return ; }
267+
268+ const u32 triggerScript = quadFlags & QUADFLAGS_TRIGGER_SCRIPT ;
269+ const Matrix m = {
270+ .m [0 ][0 ] = cache -> inputNextPos .x , .m [0 ][1 ] = cache -> inputNextPos .y , .m [0 ][2 ] = cache -> inputNextPos .z ,
271+ .m [1 ][0 ] = cache -> collInput .quadblock .driverPos .x , .m [1 ][1 ] = cache -> collInput .quadblock .driverPos .y , .m [1 ][2 ] = cache -> collInput .quadblock .driverPos .z ,
272+ };
273+ s32 distTriNextPos , distTriCurrPos ;
274+ gte_SetRotMatrix (m .m );
275+ gte_loadSVec (cache -> collIntersection .triNormal .v , GTE_VECTOR_0 );
276+ gte_dotProduct (& distTriNextPos , GTE_ROW_INDEX_0 , GTE_MATRIX_ROT , GTE_VECTOR_0 , GTE_CALC_FLOATING_POINT );
277+ gte_readMac (& distTriCurrPos , GTE_MAC_2 );
278+ distTriNextPos = distTriNextPos + (cache -> collIntersection .planeDist * -2 );
279+ distTriCurrPos = distTriCurrPos + (cache -> collIntersection .planeDist * -2 );
280+ cache -> numVerticesTested ++ ;
281+ if (distTriCurrPos < 0 )
282+ {
283+ if ((!triggerScript ) && (cache -> currQuadblock -> drawOrderLow .doubleSided == 0 )) { return ; }
284+ distTriCurrPos = - distTriCurrPos ;
285+ distTriNextPos = - distTriNextPos ;
286+ cache -> collIntersection .triNormal .x = - cache -> collIntersection .triNormal .x ;
287+ cache -> collIntersection .triNormal .y = - cache -> collIntersection .triNormal .y ;
288+ cache -> collIntersection .triNormal .z = - cache -> collIntersection .triNormal .z ;
289+ cache -> collIntersection .planeDist = - cache -> collIntersection .planeDist ;
290+ }
291+ if ((distTriNextPos >= cache -> inputHitRadius ) || ((!triggerScript ) && (distTriNextPos > distTriCurrPos ))) { return ; }
292+
293+ u32 crossedPlane = false;
294+ const SVec3 deltaPos = {
295+ .x = cache -> inputNextPos .x - cache -> collInput .quadblock .driverPos .x ,
296+ .y = cache -> inputNextPos .y - cache -> collInput .quadblock .driverPos .y ,
297+ .z = cache -> inputNextPos .z - cache -> collInput .quadblock .driverPos .z
298+ };
299+ if (distTriNextPos < 0 )
300+ {
301+ const s32 interpolationFactor = FP_DIV (- distTriNextPos , distTriCurrPos - distTriNextPos );
302+ gte_loadSVec (deltaPos .v , GTE_VECTOR_IR );
303+ gte_loadIR (interpolationFactor , GTE_IR_0 );
304+ crossedPlane = true;
305+ }
306+ else
307+ {
308+ gte_loadSVec (cache -> collIntersection .triNormal .v , GTE_VECTOR_IR );
309+ gte_loadIR (distTriNextPos , GTE_IR_0 );
310+ }
311+ Vec3 interpolation ;
312+ gte_interpolate (interpolation .v , GTE_CALC_FLOATING_POINT );
313+ cache -> collIntersection .interpolationPoint .x = cache -> inputNextPos .x - interpolation .x ;
314+ cache -> collIntersection .interpolationPoint .y = cache -> inputNextPos .y - interpolation .y ;
315+ cache -> collIntersection .interpolationPoint .z = cache -> inputNextPos .z - interpolation .z ;
316+ cache -> currTestVertices [0 ] = v1 ;
317+ cache -> currTestVertices [1 ] = v2 ;
318+ cache -> currTestVertices [2 ] = v3 ;
319+ const s32 barycentricTest = COLL_BarycentricTest (& cache -> collIntersection , v1 , v2 , v3 );
320+ if (barycentricTest == BARYCENTRIC_TEST_INVALID ) { return ; }
321+
322+ if (crossedPlane )
323+ {
324+ cache -> deltaInterpolationIntersection .x = cache -> collIntersection .interpolationPoint .x - cache -> collIntersection .pos .x ;
325+ cache -> deltaInterpolationIntersection .y = cache -> collIntersection .interpolationPoint .y - cache -> collIntersection .pos .y ;
326+ cache -> deltaInterpolationIntersection .z = cache -> collIntersection .interpolationPoint .z - cache -> collIntersection .pos .z ;
327+ }
328+ else
329+ {
330+ cache -> deltaInterpolationIntersection .x = cache -> inputNextPos .x - cache -> collIntersection .pos .x ;
331+ cache -> deltaInterpolationIntersection .y = cache -> inputNextPos .y - cache -> collIntersection .pos .y ;
332+ cache -> deltaInterpolationIntersection .z = cache -> inputNextPos .z - cache -> collIntersection .pos .z ;
333+ }
334+ s32 distSquaredInterpolationIntersection ;
335+ gte_loadRowMatrix (cache -> deltaInterpolationIntersection .v , GTE_ROW_INDEX_0 , GTE_MATRIX_ROT );
336+ gte_loadSVec (cache -> deltaInterpolationIntersection .v , GTE_VECTOR_0 );
337+ gte_dotProduct (& distSquaredInterpolationIntersection , GTE_ROW_INDEX_0 , GTE_MATRIX_ROT , GTE_VECTOR_0 , GTE_CALC_INT );
338+ if (distSquaredInterpolationIntersection > cache -> inputHitRadiusSquared ) { return ; }
339+
340+ if (triggerScript )
341+ {
342+ const u32 skip = (distTriNextPos >= 0 ) && (distTriNextPos >= cache -> inputHitRadius ) && (distTriCurrPos >= cache -> inputHitRadius );
343+ if (!skip ) { cache -> stepFlags |= cache -> currQuadblock -> terrain ; return ; }
344+ }
345+
346+ s32 deltaDist = distTriCurrPos - distTriNextPos ;
347+ if (deltaDist != 0 ) { deltaDist = FP_ONE - FP_DIV (cache -> inputHitRadius - distTriNextPos , deltaDist ); }
348+ if (deltaDist >= cache -> speedScale ) { return ; }
349+
350+ if (quadFlags & QUADFLAGS_OUT_OF_BOUNDS )
351+ {
352+ if ((quadFlags & QUADFLAGS_MASK_GRAB ) == 0 ) { return ; }
353+ cache -> stepFlags |= STEPFLAGS_OUT_OF_BOUNDS ;
354+ return ;
355+ }
356+
357+ cache -> speedScale = deltaDist ;
358+ cache -> collidedVertices [0 ] = cache -> currTestVertices [0 ]-> levVertex ;
359+ cache -> collidedVertices [1 ] = cache -> currTestVertices [1 ]-> levVertex ;
360+ cache -> collidedVertices [2 ] = cache -> currTestVertices [2 ]-> levVertex ;
361+ cache -> coll .pos = cache -> collIntersection .pos ;
362+ cache -> coll .normalDominantAxis = cache -> collIntersection .normalDominantAxis ;
363+ cache -> coll .triNormal = cache -> collIntersection .triNormal ;
364+ cache -> coll .planeDist = cache -> collIntersection .planeDist ;
365+ cache -> coll .interpolationPoint = cache -> collIntersection .interpolationPoint ;
366+ cache -> collidedQuadblock = cache -> currQuadblock ;
367+ cache -> collidedTriangleIndex = cache -> currTriangleIndex ;
368+ cache -> barycentricTest = barycentricTest ;
369+ if (deltaDist > 0 )
370+ {
371+ Vec3 nextPos ;
372+ gte_loadSVec (deltaPos .v , GTE_VECTOR_IR );
373+ gte_loadIR (deltaDist , GTE_IR_0 );
374+ gte_interpolate (nextPos .v , GTE_CALC_FLOATING_POINT );
375+ cache -> collInput .quadblock .driverNextPos .x = cache -> collInput .quadblock .driverPos .x + nextPos .x ;
376+ cache -> collInput .quadblock .driverNextPos .y = cache -> collInput .quadblock .driverPos .y + nextPos .y ;
377+ cache -> collInput .quadblock .driverNextPos .z = cache -> collInput .quadblock .driverPos .z + nextPos .z ;
378+ }
379+ else { cache -> collInput .quadblock .driverNextPos = cache -> collInput .quadblock .driverPos ; }
380+ cache -> numTrianglesCollided ++ ;
381+ }
382+
383+ void COLL_TestTriangle (CollDCache * cache , const CollVertex * v1 , const CollVertex * v2 , const CollVertex * v3 )
384+ {
385+ #ifdef TEST_COLL_IMPL
386+ * (CollDCache * )(BACKUP_ADDR ) = * cache ;
387+ #endif
388+ _COLL_TestTriangle (cache , v1 , v2 , v3 );
389+ TEST_COLL_TestTriangle ((CollDCache * )(BACKUP_ADDR ), v1 , v2 , v3 , cache );
390+ /* This is a hand written assembly function that breaks the ABI,
391+ and some callers expect the argument registers to be untouched */
392+ __asm__ volatile ("move $a0, %0" : : "r" ((u32 )cache ));
393+ __asm__ volatile ("move $t9, %0" : : "r" ((u32 )cache -> currQuadblock ));
255394}
0 commit comments