diff options
| author | krimtonz <33664508+krimtonz@users.noreply.github.com> | 2020-08-17 14:42:08 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-08-17 15:42:08 -0400 |
| commit | f11a74d41d1e31c5bf46cee71f63bd1e1fa34392 (patch) | |
| tree | 427bf0c4e57f073d401e147088d9ee6b5d5274b0 /src/code/sys_math3d.c | |
| parent | 2826421c9850aa1ece6eb90e078628a36b33eb64 (diff) | |
Math3D and olib updates (#315)
* wip
* Olib updates
* wip
* wip
* rename most Math3D functions, few matches, documentation
* wip
* document most of math3d
* pr updates
* pr updates
* add missing comment block finalizer
Diffstat (limited to 'src/code/sys_math3d.c')
| -rw-r--r--[-rwxr-xr-x] | src/code/sys_math3d.c | 2310 |
1 files changed, 1396 insertions, 914 deletions
diff --git a/src/code/sys_math3d.c b/src/code/sys_math3d.c index 4e7114efa..59e8384c7 100755..100644 --- a/src/code/sys_math3d.c +++ b/src/code/sys_math3d.c @@ -2,184 +2,352 @@ #include <global.h> #include <vt.h> -s32 func_800CA8E8(Vec3f*, Vec3f*, Vec3f*, Vec3f*, Vec3f*, Vec3f*); -s32 Math3D_TriLineIntersect(Vec3f* arg0, Vec3f* arg1, Vec3f* arg2, f32 arg3, f32 arg4, f32 arg5, f32 arg6, Vec3f* arg7, - Vec3f* arg8, Vec3f* arg9, s32 argA); -s32 func_800CAD08(f32 arg0, f32 arg1, f32 arg2, f32 arg3, f32 arg4, f32 arg5, f32 arg6, f32 arg7, Linef* arg8); -s32 func_800CB1F8(f32 arg0, f32 arg1, f32 arg2, f32 arg3, f32 arg4, f32 arg5, f32 arg6, f32 arg7, f32 arg8); -s32 func_800CB338(Vec3f* v0, Vec3f* v1, Vec3f* v2, Vec3f* center, f32 radius); - -s32 func_800CA7D0(f32 arg0, f32 arg1, f32 arg2, f32 arg3, f32 arg4, f32 arg5, f32 arg6, f32 arg7, Vec3f* arg8, - Vec3f* arg9, Vec3f* argA) { - static Linef D_8016A5A0; - static Linef D_8016A5B8; +s32 Math3D_LineSegMakePerpLineSeg(Vec3f* lineAPointA, Vec3f* lineAPointB, Vec3f* lineBPointA, Vec3f* lineBPointB, + Vec3f* lineAIntersect, Vec3f* lineBIntersect); +s32 Math3D_TriLineIntersect(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 ny, f32 nz, f32 originDist, Vec3f* linePointA, + Vec3f* linePointB, Vec3f* intersect, s32 fromFront); +s32 Math3D_PlaneVsPlaneNewLine(f32 planeAA, f32 planeAB, f32 planeAC, f32 planeADist, f32 planeBA, f32 planeBB, + f32 planeBC, f32 planeBDist, InfiniteLine* intersect); +s32 Math3D_CirSquareVsTriSquare(f32 x0, f32 y0, f32 x1, f32 y1, f32 x2, f32 y2, f32 centerX, f32 centerY, f32 radius); +s32 Math3D_SphCubeVsTriCube(Vec3f* v0, Vec3f* v1, Vec3f* v2, Vec3f* center, f32 radius); + +/** + * Creates an infinite line along the intersection of the plane defined from `planeAA`x + `planeAB`y + `planeAB`z + + * `planeADist` = 0 and `planeBA`x + `planeBB`y + `planeBC`z + `planeBDist` = 0, and finds the closest point on that + * intersection to the line segment `linePointA and linePointB`, outputs the intersection to `closestPoint` + */ +s32 Math3D_PlaneVsLineSegClosestPoint(f32 planeAA, f32 planeAB, f32 planeAC, f32 planeADist, f32 planeBA, f32 planeBB, + f32 planeBC, f32 planeBDist, Vec3f* linePointA, Vec3f* linePointB, + Vec3f* closestPoint) { + static InfiniteLine planeIntersectLine; + static Linef planeIntersectSeg; - Vec3f sp34; + Vec3f sp34; // unused - if (func_800CAD08(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, &D_8016A5A0) == 0) { - return 0; + if (!Math3D_PlaneVsPlaneNewLine(planeAA, planeAB, planeAC, planeADist, planeBA, planeBB, planeBC, planeBDist, + &planeIntersectLine)) { + // The planes are parallel + return false; } - Math_Vec3f_Copy(&D_8016A5B8.a, &D_8016A5A0.a); - D_8016A5B8.b.x = (D_8016A5A0.b.x * 100.0f) + D_8016A5A0.a.x; - D_8016A5B8.b.y = (D_8016A5A0.b.y * 100.0f) + D_8016A5A0.a.y; - D_8016A5B8.b.z = (D_8016A5A0.b.z * 100.0f) + D_8016A5A0.a.z; + // create a line segment on the plane. + Math_Vec3f_Copy(&planeIntersectSeg.a, &planeIntersectLine.point); + planeIntersectSeg.b.x = (planeIntersectLine.dir.x * 100.0f) + planeIntersectLine.point.x; + planeIntersectSeg.b.y = (planeIntersectLine.dir.y * 100.0f) + planeIntersectLine.point.y; + planeIntersectSeg.b.z = (planeIntersectLine.dir.z * 100.0f) + planeIntersectLine.point.z; - if (!func_800CA8E8(&D_8016A5B8.a, &D_8016A5B8.b, arg8, arg9, argA, &sp34)) { - return 0; + // closestPoint is a point on planeIntersect, sp34 is a point on linePointA, linePointB + if (!Math3D_LineSegMakePerpLineSeg(&planeIntersectSeg.a, &planeIntersectSeg.b, linePointA, linePointB, closestPoint, + &sp34)) { + return false; } - return 1; + return true; } -#pragma GLOBAL_ASM("asm/non_matchings/code/sys_math3d/func_800CA8E8.s") +/** + * Creates a line segment which is perpendicular to the line segments `lineAPointA`->`lineAPointB` and + * `lineBPointA`->`lineBPointB` + * +*/ +#ifdef NON_MATCHING +/** + * NON_MATCHING: + * Lots of regalloc, but is functionally equivilent, some reordering. + */ +s32 Math3D_LineSegMakePerpLineSeg(Vec3f* lineAPointA, Vec3f* lineAPointB, Vec3f* lineBPointA, Vec3f* lineBPointB, + Vec3f* lineAIntersect, Vec3f* lineBIntersect) { + f32 sp5C; + f32 sp50; + f32 sp4C; + f32 sp30; + f32 temp_f0_4; + f32 temp_f18; + Vec3f lineADiff; + Vec3f lineBDiff; + Vec3f lineABPointADiff; + f32 t; + f32 t2; -void Math3D_LineVsPos(Linef* line, Vec3f* pos, Vec3f* ret) { - f32 temp_ret; - f32 temp_f0; + lineADiff.x = lineAPointB->x - lineAPointA->x; + lineADiff.y = lineAPointB->y - lineAPointA->y; + lineADiff.z = lineAPointB->z - lineAPointA->z; + lineBDiff.x = lineBPointB->x - lineBPointA->x; + lineBDiff.y = lineBPointB->y - lineBPointA->y; + lineBDiff.z = lineBPointB->z - lineBPointA->z; + + if (IS_ZERO(SQ(lineBDiff.x) + SQ(lineBDiff.y) + SQ(lineBDiff.z))) { + return false; + } + + sp5C = ((lineADiff.x * lineBDiff.x) + (lineADiff.y * lineBDiff.y) + (lineADiff.z * lineBDiff.z)) * + (1.0f / (SQ(lineBDiff.x) + SQ(lineBDiff.y) + SQ(lineBDiff.z))); + + lineABPointADiff.x = lineAPointA->x - lineBPointA->x; + lineABPointADiff.y = lineAPointA->y - lineBPointA->y; + lineABPointADiff.z = lineAPointA->z - lineBPointA->z; + + // most reordering is here. + temp_f18 = + ((lineABPointADiff.x * lineBDiff.x) + (lineABPointADiff.y * lineBDiff.y) + (lineABPointADiff.z * lineBDiff.z)) * + (1.0f / (SQ(lineBDiff.x) + SQ(lineBDiff.y) + SQ(lineBDiff.z))); + + sp4C = lineADiff.x - (lineBDiff.x * sp5C); + sp50 = lineADiff.y - (lineBDiff.y * sp5C); + sp30 = lineADiff.z - (lineBDiff.z * sp5C); + if (IS_ZERO(SQ(sp4C) + SQ(sp50) + SQ(sp30))) { + return false; + } - temp_ret = func_800CB600(&line->b); - if (fabsf(temp_ret) < 0.008f) { + t = SQ(sp4C) + SQ(sp50) + SQ(sp30); + temp_f0_4 = -((sp4C * (lineABPointADiff.x - (lineBDiff.x * temp_f18))) + + (sp50 * (lineABPointADiff.y - (lineBDiff.y * temp_f18))) + + (sp30 * (lineABPointADiff.z - (lineBDiff.z * temp_f18)))) / + t; + lineAIntersect->x = (lineADiff.x * temp_f0_4) + lineAPointA->x; + lineAIntersect->y = (lineADiff.y * temp_f0_4) + lineAPointA->y; + lineAIntersect->z = (lineADiff.z * temp_f0_4) + lineAPointA->z; + + lineBIntersect->x = (lineBDiff.x * ((sp5C * temp_f0_4) + temp_f18)) + lineBPointA->x; + lineBIntersect->y = (lineBDiff.y * ((sp5C * temp_f0_4) + temp_f18)) + lineBPointA->y; + lineBIntersect->z = (lineBDiff.z * ((sp5C * temp_f0_4) + temp_f18)) + lineBPointA->z; + return true; +} +#else +#pragma GLOBAL_ASM("asm/non_matchings/code/sys_math3d/Math3D_LineSegMakePerpLineSeg.s") +#endif + +/** + * Determines the closest point on the line `line` to `pos`, by forming a line perpendicular from + * `point` to `line` closest point is placed in `closestPoint` + */ +void Math3D_LineClosestToPoint(Linef* line, Vec3f* pos, Vec3f* closestPoint) { + f32 dirVectorSize; + f32 t; + + dirVectorSize = Math3D_Vec3fMagnitudeSq(&line->b); + if (IS_ZERO(dirVectorSize)) { osSyncPrintf(VT_COL(YELLOW, BLACK)); // Math3D_lineVsPosSuisenCross(): No straight line length osSyncPrintf("Math3D_lineVsPosSuisenCross():直線の長さがありません\n"); // Returns cross = pos. osSyncPrintf("cross = pos を返します。\n"); osSyncPrintf(VT_RST); - Math_Vec3f_Copy(ret, pos); + Math_Vec3f_Copy(closestPoint, pos); } - temp_f0 = - (((pos->x - line->a.x) * line->b.x) + ((pos->y - line->a.y) * line->b.y) + ((pos->z - line->a.z) * line->b.z)) / - temp_ret; - ret->x = (line->b.x * temp_f0) + line->a.x; - ret->y = (line->b.y * temp_f0) + line->a.y; - ret->z = (line->b.z * temp_f0) + line->a.z; + + t = (((pos->x - line->a.x) * line->b.x) + ((pos->y - line->a.y) * line->b.y) + ((pos->z - line->a.z) * line->b.z)) / + dirVectorSize; + closestPoint->x = (line->b.x * t) + line->a.x; + closestPoint->y = (line->b.y * t) + line->a.y; + closestPoint->z = (line->b.z * t) + line->a.z; } -void func_800CACAC(f32 arg0, f32 arg1, f32 arg2, f32 arg3, f32 arg4, f32 arg5, f32 arg6, f32* arg7, f32* arg8) { - *arg7 = ((arg1 * arg6) - (arg3 * arg5)) / arg4; - *arg8 = ((arg2 * arg5) - (arg0 * arg6)) / arg4; +void Math3D_FindPointOnPlaneIntersect(f32 planeAAxis1Norm, f32 planeAAxis2Norm, f32 planeBAxis1Norm, + f32 planeBAxis2Norm, f32 axis3Direction, f32 planeADist, f32 planeBDist, + f32* axis1Point, f32* axis2Point) { + *axis1Point = ((planeAAxis2Norm * planeBDist) - (planeBAxis2Norm * planeADist)) / axis3Direction; + *axis2Point = ((planeBAxis1Norm * planeADist) - (planeAAxis1Norm * planeBDist)) / axis3Direction; } -s32 func_800CAD08(f32 arg0, f32 arg1, f32 arg2, f32 arg3, f32 arg4, f32 arg5, f32 arg6, f32 arg7, Linef* arg8) { +/** + * Creates a line between the intersections of two planes defined from `planeAA`x + `planeAB`y + `planeAC`z + + * `planeADist` = 0 and `planeBA`x + `planeBB`y + `planeBC`z + `planeBDist` = 0, and outputs the line to `intersect`. + * Returns false if the planes are parallel. + */ +s32 Math3D_PlaneVsPlaneNewLine(f32 planeAA, f32 planeAB, f32 planeAC, f32 planeADist, f32 planeBA, f32 planeBB, + f32 planeBC, f32 planeBDist, InfiniteLine* intersect) { char pad[4]; - Vec3f sp60; - Vec3f sp54; - f32 ax; - f32 ay; - f32 az; - - VEC_SET(sp60, arg0, arg1, arg2); - VEC_SET(sp54, arg4, arg5, arg6); - - Math3D_Vec3f_Cross(&sp60, &sp54, &arg8->b); - - if (fabsf(arg8->b.x) < 0.008f && fabsf(arg8->b.y) < 0.008f && fabsf(arg8->b.z) < 0.008f) { - return 0; - } - - ax = fabsf(arg8->b.x); - ay = fabsf(arg8->b.y); - az = fabsf(arg8->b.z); - - if ((ay <= ax) && (az <= ax)) { - func_800CACAC(arg1, arg2, arg5, arg6, arg8->b.x, arg3, arg7, &arg8->a.y, &arg8->a.z); - arg8->a.x = 0.0f; - } else if ((ax <= ay) && (az <= ay)) { - func_800CACAC(arg2, arg0, arg6, arg4, arg8->b.y, arg3, arg7, &arg8->a.z, &arg8->a.x); - arg8->a.y = 0.0f; + Vec3f planeANormal; + Vec3f planeBNormal; + f32 dirX; + f32 dirY; + f32 dirZ; + + VEC_SET(planeANormal, planeAA, planeAB, planeAC); + VEC_SET(planeBNormal, planeBA, planeBB, planeBC); + + Math3D_Vec3f_Cross(&planeANormal, &planeBNormal, &intersect->dir); + + if (IS_ZERO(intersect->dir.x) && IS_ZERO(intersect->dir.y) && IS_ZERO(intersect->dir.z)) { + // planes are parallel + return false; + } + + dirX = fabsf(intersect->dir.x); + dirY = fabsf(intersect->dir.y); + dirZ = fabsf(intersect->dir.z); + + if ((dirX >= dirY) && (dirX >= dirZ)) { + Math3D_FindPointOnPlaneIntersect(planeAB, planeAC, planeBB, planeBC, intersect->dir.x, planeADist, planeBDist, + &intersect->point.y, &intersect->point.z); + intersect->point.x = 0.0f; + } else if ((dirY >= dirX) && (dirY >= dirZ)) { + Math3D_FindPointOnPlaneIntersect(planeAC, planeAA, planeBC, planeBA, intersect->dir.y, planeADist, planeBDist, + &intersect->point.z, &intersect->point.x); + intersect->point.y = 0.0f; } else { - func_800CACAC(arg0, arg1, arg4, arg5, arg8->b.z, arg3, arg7, &arg8->a.x, &arg8->a.y); - arg8->a.z = 0.0f; + Math3D_FindPointOnPlaneIntersect(planeAA, planeAB, planeBA, planeBB, intersect->dir.z, planeADist, planeBDist, + &intersect->point.x, &intersect->point.y); + intersect->point.z = 0.0f; } - return 1; + return true; } -s32 func_800CAEE8(f32 arg0, f32 arg1, f32 arg2, f32 arg3, f32 arg4, f32 arg5, f32 arg6, f32 arg7, Vec3f* arg8, - Vec3f* arg9) { - static Linef D_8016A5D0; +/** + * Gets the closest point on the line formed from the intersection of of the planes defined from + * `planeAA`x + `planeAB`y + `planeAC`z + `planeADist` = 0 and + * `planeBA`x + `planeBB`y + `planeBC`z + `planeBDist` = 0 + * the point on the intersection line closest to `point` is placed in `closestPoint` + * returns false if the planes are parallel. + */ +s32 Math3D_PlaneVsPlaneVsLineClosestPoint(f32 planeAA, f32 planeAB, f32 planeAC, f32 planeADist, f32 planeBA, + f32 planeBB, f32 planeBC, f32 planeBDist, Vec3f* point, Vec3f* closestPoint) { + static Linef planeIntersect; - if (func_800CAD08(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, &D_8016A5D0) == 0) { - return 0; + if (!Math3D_PlaneVsPlaneNewLine(planeAA, planeAB, planeAC, planeADist, planeBA, planeBB, planeBC, planeBDist, + &planeIntersect)) { + return false; } - Math3D_LineVsPos(&D_8016A5D0, arg8, arg9); - return 1; + Math3D_LineClosestToPoint(&planeIntersect, point, closestPoint); + return true; } -void func_800CAF5C(Vec3f* arg0, Vec3f* arg1, f32 arg2, Vec3f* arg3) { - arg3->x = (arg1->x * arg2) + arg0->x; - arg3->y = (arg1->y * arg2) + arg0->y; - arg3->z = (arg1->z * arg2) + arg0->z; +/** + * Finds a point on the line from starting point `v0`, and directional vector `dir` + * which is `dist` length from the starting point. Result is placed in `ret` + */ +void Math3D_PointOnInfinteLine(Vec3f* v0, Vec3f* dir, f32 dist, Vec3f* ret) { + ret->x = (dir->x * dist) + v0->x; + ret->y = (dir->y * dist) + v0->y; + ret->z = (dir->z * dist) + v0->z; } -void func_800CAFA0(Vec3f* v0, Vec3f* v1, f32 arg2, Vec3f* ret) { +/** + * Splits the line segment from end points `v0` and `v1`, and splits that segment + * by `ratio` of `v0`:`v1`, places the resulting point on the line in `ret` + */ +void Math3D_LineSplitRatio(Vec3f* v0, Vec3f* v1, f32 ratio, Vec3f* ret) { Vec3f diff; Math_Vec3f_Diff(v1, v0, &diff); - func_800CAF5C(v0, &diff, arg2, ret); + Math3D_PointOnInfinteLine(v0, &diff, ratio, ret); } -f32 Math3D_DotProduct(Vec3f* vec1, Vec3f* vec2) { +/** + * Calculates the cosine between vectors `a` and `b` + */ +f32 Math3D_Cos(Vec3f* a, Vec3f* b) { f32 ret; - func_800CB010(vec1, vec2, &ret); + Math3D_CosOut(a, b, &ret); return ret; } -s32 func_800CB010(Vec3f* vec1, Vec3f* vec2, f32* dst) { +/** + * Calculates the cosine between bectors `a` and `b` and places the result in `ret` + * returns true if the cosine cannot be calculated because the product of the magnitudes is zero + */ +s32 Math3D_CosOut(Vec3f* a, Vec3f* b, f32* dst) { f32 magProduct; - magProduct = Math3D_Vec3fMagnitude(vec1) * Math3D_Vec3fMagnitude(vec2); - if (fabsf(magProduct) < 0.008f) { + magProduct = Math3D_Vec3fMagnitude(a) * Math3D_Vec3fMagnitude(b); + if (IS_ZERO(magProduct)) { *dst = 0.0f; - return 1; + return true; } - *dst = ((vec1->x * vec2->x) + (vec1->y * vec2->y) + (vec1->z * vec2->z)) / magProduct; - return 0; + *dst = ((a->x * b->x) + (a->y * b->y) + (a->z * b->z)) / magProduct; + return false; } -void func_800CB0C0(Vec3f* vec1, Vec3f* vec2, Vec3f* ret) { +/** + * Reflects vector `vec` across the normal vector `normal`, reflection vector is placed in + * `reflVec` + */ +void Math3D_Vec3fReflect(Vec3f* vec, Vec3f* normal, Vec3f* reflVec) { - f32 temp_f12; - Vec3f negVec1; - f32 temp_f14; - f32 temp_f2; - f32 dotProduct; + f32 normScaleY; + Vec3f negVec; + f32 normScaleZ; + f32 normScaleX; + f32 vecDotNorm; - negVec1.x = vec1->x * -1.0f; - negVec1.y = vec1->y * -1.0f; - negVec1.z = vec1->z * -1.0f; + negVec.x = vec->x * -1.0f; + negVec.y = vec->y * -1.0f; + negVec.z = vec->z * -1.0f; - dotProduct = Math3D_DotProduct(&negVec1, vec2); + vecDotNorm = Math3D_Cos(&negVec, normal); - temp_f2 = vec2->x * dotProduct; - temp_f12 = vec2->y * dotProduct; - temp_f14 = vec2->z * dotProduct; + normScaleX = normal->x * vecDotNorm; + normScaleY = normal->y * vecDotNorm; + normScaleZ = normal->z * vecDotNorm; - ret->x = ((temp_f2 + vec1->x) + (temp_f2 + vec1->x)) + negVec1.x; - ret->y = ((temp_f12 + vec1->y) + (temp_f12 + vec1->y)) + negVec1.y; - ret->z = ((temp_f14 + vec1->z) + (temp_f14 + vec1->z)) + negVec1.z; + reflVec->x = ((normScaleX + vec->x) + (normScaleX + vec->x)) + negVec.x; + reflVec->y = ((normScaleY + vec->y) + (normScaleY + vec->y)) + negVec.y; + reflVec->z = ((normScaleZ + vec->z) + (normScaleZ + vec->z)) + negVec.z; } -s32 func_800CB198(f32 arg0, f32 arg1, f32 arg2, f32 arg3, f32 arg4, f32 arg5) { - if (arg0 <= arg4 && arg4 <= arg1 && arg2 <= arg5 && arg5 <= arg3) { - return 1; +/** + * Checks if the point (`x`,`y`) is contained within the square formed from (`upperLeftX`,`upperLeftY`) to + * (`lowerRightX`,`lowerRightY`) + */ +s32 Math3D_PointInSquare2D(f32 upperLeftX, f32 lowerRightX, f32 upperLeftY, f32 lowerRightY, f32 x, f32 y) { + if (x >= upperLeftX && x <= lowerRightX && y >= upperLeftY && y <= lowerRightY) { + return true; } - return 0; + return false; } -/*************************************************************************/ -/* The next 2 functions have some interesting control flow */ -/*************************************************************************/ -#pragma GLOBAL_ASM("asm/non_matchings/code/sys_math3d/func_800CB1F8.s") +/** + * Checks if the square formed around the circle with center (`centerX`,`centerY`) with radius `radius` + * touches any portion of the square formed around the triangle with vertices (`x0`,`y0`), (`x1`,`y1`), + * and (`x2`,`y2`) + */ +s32 Math3D_CirSquareVsTriSquare(f32 x0, f32 y0, f32 x1, f32 y1, f32 x2, f32 y2, f32 centerX, f32 centerY, f32 radius) { + f32 minX; + f32 maxX; + f32 minY; + f32 maxY; -#ifdef NON_MATCHING -/* - * Math3D_TriInSphere - * Checks if a tringle defined by `v0`, `v1`, and `v2` lies within a spehere - * centered at `center` and has radius `radius`. Returns 1 if any vertex of the - * triangle lies within the sphere, or 0 otherwise. + minX = maxX = x0; + minY = maxY = y0; + + if (x1 < minX) { + minX = x1; + } else if (maxX < x1) { + maxX = x1; + } + + if (y1 < minY) { + minY = y1; + } else if (maxY < y1) { + maxY = y1; + } + + if (x2 < minX) { + minX = x2; + } else if (maxX < x2) { + maxX = x2; + } + + if (y2 < minY) { + minY = y2; + } else if (maxY < y2) { + maxY = y2; + } + + if ((minX - radius) <= centerX && (maxX + radius) >= centerX && (minY - radius) <= centerY && + (maxY + radius) >= centerY) { + return true; + } + return false; +} + +/** + * Checks if the cube formed around the triangle formed from `v0`, `v1`, and `v2` + * has any portion touching the cube formed around the sphere with center `center` + * and radius of `radius` */ -s32 func_800CB338(Vec3f* v0, Vec3f* v1, Vec3f* v2, Vec3f* center, f32 radius) { +s32 Math3D_SphCubeVsTriCube(Vec3f* v0, Vec3f* v1, Vec3f* v2, Vec3f* center, f32 radius) { f32 minX; f32 maxX; f32 minY; @@ -187,27 +355,25 @@ s32 func_800CB338(Vec3f* v0, Vec3f* v1, Vec3f* v2, Vec3f* center, f32 radius) { f32 minZ; f32 maxZ; - if (v1->x < v0->x) { + minX = maxX = v0->x; + minY = maxY = v0->y; + minZ = maxZ = v0->z; + + if (v1->x < minX) { minX = v1->x; - maxX = v0->x; - } else if (v0->x < v1->x) { - minX = v0->x; + } else if (maxX < v1->x) { maxX = v1->x; } - if (v1->y < v0->y) { + if (v1->y < minY) { minY = v1->y; - maxY = v0->y; - } else if (v0->y < v1->y) { - minY = v0->y; + } else if (maxY < v1->y) { maxY = v1->y; } - if (v1->z < v0->z) { + if (v1->z < minZ) { minZ = v1->z; - maxZ = v0->z; - } else if (v0->z < v1->z) { - minZ = v0->z; + } else if (maxZ < v1->z) { maxZ = v1->z; } @@ -229,51 +395,67 @@ s32 func_800CB338(Vec3f* v0, Vec3f* v1, Vec3f* v2, Vec3f* center, f32 radius) { maxZ = v2->z; } - if (((minX - radius) <= center->x) && (center->x <= (maxX + radius)) && ((minY - radius) <= center->y) && - (center->y <= (maxY + radius)) && ((minZ - radius) <= center->z) && (center->z <= (maxZ + radius))) { - return 1; + if ((center->x >= (minX - radius)) && (center->x <= (maxX + radius)) && (center->y >= (minY - radius)) && + (center->y <= (maxY + radius)) && (center->z >= (minZ - radius)) && (center->z <= (maxZ + radius))) { + return true; } - return 0; + return false; } -#else -#pragma GLOBAL_ASM("asm/non_matchings/code/sys_math3d/func_800CB338.s") -#endif -/**********************************************************************/ -f32 func_800CB55C(f32 arg0, f32 arg1) { - return SQ(arg0) + SQ(arg1); +/** + * Returns the distance squared between `a` and `b` on a single axis + */ +f32 Math3D_Dist1DSq(f32 a, f32 b) { + return SQ(a) + SQ(b); } -f32 func_800CB570(f32 arg0, f32 arg1) { - return sqrtf(func_800CB55C(arg0, arg1)); +/** + * Returns the distance between `a` and `b` on a single axis + */ +f32 Math3D_Dist1D(f32 a, f32 b) { + return sqrtf(Math3D_Dist1DSq(a, b)); } -f32 func_800CB594(f32 arg0, f32 arg1, f32 arg2, f32 arg3) { - func_800CB55C(arg0 - arg2, arg1 - arg3); +/** + * Returns the distance squared between (`x0`,`y0`) and (`x1`,`x2`) + */ +f32 Math3D_Dist2DSq(f32 x0, f32 y0, f32 x1, f32 y1) { + Math3D_Dist1DSq(x0 - x1, y0 - y1); } -f32 Math3D_Dist2D(f32 arg0, f32 arg1, f32 arg2, f32 arg3) { - return sqrtf(func_800CB594(arg0, arg1, arg2, arg3)); +/** + * Returns the distance between points (`x0`,`y0`) and (`x1`,`y1`) + */ +f32 Math3D_Dist2D(f32 x0, f32 y0, f32 x1, f32 y1) { + return sqrtf(Math3D_Dist2DSq(x0, y0, x1, y1)); } -f32 func_800CB600(Vec3f* vec) { +/** + * Returns the magntiude (length) squared of `vec` + */ +f32 Math3D_Vec3fMagnitudeSq(Vec3f* vec) { return SQ(vec->x) + SQ(vec->y) + SQ(vec->z); } +/** + * Returns the magnitude(length) of `vec` + */ f32 Math3D_Vec3fMagnitude(Vec3f* vec) { - return sqrt(func_800CB600(vec)); + return sqrt(Math3D_Vec3fMagnitudeSq(vec)); } -f32 func_800CB650(Vec3f* a, Vec3f* b) { +/** + * Returns the distance between `a` and `b` squared. + */ +f32 Math3D_Vec3fDistSq(Vec3f* a, Vec3f* b) { Vec3f diff; Math_Vec3f_Diff(a, b, &diff); - return func_800CB600(&diff); + return Math3D_Vec3fMagnitudeSq(&diff); } /* - * Math3D_Vec3f_DistXYZ * Calculates the distance between points `a` and `b` */ f32 Math3D_Vec3f_DistXYZ(Vec3f* a, Vec3f* b) { @@ -292,18 +474,30 @@ f32 Math3D_DistXYZ16toF(Vec3s* a, Vec3f* b) { return Math3D_Vec3fMagnitude(&diff); } -f32 func_800CB70C(Vec3f* arg0, Vec3f* arg1, f32 arg2, f32 arg3) { - return ((arg0->x - arg2) * (arg1->y - arg3)) - ((arg0->y - arg3) * (arg1->x - arg2)); +/** + * Gets the Z portion of the cross product of vectors `a - (`dx`,`dy`,z) and `b` - (`dx`,`dy`,z) + */ +f32 Math3D_Vec3fDiff_CrossZ(Vec3f* a, Vec3f* b, f32 dx, f32 dy) { + return ((a->x - dx) * (b->y - dy)) - ((a->y - dy) * (b->x - dx)); } -f32 func_800CB744(Vec3f* arg0, Vec3f* arg1, f32 arg2, f32 arg3) { - return ((arg0->y - arg2) * (arg1->z - arg3)) - ((arg0->z - arg3) * (arg1->y - arg2)); +/** + * Gets the X portion of the cross product of vectors `a - (x,`dy`,`dz`) and `b` - (x,`dy`,`dz`) + */ +f32 Math3D_Vec3fDiff_CrossX(Vec3f* a, Vec3f* b, f32 dy, f32 dz) { + return ((a->y - dy) * (b->z - dz)) - ((a->z - dz) * (b->y - dy)); } -f32 func_800CB77C(Vec3f* arg0, Vec3f* arg1, f32 arg2, f32 arg3) { - return ((arg0->z - arg2) * (arg1->x - arg3)) - ((arg0->x - arg3) * (arg1->z - arg2)); +/** + * Gets the Y portion of the cross product of vectors `a - (`dx`,y,`dz`) and `b` - (`dx`,y,`dz`) + */ +f32 Math3D_Vec3fDiff_CrossY(Vec3f* a, Vec3f* b, f32 dz, f32 dx) { + return ((a->z - dz) * (b->x - dx)) - ((a->x - dx) * (b->z - dz)); } +/** + * Gets the Cross Product of vectors `a` and `b` and places the result in `ret` + */ void Math3D_Vec3f_Cross(Vec3f* a, Vec3f* b, Vec3f* ret) { ret->x = (a->y * b->z) - (a->z * b->y); ret->y = (a->z * b->x) - (a->x * b->z); @@ -323,350 +517,367 @@ void Math3D_SurfaceNorm(Vec3f* va, Vec3f* vb, Vec3f* vc, Vec3f* normal) { Math3D_Vec3f_Cross(&abDiff, &acDiff, normal); } -s32 func_800CB88C(Vec3f* arg0, Vec3f* arg1, Vec3f* arg2) { +/** + * Creates flags relative to the faces of a cube. + */ +s32 Math3D_PointRelativeToCubeFaces(Vec3f* point, Vec3f* min, Vec3f* max) { s32 ret = 0; - if (arg2->x < arg0->x) { + if (point->x > max->x) { ret = 1; } - if (arg0->x < arg1->x) { + if (point->x < min->x) { ret |= 2; } - if (arg2->y < arg0->y) { + if (point->y > max->y) { ret |= 4; } - if (arg0->y < arg1->y) { + if (point->y < min->y) { ret |= 8; } - if (arg2->z < arg0->z) { + if (point->z > max->z) { ret |= 0x10; } - if (arg0->z < arg1->z) { + if (point->z < min->z) { ret |= 0x20; } + return ret; } -#ifdef NON_MATCHING -s32 func_800CB934(Vec3f* arg0, Vec3f* arg1, Vec3f* arg2) { +/** + * Creates flags of `point` relative to the edges of a cube + */ +s32 Math3D_PointRelativeToCubeEdges(Vec3f* point, Vec3f* min, Vec3f* max) { s32 ret = 0; - if ((arg2->y - arg1->x) < (arg0->y - arg0->x)) { + if ((-min->x + max->y) < (-point->x + point->y)) { ret |= 1; } - if ((arg0->y - arg0->x) < (arg1->y - arg2->x)) { + if ((-point->x + point->y) < (-max->x + min->y)) { ret |= 2; } - if ((arg2->x + arg2->y) < (arg0->x + arg0->y)) { + if ((max->x + max->y) < (point->x + point->y)) { ret |= 4; } - if ((arg0->x + arg0->y) < (arg1->x + arg1->y)) { + if ((point->x + point->y) < (min->x + min->y)) { ret |= 8; } - if ((-arg1->z + arg2->y) < (-arg0->z + arg0->y)) { + if ((-min->z + max->y) < (-point->z + point->y)) { ret |= 0x10; } - if ((-arg0->z + arg0->y) < (arg1->y - arg2->z)) { + if ((-point->z + point->y) < (-max->z + min->y)) { ret |= 0x20; } - if ((arg2->z + arg2->y) < (arg0->z + arg0->y)) { + if ((max->z + max->y) < (point->z + point->y)) { ret |= 0x40; } - if ((arg0->z + arg0->y) < (arg1->z + arg1->y)) { + if ((point->z + point->y) < (min->z + min->y)) { ret |= 0x80; } - if ((-arg1->z + arg2->x) < (-arg0->z + arg0->x)) { + if ((-min->z + max->x) < (-point->z + point->x)) { ret |= 0x100; } - if ((-arg0->z + arg0->x) < (-arg2->z + arg1->x)) { + if ((-point->z + point->x) < (-max->z + min->x)) { ret |= 0x200; } - if ((arg2->z + arg2->x) < (arg0->z + arg0->x)) { + if ((max->z + max->x) < (point->z + point->x)) { ret |= 0x400; } - if ((arg0->z + arg0->x) < (arg1->z + arg1->x)) { + if ((point->z + point->x) < (min->z + min->x)) { ret |= 0x800; } return ret; } -#else -#pragma GLOBAL_ASM("asm/non_matchings/code/sys_math3d/func_800CB934.s") -#endif -s32 func_800CBAE4(Vec3f* v0, Vec3f* v1, Vec3f* v2) { +/** + * Creates flags for `point` relative to the vertices of a cube + */ +s32 Math3D_PointRelativeToCubeVertices(Vec3f* point, Vec3f* min, Vec3f* max) { s32 ret = 0; - if ((v2->x + v2->y + v2->z) < (v0->x + v0->y + v0->z)) { - ret |= 1; + if ((max->x + max->y + max->z) < (point->x + point->y + point->z)) { + ret = 1; } - if ((-v1->x + v2->y + v2->z) < (-v0->x + v0->y + v0->z)) { + if ((-min->x + max->y + max->z) < (-point->x + point->y + point->z)) { ret |= 2; } - if ((-v1->x + v2->y - v1->z) < (-v0->x + v0->y - v0->z)) { + if ((-min->x + max->y - min->z) < (-point->x + point->y - point->z)) { ret |= 4; } - if ((v2->x + v2->y - v1->z) < (v0->x + v0->y - v0->z)) { + if ((max->x + max->y - min->z) < (point->x + point->y - point->z)) { ret |= 8; } - if ((v2->x - v1->y + v2->z) < (v0->x - v0->y + v0->z)) { + if ((max->x - min->y + max->z) < (point->x - point->y + point->z)) { ret |= 0x10; } - if ((-v1->x - v1->y + v2->z) < (-v0->x - v0->y + v0->z)) { + // @BUG: The next 2 conditions are the same check. + if ((-min->x - min->y + max->z) < (-point->x - point->y + point->z)) { ret |= 0x20; } - if ((-v1->x - v1->y + v2->z) < (-v0->x - v0->y + v0->z)) { + if ((-min->x - min->y + max->z) < (-point->x - point->y + point->z)) { ret |= 0x40; } - if ((-v1->x - v1->y - v1->z) < (-v0->x - v0->y - v0->z)) { + if ((-min->x - min->y - min->z) < (-point->x - point->y - point->z)) { ret |= 0x80; } return ret; } -s32 func_800CBC60(Vec3f* v0, Vec3f* v1, Vec3f* v2, Vec3f* v3) { - static Vec3f D_8016A608; - static Vec3f D_8016A618; - static Vec3f D_8016A628; - static Vec3f D_8016A638; +/** + * Checks if a line segment with endpoints `a` and `b` intersect a cube + */ +s32 Math3D_LineVsCube(Vec3f* min, Vec3f* max, Vec3f* a, Vec3f* b) { + static Vec3f triVtx0; + static Vec3f triVtx1; + static Vec3f triVtx2; + static Vec3f intersectPoint; s32 flags[2]; flags[0] = flags[1] = 0; - flags[0] = func_800CB88C(v2, v0, v1); + flags[0] = Math3D_PointRelativeToCubeFaces(a, min, max); if (!flags[0]) { - return 1; + return true; } - flags[1] = func_800CB88C(v3, v0, v1); + flags[1] = Math3D_PointRelativeToCubeFaces(b, min, max); if (!flags[1]) { - return 1; + return true; } if (flags[0] & flags[1]) { - return 0; + return false; } - flags[0] |= (func_800CB934(v2, v0, v1) << 8); - flags[1] |= (func_800CB934(v3, v0, v1) << 8); + flags[0] |= (Math3D_PointRelativeToCubeEdges(a, min, max) << 8); + flags[1] |= (Math3D_PointRelativeToCubeEdges(b, min, max) << 8); if (flags[0] & flags[1]) { - return 0; + return false; } - flags[0] |= (func_800CBAE4(v2, v0, v1) << 0x18); - flags[1] |= (func_800CBAE4(v3, v0, v1) << 0x18); + flags[0] |= (Math3D_PointRelativeToCubeVertices(a, min, max) << 0x18); + flags[1] |= (Math3D_PointRelativeToCubeVertices(b, min, max) << 0x18); if (flags[0] & flags[1]) { - return 0; - } - D_8016A608.x = v0->x; - D_8016A608.y = v0->y; - D_8016A608.z = v0->z; - D_8016A618.x = v0->x; - D_8016A618.y = v0->y; - D_8016A618.z = v1->z; - D_8016A628.x = v0->x; - D_8016A628.y = v1->y; - D_8016A628.z = v1->z; - if (Math3D_TriLineIntersect(&D_8016A608, &D_8016A618, &D_8016A628, -1.0f, 0.0f, 0.0f, v0->x, v2, v3, &D_8016A638, - 0)) { - return 1; - } - D_8016A608.x = v0->x; - D_8016A608.y = v0->y; - D_8016A608.z = v0->z; - D_8016A618.x = v0->x; - D_8016A618.y = v1->y; - D_8016A618.z = v1->z; - D_8016A628.x = v0->x; - D_8016A628.y = v1->y; - D_8016A628.z = v0->z; - if (Math3D_TriLineIntersect(&D_8016A608, &D_8016A618, &D_8016A628, -1.0f, 0.0f, 0.0f, v0->x, v2, v3, &D_8016A638, - 0)) { - return 1; - } - D_8016A608.x = v0->x; - D_8016A608.y = v1->y; - D_8016A608.z = v1->z; - D_8016A618.x = v0->x; - D_8016A618.y = v0->y; - D_8016A618.z = v1->z; - D_8016A628.x = v1->x; - D_8016A628.y = v1->y; - D_8016A628.z = v1->z; - if (Math3D_TriLineIntersect(&D_8016A608, &D_8016A618, &D_8016A628, 0.0f, 0.0f, 1.0f, -v1->z, v2, v3, &D_8016A638, - 0)) { - return 1; - } - D_8016A608.x = v1->x; - D_8016A608.y = v1->y; - D_8016A608.z = v1->z; - D_8016A618.x = v0->x; - D_8016A618.y = v0->y; - D_8016A618.z = v1->z; - D_8016A628.x = v1->x; - // POSSIBLE BUG? - D_8016A618.y = v0->y; - D_8016A628.z = v1->z; - if (Math3D_TriLineIntersect(&D_8016A608, &D_8016A618, &D_8016A628, 0.0f, 0.0f, 1.0f, -v1->z, v2, v3, &D_8016A638, - 0)) { - return 1; - } - D_8016A608.x = v1->x; - D_8016A608.y = v1->y; - D_8016A608.z = v1->z; - D_8016A618.x = v0->x; - D_8016A618.y = v1->y; - D_8016A618.z = v0->z; - D_8016A628.x = v0->x; - D_8016A628.y = v1->y; - D_8016A628.z = v1->z; - if (Math3D_TriLineIntersect(&D_8016A608, &D_8016A618, &D_8016A628, 0.0f, 1.0f, 0.0f, -v1->y, v2, v3, &D_8016A638, - 0)) { - return 1; - } - D_8016A608.x = v1->x; - D_8016A608.y = v1->y; - D_8016A608.z = v1->z; - D_8016A618.x = v1->x; - D_8016A618.y = v1->y; - D_8016A618.z = v0->z; - D_8016A628.x = v0->x; - D_8016A628.y = v1->y; - D_8016A628.z = v0->z; - if (Math3D_TriLineIntersect(&D_8016A608, &D_8016A618, &D_8016A628, 0.0f, 1.0f, 0.0f, -v1->y, v2, v3, &D_8016A638, - 0)) { - return 1; - } - D_8016A608.x = v0->x; - D_8016A608.y = v0->y; - D_8016A608.z = v0->z; - D_8016A618.x = v0->x; - D_8016A618.y = v1->y; - D_8016A618.z = v0->z; - D_8016A628.x = v1->x; - D_8016A628.y = v1->y; - D_8016A628.z = v0->z; - if (Math3D_TriLineIntersect(&D_8016A608, &D_8016A618, &D_8016A628, 0.0f, 0.0f, -1.0f, v0->z, v2, v3, &D_8016A638, - 0)) { - return 1; - } - D_8016A608.x = v0->x; - D_8016A608.y = v0->y; - D_8016A608.z = v0->z; - D_8016A618.x = v1->x; - D_8016A618.y = v1->y; - D_8016A618.z = v0->z; - D_8016A628.x = v1->x; - D_8016A628.y = v0->y; - D_8016A628.z = v0->z; - if (Math3D_TriLineIntersect(&D_8016A608, &D_8016A618, &D_8016A628, 0.0f, 0.0f, -1.0f, v0->z, v2, v3, &D_8016A638, - 0)) { - return 1; - } - D_8016A608.x = v0->x; - D_8016A608.y = v0->y; - D_8016A608.z = v0->z; - D_8016A618.x = v1->x; - D_8016A618.y = v0->y; - D_8016A618.z = v0->z; - D_8016A628.x = v1->x; - D_8016A628.y = v0->y; - D_8016A628.z = v1->z; - if (Math3D_TriLineIntersect(&D_8016A608, &D_8016A618, &D_8016A628, 0.0f, -1.0f, 0.0f, v0->y, v2, v3, &D_8016A638, - 0)) { - return 1; - } - D_8016A608.x = v0->x; - D_8016A608.y = v0->y; - D_8016A608.z = v0->z; - D_8016A618.x = v1->x; - D_8016A618.y = v0->y; - D_8016A618.z = v1->z; - D_8016A628.x = v0->x; - D_8016A628.y = v0->y; - D_8016A628.z = v1->z; - if (Math3D_TriLineIntersect(&D_8016A608, &D_8016A618, &D_8016A628, 0.0f, -1.0f, 0.0f, v0->y, v2, v3, &D_8016A638, - 0)) { - return 1; - } - D_8016A608.x = v1->x; - D_8016A608.y = v1->y; - D_8016A608.z = v1->z; - D_8016A618.x = v1->x; - D_8016A618.y = v0->y; - D_8016A618.z = v0->z; - D_8016A628.x = v1->x; - D_8016A628.y = v1->y; - D_8016A628.z = v0->z; - if (Math3D_TriLineIntersect(&D_8016A608, &D_8016A618, &D_8016A628, 1.0f, 0.0f, 0.0f, -v1->x, v2, v3, &D_8016A638, - 0)) { - return 1; - } - D_8016A608.x = v1->x; - D_8016A608.y = v1->y; - D_8016A608.z = v1->z; - D_8016A618.x = v1->x; - D_8016A618.y = v0->y; - D_8016A618.z = v1->z; - D_8016A628.x = v1->x; - D_8016A628.y = v0->y; - D_8016A628.z = v0->z; - if (Math3D_TriLineIntersect(&D_8016A608, &D_8016A618, &D_8016A628, 1.0f, 0.0f, 0.0f, -v1->x, v2, v3, &D_8016A638, - 0)) { - return 1; - } - - return 0; -} - -// Some type of quad detection? -s32 func_800CC6D8(Vec3s* v0, Vec3s* v1, Vec3s* v2, Vec3s* v3) { - static Vec3f v0f; - static Vec3f v1f; - static Vec3f v2f; - static Vec3f v3f; - - v0f.x = v0->x; - v0f.y = v0->y; - v0f.z = v0->z; - v1f.x = v1->x; - v1f.y = v1->y; - v1f.z = v1->z; - v2f.x = v2->x; - v2f.y = v2->y; - v2f.z = v2->z; - v3f.x = v3->x; - v3f.y = v3->y; - v3f.z = v3->z; - return func_800CBC60(&v0f, &v1f, &v2f, &v3f); -} - -void func_800CC824(Vec3f* arg0, s16 angle, f32* arg2, f32* arg3, f32* arg4) { - *arg2 = Math_Sins(angle) * 32767.0f; - *arg3 = Math_Coss(angle) * 32767.0f; - *arg4 = -((*arg2 * arg0->x) + (*arg3 * arg0->z)); + return false; + } + + // face 1 + triVtx0.x = min->x; + triVtx0.y = min->y; + triVtx0.z = min->z; + triVtx1.x = min->x; + triVtx1.y = min->y; + triVtx1.z = max->z; + triVtx2.x = min->x; + triVtx2.y = max->y; + triVtx2.z = max->z; + if (Math3D_TriLineIntersect(&triVtx0, &triVtx1, &triVtx2, -1.0f, 0.0f, 0.0f, min->x, a, b, &intersectPoint, 0)) { + return true; + } + + triVtx0.x = min->x; + triVtx0.y = min->y; + triVtx0.z = min->z; + triVtx1.x = min->x; + triVtx1.y = max->y; + triVtx1.z = max->z; + triVtx2.x = min->x; + triVtx2.y = max->y; + triVtx2.z = min->z; + if (Math3D_TriLineIntersect(&triVtx0, &triVtx1, &triVtx2, -1.0f, 0.0f, 0.0f, min->x, a, b, &intersectPoint, 0)) { + return true; + } + + // face 2 + triVtx0.x = min->x; + triVtx0.y = max->y; + triVtx0.z = max->z; + triVtx1.x = min->x; + triVtx1.y = min->y; + triVtx1.z = max->z; + triVtx2.x = max->x; + triVtx2.y = max->y; + triVtx2.z = max->z; + if (Math3D_TriLineIntersect(&triVtx0, &triVtx1, &triVtx2, 0.0f, 0.0f, 1.0f, -max->z, a, b, &intersectPoint, 0)) { + return true; + } + triVtx0.x = max->x; + triVtx0.y = max->y; + triVtx0.z = max->z; + triVtx1.x = min->x; + triVtx1.y = min->y; + triVtx1.z = max->z; + triVtx2.x = max->x; + // @Bug trVtx1.y should be triVtx2.y, prevents a tri on the cube from being checked. + triVtx1.y = min->y; + triVtx2.z = max->z; + if (Math3D_TriLineIntersect(&triVtx0, &triVtx1, &triVtx2, 0.0f, 0.0f, 1.0f, -max->z, a, b, &intersectPoint, 0)) { + return true; + } + + // face 3 + triVtx0.x = max->x; + triVtx0.y = max->y; + triVtx0.z = max->z; + triVtx1.x = min->x; + triVtx1.y = max->y; + triVtx1.z = min->z; + triVtx2.x = min->x; + triVtx2.y = max->y; + triVtx2.z = max->z; + if (Math3D_TriLineIntersect(&triVtx0, &triVtx1, &triVtx2, 0.0f, 1.0f, 0.0f, -max->y, a, b, &intersectPoint, 0)) { + return true; + } + triVtx0.x = max->x; + triVtx0.y = max->y; + triVtx0.z = max->z; + triVtx1.x = max->x; + triVtx1.y = max->y; + triVtx1.z = min->z; + triVtx2.x = min->x; + triVtx2.y = max->y; + triVtx2.z = min->z; + if (Math3D_TriLineIntersect(&triVtx0, &triVtx1, &triVtx2, 0.0f, 1.0f, 0.0f, -max->y, a, b, &intersectPoint, 0)) { + return true; + } + + // face 4 + triVtx0.x = min->x; + triVtx0.y = min->y; + triVtx0.z = min->z; + triVtx1.x = min->x; + triVtx1.y = max->y; + triVtx1.z = min->z; + triVtx2.x = max->x; + triVtx2.y = max->y; + triVtx2.z = min->z; + if (Math3D_TriLineIntersect(&triVtx0, &triVtx1, &triVtx2, 0.0f, 0.0f, -1.0f, min->z, a, b, &intersectPoint, 0)) { + return true; + } + triVtx0.x = min->x; + triVtx0.y = min->y; + triVtx0.z = min->z; + triVtx1.x = max->x; + triVtx1.y = max->y; + triVtx1.z = min->z; + triVtx2.x = max->x; + triVtx2.y = min->y; + triVtx2.z = min->z; + + // face 5 + if (Math3D_TriLineIntersect(&triVtx0, &triVtx1, &triVtx2, 0.0f, 0.0f, -1.0f, min->z, a, b, &intersectPoint, 0)) { + return true; + } + triVtx0.x = min->x; + triVtx0.y = min->y; + triVtx0.z = min->z; + triVtx1.x = max->x; + triVtx1.y = min->y; + triVtx1.z = min->z; + triVtx2.x = max->x; + triVtx2.y = min->y; + triVtx2.z = max->z; + if (Math3D_TriLineIntersect(&triVtx0, &triVtx1, &triVtx2, 0.0f, -1.0f, 0.0f, min->y, a, b, &intersectPoint, 0)) { + return true; + } + triVtx0.x = min->x; + triVtx0.y = min->y; + triVtx0.z = min->z; + triVtx1.x = max->x; + triVtx1.y = min->y; + triVtx1.z = max->z; + triVtx2.x = min->x; + triVtx2.y = min->y; + triVtx2.z = max->z; + + // face 6 + if (Math3D_TriLineIntersect(&triVtx0, &triVtx1, &triVtx2, 0.0f, -1.0f, 0.0f, min->y, a, b, &intersectPoint, 0)) { + return true; + } + triVtx0.x = max->x; + triVtx0.y = max->y; + triVtx0.z = max->z; + triVtx1.x = max->x; + triVtx1.y = min->y; + triVtx1.z = min->z; + triVtx2.x = max->x; + triVtx2.y = max->y; + triVtx2.z = min->z; + if (Math3D_TriLineIntersect(&triVtx0, &triVtx1, &triVtx2, 1.0f, 0.0f, 0.0f, -max->x, a, b, &intersectPoint, 0)) { + return true; + } + triVtx0.x = max->x; + triVtx0.y = max->y; + triVtx0.z = max->z; + triVtx1.x = max->x; + triVtx1.y = min->y; + triVtx1.z = max->z; + triVtx2.x = max->x; + triVtx2.y = min->y; + triVtx2.z = min->z; + if (Math3D_TriLineIntersect(&triVtx0, &triVtx1, &triVtx2, 1.0f, 0.0f, 0.0f, -max->x, a, b, &intersectPoint, 0)) { + return true; + } + + return false; +} + +/** + * Checks if a line segment with endpoints `a` and `b` intersect a cube + */ +s32 Math3D_LineVsCubeShort(Vec3s* min, Vec3s* max, Vec3s* a, Vec3s* b) { + static Vec3f minF; + static Vec3f maxF; + static Vec3f aF; + static Vec3f bF; + + minF.x = min->x; + minF.y = min->y; + minF.z = min->z; + maxF.x = max->x; + maxF.y = max->y; + maxF.z = max->z; + aF.x = a->x; + aF.y = a->y; + aF.z = a->z; + bF.x = b->x; + bF.y = b->y; + bF.z = b->z; + return Math3D_LineVsCube(&minF, &maxF, &aF, &bF); +} + +/** + * Rotates the xz plane around the y axis `angle` degrees. + * outputs the plane equation `a``pointOnPlane->x` + 0y + `c``pointOnPlane->z`+`d` = 0 + */ +void Math3D_RotateXZPlane(Vec3f* pointOnPlane, s16 angle, f32* a, f32* c, f32* d) { + *a = Math_Sins(angle) * 32767.0f; + *c = Math_Coss(angle) * 32767.0f; + *d = -((*a * pointOnPlane->x) + (*c * pointOnPlane->z)); } /* @@ -674,19 +885,19 @@ void func_800CC824(Vec3f* arg0, s16 angle, f32* arg2, f32* arg3, f32* arg4) { * `nx`, `ny`, and `nz`. Distance from the origin is output to `originDist` * Satisifes the plane equation NxVx + NyVy + NzVz + D = 0 */ -void func_800CC8B4(Vec3f* va, Vec3f* vb, Vec3f* vc, f32* nx, f32* ny, f32* nz, f32* originDist) { +void Math3D_DefPlane(Vec3f* va, Vec3f* vb, Vec3f* vc, f32* nx, f32* ny, f32* nz, f32* originDist) { static Vec3f normal; f32 normMagnitude; - f32 t; + f32 normMagInv; Math3D_SurfaceNorm(va, vb, vc, &normal); normMagnitude = sqrtf(SQ(normal.x) + SQ(normal.y) + SQ(normal.z)); - if (!(fabsf(normMagnitude) < 0.008f)) { - t = 1.0f / normMagnitude; - *nx = normal.x * t; - *ny = normal.y * t; - *nz = normal.z * t; + if (!IS_ZERO(normMagnitude)) { + normMagInv = 1.0f / normMagnitude; + *nx = normal.x * normMagInv; + *ny = normal.y * normMagInv; + *nz = normal.z * normMagInv; *originDist = -((*nx * va->x) + (*ny * va->y) + (*nz * va->z)); } else { *originDist = 0.0f; @@ -699,15 +910,16 @@ void func_800CC8B4(Vec3f* va, Vec3f* vb, Vec3f* vc, f32* nx, f32* ny, f32* nz, f /* * Returns the answer to the plane equation with elements specified by arguments. */ -f32 Math3D_Planef(f32 nx, f32 ny, f32 nz, f32 originDist, Vec3f* v) { - return (v->x * nx) + (ny * v->y) + (nz * v->z) + originDist; +f32 Math3D_Planef(f32 nx, f32 ny, f32 nz, f32 originDist, Vec3f* pointOnPlane) { + return (nx * pointOnPlane->x) + (ny * pointOnPlane->y) + (nz * pointOnPlane->z) + originDist; } /* * Returns the answer to the plane equation */ -f32 Math3D_Plane(Plane* plane, Vec3f* v) { - return ((plane->normal.x * v->x) + (plane->normal.y * v->y) + (plane->normal.z * v->z)) + plane->originDist; +f32 Math3D_Plane(Plane* plane, Vec3f* pointOnPlane) { + return (plane->normal.x * pointOnPlane->x) + (plane->normal.y * pointOnPlane->y) + + (plane->normal.z * pointOnPlane->z) + plane->originDist; } /* @@ -716,7 +928,7 @@ f32 Math3D_Plane(Plane* plane, Vec3f* v) { */ f32 Math3D_UDistPlaneToPos(f32 nx, f32 ny, f32 nz, f32 originDist, Vec3f* p) { - if (fabsf(sqrtf(SQ(nx) + SQ(ny) + SQ(nz))) < 0.008f) { + if (IS_ZERO(sqrtf(SQ(nx) + SQ(ny) + SQ(nz)))) { osSyncPrintf(VT_COL(YELLOW, BLACK)); // Math3DLengthPlaneAndPos(): Normal size is near zero %f %f %f osSyncPrintf("Math3DLengthPlaneAndPos():法線size がゼロ近いです%f %f %f\n", nx, ny, nz); @@ -734,7 +946,7 @@ f32 Math3D_DistPlaneToPos(f32 nx, f32 ny, f32 nz, f32 originDist, Vec3f* p) { f32 normMagnitude; normMagnitude = sqrtf(SQ(nx) + SQ(ny) + SQ(nz)); - if (fabsf(normMagnitude) < 0.008f) { + if (IS_ZERO(normMagnitude)) { osSyncPrintf(VT_COL(YELLOW, BLACK)); // Math3DSignedLengthPlaneAndPos(): Normal size is close to zero %f %f %f osSyncPrintf("Math3DSignedLengthPlaneAndPos():法線size がゼロ近いです%f %f %f\n", nx, ny, nz); @@ -744,379 +956,401 @@ f32 Math3D_DistPlaneToPos(f32 nx, f32 ny, f32 nz, f32 originDist, Vec3f* p) { return Math3D_Planef(nx, ny, nz, originDist, p) / normMagnitude; } -s32 func_800CCBE4(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 z, f32 x, f32 arg5, f32 arg6, f32 ny) { - f32 temp_f6; - f32 temp_f10; - f32 temp_f8; - f32 sp60; - f32 sq6; +/** + * Checks if the point defined by (`z`,`x`) is within distance of the triangle defined from `v0`,`v1`, and `v2` + */ +s32 Math3D_TriChkPointParaYImpl(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 z, f32 x, f32 detMax, f32 chkDist, f32 ny) { + f32 detv0v1; + f32 detv1v2; + f32 detv2v0; + f32 distToEdgeSq; + f32 chkDistSq; - if (func_800CB1F8(v0->z, v0->x, v1->z, v1->x, v2->z, v2->x, z, x, arg6) == 0) { - return 0; + // first check if the point is within range of the triangle. + if (!Math3D_CirSquareVsTriSquare(v0->z, v0->x, v1->z, v1->x, v2->z, v2->x, z, x, chkDist)) { + return false; } - sq6 = SQ(arg6); - if (((SQ(v0->z - z) + SQ(v0->x - x)) < sq6) || ((SQ(v1->z - z) + SQ(v1->x - x)) < sq6) || - ((SQ(v2->z - z) + SQ(v2->x - x)) < sq6)) { + // check if the point is within `chkDist` units of any vertex of the triangle. + chkDistSq = SQ(chkDist); + if (((SQ(v0->z - z) + SQ(v0->x - x)) < chkDistSq) || ((SQ(v1->z - z) + SQ(v1->x - x)) < chkDistSq) || + ((SQ(v2->z - z) + SQ(v2->x - x)) < chkDistSq)) { - return 1; + return true; } - temp_f6 = ((v0->z - z) * (v1->x - x)) - ((v0->x - x) * (v1->z - z)); - temp_f10 = ((v1->z - z) * (v2->x - x)) - ((v1->x - x) * (v2->z - z)); - temp_f8 = ((v2->z - z) * (v0->x - x)) - ((v2->x - x) * (v0->z - z)); + // Calculate the determinant of each face of the triangle to the point. + // If all the of determinants are within abs(`detMax`), return true. + detv0v1 = ((v0->z - z) * (v1->x - x)) - ((v0->x - x) * (v1->z - z)); + detv1v2 = ((v1->z - z) * (v2->x - x)) - ((v1->x - x) * (v2->z - z)); + detv2v0 = ((v2->z - z) * (v0->x - x)) - ((v2->x - x) * (v0->z - z)); - if (((temp_f6 <= arg5) && (temp_f10 <= arg5) && (temp_f8 <= arg5)) || - ((-arg5 <= temp_f6) && (-arg5 <= temp_f10) && (-arg5 <= temp_f8))) { - return 1; + if (((detMax >= detv0v1) && (detMax >= detv1v2) && (detMax >= detv2v0)) || + ((-detMax <= detv0v1) && (-detMax <= detv1v2) && (-detMax <= detv2v0))) { + return true; } - if (0.5f < fabsf(ny)) { - if (func_800CE4B8(z, x, v0->z, v0->x, v1->z, v1->x, &sp60)) { - if (sp60 < sq6) { - return 1; - } + + if (fabsf(ny) > 0.5f) { + // Do a check on each face of the triangle, if the point is within `chkDist` units return true. + if (Math3D_PointDistToLine2D(z, x, v0->z, v0->x, v1->z, v1->x, &distToEdgeSq) && (distToEdgeSq < chkDistSq)) { + return true; } - if (func_800CE4B8(z, x, v1->z, v1->x, v2->z, v2->x, &sp60)) { - if (sp60 < sq6) { - return 1; - } + if (Math3D_PointDistToLine2D(z, x, v1->z, v1->x, v2->z, v2->x, &distToEdgeSq) && (distToEdgeSq < chkDistSq)) { + return true; } - if (func_800CE4B8(z, x, v2->z, v2->x, v0->z, v0->x, &sp60)) { - if (sp60 < sq6) { - return 1; - } + + if (Math3D_PointDistToLine2D(z, x, v2->z, v2->x, v0->z, v0->x, &distToEdgeSq) && (distToEdgeSq < chkDistSq)) { + return true; } } - return 0; + return false; } -s32 func_800CCF00(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 z, f32 x, f32 arg5, f32 ny) { - return func_800CCBE4(v0, v1, v2, z, x, arg5, 1.0f, ny); +s32 Math3D_TriChkPointParaYDeterminate(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 z, f32 x, f32 detMax, f32 ny) { + return Math3D_TriChkPointParaYImpl(v0, v1, v2, z, x, detMax, 1.0f, ny); } -s32 func_800CCF48(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 z, f32 x) { - return func_800CCBE4(v0, v1, v2, z, x, 300.0f, 1.0f, 0.6f); +s32 Math3D_TriChkPointParaYSlopedY(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 z, f32 x) { + return Math3D_TriChkPointParaYImpl(v0, v1, v2, z, x, 300.0f, 1.0f, 0.6f); } -s32 func_800CCF98(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 arg3, f32 normMagnitude, f32 arg5, f32 arg6, f32 z, f32 x, - f32* pointDist, f32 argA) { - if (fabsf(normMagnitude) < 0.008f) { - return 0; +/** + * Performs the triangle and point check parallel to the Y axis, outputs the y coordinate of the point to `yIntersect` + */ +s32 Math3D_TriChkPointParaYIntersectDist(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 ny, f32 nz, f32 originDist, f32 z, + f32 x, f32* yIntersect, f32 chkDist) { + if (IS_ZERO(ny)) { + return false; } - if (func_800CCBE4(v0, v1, v2, z, x, 300.0f, argA, normMagnitude)) { - *pointDist = (f32)((((-arg3 * x) - (arg5 * z)) - arg6) / normMagnitude); - return 1; + + if (Math3D_TriChkPointParaYImpl(v0, v1, v2, z, x, 300.0f, chkDist, ny)) { + *yIntersect = (f32)((((-nx * x) - (nz * z)) - originDist) / ny); + return true; } - return 0; + + return false; } -s32 func_800CD044(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 arg3, f32 ny, f32 arg5, f32 arg6, f32 z, f32 x, f32* arg9, - f32 argA) { - if (fabsf(ny) < 0.008f) { - return 0; +s32 Math3D_TriChkPointParaYIntersectInsideTri(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 ny, f32 nz, f32 originDist, + f32 z, f32 x, f32* yIntersect, f32 chkDist) { + if (IS_ZERO(ny)) { + return false; } - if (func_800CCBE4(v0, v1, v2, z, x, 0.0f, argA, ny)) { - *arg9 = (f32)((((-arg3 * x) - (arg5 * z)) - arg6) / ny); - return 1; + + if (Math3D_TriChkPointParaYImpl(v0, v1, v2, z, x, 0.0f, chkDist, ny)) { + *yIntersect = (f32)((((-nx * x) - (nz * z)) - originDist) / ny); + return true; } - return 0; + + return false; } -s32 func_800CD0F0(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 ny, f32 z, f32 x) { - if (fabsf(ny) < 0.008f) { - return 0; +s32 Math3D_TriChkPointParaY(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 ny, f32 z, f32 x) { + if (IS_ZERO(ny)) { + return false; } - if (func_800CCBE4(v0, v1, v2, z, x, 300.0f, 1.0f, ny)) { - return 1; + if (Math3D_TriChkPointParaYImpl(v0, v1, v2, z, x, 300.0f, 1.0f, ny)) { + return true; } - return 0; + return false; } -/* - * Determines if the Triangle defined by verticies `v0`, `v1`, and `v2` with normal vector - * `nx`, `ny`, and `nz` is touching the cylinder defined by the center `cylZ`, `cylX` and top - * y componets `cylBottom` and `cylTop` are touching. The y component which they are touching is - * output to `yIntercept`, returns 1 if any part of the triangle is touching the cylinder. - */ -s32 Math3D_TriVtxCylTouching(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 ny, f32 nz, f32 originDist, f32 cylZ, - f32 cylX, f32* yIntercept, f32 cylBottom, f32 cylTop) { - f32 bottomDist; - f32 topDist; - Vec3f cylPos; +s32 Math3D_TriChkLineSegParaYIntersect(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 ny, f32 nz, f32 originDist, f32 z, + f32 x, f32* yIntersect, f32 y0, f32 y1) { + f32 pointADist; + f32 pointBDist; + Vec3f planePos; - if (fabsf(ny) < 0.008f) { - return 0; + if (IS_ZERO(ny)) { + return false; } - cylPos.x = cylX; - cylPos.y = cylBottom; - cylPos.z = cylZ; + planePos.x = x; + planePos.y = y0; + planePos.z = z; - bottomDist = Math3D_Planef(nx, ny, nz, originDist, &cylPos); - cylPos.y = cylTop; - topDist = Math3D_Planef(nx, ny, nz, originDist, &cylPos); - if (((bottomDist > 0.0f) && (topDist > 0.0f)) || ((bottomDist < 0.0f) && (topDist < 0.0f))) { - return 0; + pointADist = Math3D_Planef(nx, ny, nz, originDist, &planePos); + planePos.y = y1; + pointBDist = Math3D_Planef(nx, ny, nz, originDist, &planePos); + if (((pointADist > 0.0f) && (pointBDist > 0.0f)) || ((pointADist < 0.0f) && (pointBDist < 0.0f))) { + return false; } - if (func_800CCBE4(v0, v1, v2, cylZ, cylX, 300.0f, 1.0f, ny)) { - *yIntercept = (((-nx * cylX) - (nz * cylZ)) - originDist) / ny; - return 1; + if (Math3D_TriChkPointParaYImpl(v0, v1, v2, z, x, 300.0f, 1.0f, ny)) { + *yIntersect = (((-nx * x) - (nz * z)) - originDist) / ny; + return true; } - return 0; + + return false; } -s32 func_800CD2D8(Vec3f* v0, Vec3f* v1, Vec3f* v2, Plane* plane, f32 z, f32 x, f32 arg6) { - if (fabsf(plane->normal.y) < 0.008f) { - return 0; +s32 Math3D_TriChkPointParaYDist(Vec3f* v0, Vec3f* v1, Vec3f* v2, Plane* plane, f32 z, f32 x, f32 chkDist) { + if (IS_ZERO(plane->normal.y)) { + return false; } - if (func_800CCBE4(v0, v1, v2, z, x, 0.0f, arg6, plane->normal.y)) { - return 1; + + if (Math3D_TriChkPointParaYImpl(v0, v1, v2, z, x, 0.0f, chkDist, plane->normal.y)) { + return true; } - return 0; + + return false; } -s32 func_800CD34C(Vec3f* arg0, Vec3f* arg1, Vec3f* arg2, f32 arg3, f32 arg4, f32 arg5, f32 arg6, f32 arg7) { - f32 temp_f6; - f32 temp_f10; - f32 temp_f8; - f32 sp60; - f32 sq6; +s32 Math3D_TriChkPointParaXImpl(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 y, f32 z, f32 detMax, f32 chkDist, f32 nx) { + f32 detv0v1; + f32 detv1v2; + f32 detv2v0; + f32 distToEdgeSq; + f32 chkDistSq; - if (func_800CB1F8(arg0->y, arg0->z, arg1->y, arg1->z, arg2->y, arg2->z, arg3, arg4, arg6) == 0) { - return 0; + if (!Math3D_CirSquareVsTriSquare(v0->y, v0->z, v1->y, v1->z, v2->y, v2->z, y, z, chkDist)) { + return false; } - sq6 = SQ(arg6); - if (((SQ(arg0->y - arg3) + SQ(arg0->z - arg4)) < sq6) || ((SQ(arg1->y - arg3) + SQ(arg1->z - arg4)) < sq6) || - ((SQ(arg2->y - arg3) + SQ(arg2->z - arg4)) < sq6)) { - return 1; + chkDistSq = SQ(chkDist); + + if (((SQ(v0->y - y) + SQ(v0->z - z)) < chkDistSq) || ((SQ(v1->y - y) + SQ(v1->z - z)) < chkDistSq) || + ((SQ(v2->y - y) + SQ(v2->z - z)) < chkDistSq)) { + return true; } - temp_f6 = ((arg0->y - arg3) * (arg1->z - arg4)) - ((arg0->z - arg4) * (arg1->y - arg3)); - temp_f10 = ((arg1->y - arg3) * (arg2->z - arg4)) - ((arg1->z - arg4) * (arg2->y - arg3)); - temp_f8 = ((arg2->y - arg3) * (arg0->z - arg4)) - ((arg2->z - arg4) * (arg0->y - arg3)); + detv0v1 = ((v0->y - y) * (v1->z - z)) - ((v0->z - z) * (v1->y - y)); + detv1v2 = ((v1->y - y) * (v2->z - z)) - ((v1->z - z) * (v2->y - y)); + detv2v0 = ((v2->y - y) * (v0->z - z)) - ((v2->z - z) * (v0->y - y)); - if (((temp_f6 <= arg5) && (temp_f10 <= arg5) && (temp_f8 <= arg5)) || - ((-arg5 <= temp_f6) && (-arg5 <= temp_f10) && (-arg5 <= temp_f8))) { - return 1; + if (((detv0v1 <= detMax) && (detv1v2 <= detMax) && (detv2v0 <= detMax)) || + ((-detMax <= detv0v1) && (-detMax <= detv1v2) && (-detMax <= detv2v0))) { + return true; } - if (0.5f < fabsf(arg7)) { + if (fabsf(nx) > 0.5f) { - if (func_800CE4B8(arg3, arg4, arg0->y, arg0->z, arg1->y, arg1->z, &sp60)) { - if (sp60 < sq6) { - return 1; - } + if (Math3D_PointDistToLine2D(y, z, v0->y, v0->z, v1->y, v1->z, &distToEdgeSq) && (distToEdgeSq < chkDistSq)) { + return true; } - if (func_800CE4B8(arg3, arg4, arg1->y, arg1->z, arg2->y, arg2->z, &sp60)) { - if (sp60 < sq6) { - return 1; - } + if (Math3D_PointDistToLine2D(y, z, v1->y, v1->z, v2->y, v2->z, &distToEdgeSq) && (distToEdgeSq < chkDistSq)) { + return true; } - if (func_800CE4B8(arg3, arg4, arg2->y, arg2->z, arg0->y, arg0->z, &sp60)) { - if (sp60 < sq6) { - return 1; - } + if (Math3D_PointDistToLine2D(y, z, v2->y, v2->z, v0->y, v0->z, &distToEdgeSq) && (distToEdgeSq < chkDistSq)) { + return true; } } - return 0; + return false; } -s32 func_800CD668(Vec3f* arg0, Vec3f* arg1, Vec3f* arg2, f32 arg3, f32 arg4, f32 arg5, f32 arg6) { - return func_800CD34C(arg0, arg1, arg2, arg3, arg4, arg5, 1.0f, arg6); +s32 Math3D_TriChkPointParaXDeterminate(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 y, f32 z, f32 detMax, f32 nx) { + return Math3D_TriChkPointParaXImpl(v0, v1, v2, y, z, detMax, 1.0f, nx); } -s32 func_800CD6B0(Vec3f* arg0, Vec3f* arg1, Vec3f* arg2, f32 arg3, f32 arg4, f32 arg5, f32 arg6, f32 arg7, f32 arg8, - f32* arg9) { - if (fabsf(arg3) < 0.008f) { - return 0; +s32 Math3D_TriChkPointParaXIntersect(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 ny, f32 nz, f32 originDist, f32 y, + f32 z, f32* xIntersect) { + if (IS_ZERO(nx)) { + return false; } - arg3 = arg3; - if (func_800CD34C(arg0, arg1, arg2, arg7, arg8, 300.0f, 1.0f, arg3)) { - *arg9 = (f32)((((-arg4 * arg7) - (arg5 * arg8)) - arg6) / arg3); - return 1; + + if (Math3D_TriChkPointParaXImpl(v0, v1, v2, y, z, 300.0f, 1.0f, nx)) { + *xIntersect = (((-ny * y) - (nz * z)) - originDist) / nx; + return true; } - return 0; + return false; } -s32 func_800CD760(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 y, f32 z) { - if (fabsf(nx) < 0.008f) { - return 0; +s32 Math3D_TriChkPointParaX(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 y, f32 z) { + if (IS_ZERO(nx)) { + return false; } - if (func_800CD34C(v0, v1, v2, y, z, 300.0f, 1.0f, nx)) { - return 1; + if (Math3D_TriChkPointParaXImpl(v0, v1, v2, y, z, 300.0f, 1.0f, nx)) { + return true; } - return 0; + return false; } -s32 func_800CD7D8(Vec3f* arg0, Vec3f* arg1, Vec3f* arg2, f32 arg3, f32 arg4, f32 arg5, f32 arg6, f32 arg7, f32 arg8, - f32* arg9, f32 argA, f32 argB) { - static Vec3f D_8016A698; +s32 Math3D_TriChkLineSegParaXIntersect(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 ny, f32 nz, f32 originDist, f32 y, + f32 z, f32* xIntersect, f32 x0, f32 x1) { + static Vec3f planePos; - f32 sp34; - f32 temp_ret; + f32 pointADist; + f32 pointBDist; - if (fabsf(arg3) < 0.008f) { - return 0; + if (IS_ZERO(nx)) { + return false; } - D_8016A698.x = argA; - D_8016A698.y = arg7; - D_8016A698.z = arg8; - sp34 = Math3D_Planef(arg3, arg4, arg5, arg6, &D_8016A698); - D_8016A698.x = argB; - temp_ret = Math3D_Planef(arg3, arg4, arg5, arg6, &D_8016A698); - if (((sp34 > 0.0f) && (temp_ret > 0.0f)) || ((sp34 < 0.0f) && (temp_ret < 0.0f))) { - return 0; + planePos.x = x0; + planePos.y = y; + planePos.z = z; + pointADist = Math3D_Planef(nx, ny, nz, originDist, &planePos); + + planePos.x = x1; + pointBDist = Math3D_Planef(nx, ny, nz, originDist, &planePos); + + if (((pointADist > 0.0f) && (pointBDist > 0.0f)) || ((pointADist < 0.0f) && (pointBDist < 0.0f))) { + return false; } - if (func_800CD34C(arg0, arg1, arg2, arg7, arg8, 300.0f, 1.0f, arg3)) { - *arg9 = (((-arg4 * arg7) - (arg5 * arg8)) - arg6) / arg3; - return 1; + + if (Math3D_TriChkPointParaXImpl(v0, v1, v2, y, z, 300.0f, 1.0f, nx)) { + *xIntersect = (((-ny * y) - (nz * z)) - originDist) / nx; + return true; } - return 0; + return false; } -s32 func_800CD95C(Vec3f* arg0, Vec3f* arg1, Vec3f* arg2, f32* arg3, f32 arg4, f32 arg5, f32 arg6) { - if (fabsf(*arg3) < 0.008f) { - return 0; +s32 Math3D_TriChkPointParaXDist(Vec3f* v0, Vec3f* v1, Vec3f* v2, Plane* plane, f32 y, f32 z, f32 chkDist) { + if (IS_ZERO(plane->normal.x)) { + return false; } - if (func_800CD34C(arg0, arg1, arg2, arg4, arg5, 0.0f, arg6, *arg3)) { - return 1; + if (Math3D_TriChkPointParaXImpl(v0, v1, v2, y, z, 0.0f, chkDist, plane->normal.x)) { + return true; } - return 0; + return false; } -s32 func_800CD9D0(Vec3f* arg0, Vec3f* arg1, Vec3f* arg2, f32 arg3, f32 arg4, f32 arg5, f32 arg6, f32 arg7) { - f32 temp_f4; - f32 temp_f8; - f32 temp_f10; - f32 sp78; - f32 sq6; +s32 Math3D_TriChkPointParaZImpl(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 x, f32 y, f32 detMax, f32 chkDist, f32 nz) { + f32 detv0v1; + f32 detv1v2; + f32 detv2v0; + f32 distToEdgeSq; + f32 chkDistSq; - if (!func_800CB1F8(arg0->x, arg0->y, arg1->x, arg1->y, arg2->x, arg2->y, arg3, arg4, arg6)) { - return 0; + if (!Math3D_CirSquareVsTriSquare(v0->x, v0->y, v1->x, v1->y, v2->x, v2->y, x, y, chkDist)) { + return false; } - sq6 = SQ(arg6); - if (((SQ(arg3 - arg0->x) + SQ(arg4 - arg0->y)) < sq6) || ((SQ(arg3 - arg1->x) + SQ(arg4 - arg1->y)) < sq6) || - ((SQ(arg3 - arg2->x) + SQ(arg4 - arg2->y)) < sq6)) { - return 1; + + chkDistSq = SQ(chkDist); + + if (((SQ(x - v0->x) + SQ(y - v0->y)) < chkDistSq) || ((SQ(x - v1->x) + SQ(y - v1->y)) < chkDistSq) || + ((SQ(x - v2->x) + SQ(y - v2->y)) < chkDistSq)) { + // Distance from any vertex to a point is less than chkDist + return true; } - temp_f4 = ((arg0->x - arg3) * (arg1->y - arg4)) - ((arg0->y - arg4) * (arg1->x - arg3)); - temp_f8 = ((arg1->x - arg3) * (arg2->y - arg4)) - ((arg1->y - arg4) * (arg2->x - arg3)); - temp_f10 = ((arg2->x - arg3) * (arg0->y - arg4)) - ((arg2->y - arg4) * (arg0->x - arg3)); + detv0v1 = ((v0->x - x) * (v1->y - y)) - ((v0->y - y) * (v1->x - x)); + detv1v2 = ((v1->x - x) * (v2->y - y)) - ((v1->y - y) * (v2->x - x)); + detv2v0 = ((v2->x - x) * (v0->y - y)) - ((v2->y - y) * (v0->x - x)); - if (((arg5 >= temp_f4) && (arg5 >= temp_f8) && (arg5 >= temp_f10)) || - ((-arg5 <= temp_f4) && (-arg5 <= temp_f8) && (-arg5 <= temp_f10))) { - return 1; + if (((detMax >= detv0v1) && (detMax >= detv1v2) && (detMax >= detv2v0)) || + ((-detMax <= detv0v1) && (-detMax <= detv1v2) && (-detMax <= detv2v0))) { + return true; } - if (fabsf(arg7) > 0.5f) { + if (fabsf(nz) > 0.5f) { - if (func_800CE4B8(arg3, arg4, arg0->x, arg0->y, arg1->x, arg1->y, &sp78) && (sp78 < sq6)) { - return 1; + if (Math3D_PointDistToLine2D(x, y, v0->x, v0->y, v1->x, v1->y, &distToEdgeSq) && (distToEdgeSq < chkDistSq)) { + return true; } - if (func_800CE4B8(arg3, arg4, arg1->x, arg1->y, arg2->x, arg2->y, &sp78) && (sp78 < sq6)) { - return 1; + if (Math3D_PointDistToLine2D(x, y, v1->x, v1->y, v2->x, v2->y, &distToEdgeSq) && (distToEdgeSq < chkDistSq)) { + return true; } - if (func_800CE4B8(arg3, arg4, arg2->x, arg2->y, arg0->x, arg0->y, &sp78) && (sp78 < sq6)) { - return 1; + if (Math3D_PointDistToLine2D(x, y, v2->x, v2->y, v0->x, v0->y, &distToEdgeSq) && (distToEdgeSq < chkDistSq)) { + return true; } } - return 0; + return false; } -s32 func_800CDD18(Vec3f* arg0, Vec3f* arg1, Vec3f* arg2, f32 arg3, f32 arg4, f32 arg5, f32 arg6) { - return func_800CD9D0(arg0, arg1, arg2, arg3, arg4, arg5, 1.0f, arg6); +s32 Math3D_TriChkPointParaZDeterminate(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 x, f32 y, f32 detMax, f32 nz) { + return Math3D_TriChkPointParaZImpl(v0, v1, v2, x, y, detMax, 1.0f, nz); } -s32 func_800CDD60(Vec3f* arg0, Vec3f* arg1, Vec3f* arg2, f32 arg3, f32 arg4, f32 arg5, f32 arg6, f32 arg7, f32 arg8, - f32* arg9) { - if (fabsf(arg5) < 0.008f) { - return 0; +s32 Math3D_TriChkPointParaZIntersect(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 ny, f32 nz, f32 originDist, f32 x, + f32 y, f32* zIntersect) { + + if (IS_ZERO(nz)) { + return false; } - if (func_800CD9D0(arg0, arg1, arg2, arg7, arg8, 300.0f, 1.0f, arg5)) { - *arg9 = (f32)((((-arg3 * arg7) - (arg4 * arg8)) - arg6) / arg5); - return 1; + + if (Math3D_TriChkPointParaZImpl(v0, v1, v2, x, y, 300.0f, 1.0f, nz)) { + *zIntersect = (f32)((((-nx * x) - (ny * y)) - originDist) / nz); + return true; } - return 0; + return false; } -s32 func_800CDE10(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nz, f32 x, f32 y) { - if (fabsf(nz) < 0.008f) { - return 0; +s32 Math3D_TriChkPointParaZ(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nz, f32 x, f32 y) { + if (IS_ZERO(nz)) { + return false; } - if (func_800CD9D0(v0, v1, v2, x, y, 300.0f, 1.0f, nz)) { - return 1; + if (Math3D_TriChkPointParaZImpl(v0, v1, v2, x, y, 300.0f, 1.0f, nz)) { + return true; } - return 0; + return false; } -s32 func_800CDE88(Vec3f* arg0, Vec3f* arg1, Vec3f* arg2, f32 arg3, f32 arg4, f32 arg5, f32 arg6, f32 arg7, f32 arg8, - f32* arg9, f32 argA, f32 argB) { - static Vec3f D_8016A6A8; +s32 Math3D_TriChkLineSegParaZIntersect(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 ny, f32 nz, f32 originDist, f32 x, + f32 y, f32* zIntersect, f32 z0, f32 z1) { + static Vec3f planePos; - f32 sp2C; - f32 temp_ret; + f32 pointADist; + f32 pointBDist; - if (fabsf(arg5) < 0.008f) { - return 0; + if (IS_ZERO(nz)) { + return false; } - D_8016A6A8.x = arg7; - D_8016A6A8.y = arg8; - D_8016A6A8.z = argA; - sp2C = Math3D_Planef(arg3, arg4, arg5, arg6, &D_8016A6A8); - D_8016A6A8.z = argB; - temp_ret = Math3D_Planef(arg3, arg4, arg5, arg6, &D_8016A6A8); - if (((sp2C > 0.0f) && (temp_ret > 0.0f)) || ((sp2C < 0.0f) && (temp_ret < 0.0f))) { - return 0; + planePos.x = x; + planePos.y = y; + planePos.z = z0; + pointADist = Math3D_Planef(nx, ny, nz, originDist, &planePos); + + planePos.z = z1; + pointBDist = Math3D_Planef(nx, ny, nz, originDist, &planePos); + if (((pointADist > 0.0f) && (pointBDist > 0.0f)) || ((pointADist < 0.0f) && (pointBDist < 0.0f))) { + // points on the line segment are on the same side of the plane + return false; } - if (func_800CD9D0(arg0, arg1, arg2, arg7, arg8, 300.0f, 1.0f, arg5)) { - *arg9 = (((-arg3 * arg7) - (arg4 * arg8)) - arg6) / arg5; - return 1; + if (Math3D_TriChkPointParaZImpl(v0, v1, v2, x, y, 300.0f, 1.0f, nz)) { + *zIntersect = (((-nx * x) - (ny * y)) - originDist) / nz; + return true; } - return 0; + return false; } -s32 func_800CE010(Vec3f* arg0, Vec3f* arg1, Vec3f* arg2, Vec3f* arg3, f32 arg4, f32 arg5, f32 arg6) { - if (fabsf(arg3->z) < 0.008f) { - return 0; +s32 Math3D_TriChkLineSegParaZDist(Vec3f* v0, Vec3f* v1, Vec3f* v2, Plane* plane, f32 x, f32 y, f32 chkDist) { + if (IS_ZERO(plane->normal.z)) { + return false; } - if (func_800CD9D0(arg0, arg1, arg2, arg4, arg5, 0.0f, arg6, arg3->z)) { - return 1; + if (Math3D_TriChkPointParaZImpl(v0, v1, v2, x, y, 0.0f, chkDist, plane->normal.z)) { + return true; } - return 0; + return false; } -s32 func_800CE084(f32 pointADist, f32 pointBDist, Vec3f* pointA, Vec3f* pointB, Vec3f* intersect) { - f32 temp_f2; +s32 Math3D_LineSegFindPlaneIntersect(f32 pointADist, f32 pointBDist, Vec3f* pointA, Vec3f* pointB, Vec3f* intersect) { + f32 distDiff; - temp_f2 = pointADist - pointBDist; - if (fabsf(temp_f2) < 0.008f) { + distDiff = pointADist - pointBDist; + if (IS_ZERO(distDiff)) { + // both points lie on the plane. *intersect = *pointB; - return 0; + return false; } if (pointADist == 0.0f) { + // pointA is on the plane *intersect = *pointA; } else if (pointBDist == 0.0f) { + // pointB is on the plane *intersect = *pointB; } else { - func_800CAFA0(pointA, pointB, pointADist / temp_f2, intersect); + // place the point at the intersection point. + Math3D_LineSplitRatio(pointA, pointB, pointADist / distDiff, intersect); } - return 1; + return true; } -s32 func_800CE15C(f32 nx, f32 ny, f32 nz, f32 originDist, Vec3f* linePointA, Vec3f* linePointB, Vec3f* intersect, - s32 arg7) { +/** + * Determines if the line segement from `linePointA` to `linePointB` crosses the plane + * from `nx` + `ny` + `nz` + `originDist` = 0. If fromFront is set, then detection will only + * be true if point A crosses from the front of the plane + */ +s32 Math3D_LineSegVsPlane(f32 nx, f32 ny, f32 nz, f32 originDist, Vec3f* linePointA, Vec3f* linePointB, + Vec3f* intersect, s32 fromFront) { f32 pointADist; f32 pointBDist; @@ -1125,15 +1359,15 @@ s32 func_800CE15C(f32 nx, f32 ny, f32 nz, f32 originDist, Vec3f* linePointA, Vec if ((pointADist * pointBDist) > 0.0f) { *intersect = *linePointB; - return 0; + return false; } - if (arg7 != 0 && (pointADist < 0.0f) && (pointBDist > 0.0f)) { + if (fromFront && (pointADist < 0.0f) && (pointBDist > 0.0f)) { *intersect = *linePointB; - return 0; + return false; } - return func_800CE084(pointADist, pointBDist, linePointA, linePointB, intersect); + return Math3D_LineSegFindPlaneIntersect(pointADist, pointBDist, linePointA, linePointB, intersect); } /* @@ -1143,20 +1377,20 @@ s32 func_800CE15C(f32 nx, f32 ny, f32 nz, f32 originDist, Vec3f* linePointA, Vec * Returns 1 if the line intersects with the triangle, 0 otherwise */ s32 Math3D_TriLineIntersect(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 ny, f32 nz, f32 originDist, Vec3f* linePointA, - Vec3f* linePointB, Vec3f* intersect, s32 argA) { + Vec3f* linePointB, Vec3f* intersect, s32 fromFront) { - if (!func_800CE15C(nx, ny, nz, originDist, linePointA, linePointB, intersect, argA)) { - return 0; + if (!Math3D_LineSegVsPlane(nx, ny, nz, originDist, linePointA, linePointB, intersect, fromFront)) { + return false; } - if (((nx == 0.0f) || (func_800CD760(v0, v1, v2, nx, intersect->y, intersect->z))) && - ((ny == 0.0f) || (func_800CD0F0(v0, v1, v2, ny, intersect->z, intersect->x))) && - ((nz == 0.0f) || (func_800CDE10(v0, v1, v2, nz, intersect->x, intersect->y)))) { - return 1; + if (((nx == 0.0f) || (Math3D_TriChkPointParaX(v0, v1, v2, nx, intersect->y, intersect->z))) && + ((ny == 0.0f) || (Math3D_TriChkPointParaY(v0, v1, v2, ny, intersect->z, intersect->x))) && + ((nz == 0.0f) || (Math3D_TriChkPointParaZ(v0, v1, v2, nz, intersect->x, intersect->y)))) { + return true; } *intersect = *linePointB; - return 0; + return false; } /* @@ -1167,114 +1401,131 @@ void Math3D_TriNorm(TriNorm* tri, Vec3f* va, Vec3f* vb, Vec3f* vc) { tri->vtx[0] = *va; tri->vtx[1] = *vb; tri->vtx[2] = *vc; - func_800CC8B4(va, vb, vc, &tri->plane.normal.x, &tri->plane.normal.y, &tri->plane.normal.z, &tri->plane.originDist); + Math3D_DefPlane(va, vb, vc, &tri->plane.normal.x, &tri->plane.normal.y, &tri->plane.normal.z, + &tri->plane.originDist); } /* * Determines if point `point` lies within `sphere` */ -s32 Math3D_PointInSphere(Sphere16* sphere, Vec3f* point) { +s32 Math3D_PointInSph(Sphere16* sphere, Vec3f* point) { if (Math3D_DistXYZ16toF(&sphere->center, point) < sphere->radius) { - return 1; + return true; } - return 0; + return false; } -s32 func_800CE4B8(f32 arg0, f32 arg1, f32 arg2, f32 arg3, f32 arg4, f32 arg5, f32* arg6) { - static Vec3f D_8016A6B8; - - f32 temp_f0; - f32 temp_f2; - f32 temp_f16; - f32 temp_f18; - s32 ret = 0; - - temp_f2 = arg4 - arg2; - temp_f18 = arg5 - arg3; - temp_f16 = (temp_f2 * temp_f2) + (temp_f18 * temp_f18); - if (fabsf(temp_f16) < 0.008f) { - *arg6 = 0.0f; - return 0; - } - - temp_f0 = (((arg0 - arg2) * temp_f2) + (arg1 - arg3) * temp_f18) / temp_f16; - if (temp_f0 >= 0.0f) { - if (temp_f0 <= 1.0f) { - ret = 1; - } - } - D_8016A6B8.x = (temp_f2 * temp_f0) + arg2; - D_8016A6B8.y = (temp_f18 * temp_f0) + arg3; - *arg6 = (f32)(SQ(D_8016A6B8.x - arg0) + SQ(D_8016A6B8.y - arg1)); +/** + * Determines the distance from point (`x0`,`y0`) to the line fromed from (`x1`,`y1`) and (`x2`,`y2`) + * Distance squared is output to `lineLenSq`, returns true if the point perpendicular from (`x0`,`y0`) + * is contained within the segement between (`x1`,`y1`) and (`x2`,`y2`) + */ +s32 Math3D_PointDistToLine2D(f32 x0, f32 y0, f32 x1, f32 y1, f32 x2, f32 y2, f32* lineLenSq) { + static Vec3f perpendicularPoint; + + f32 perpendicularRatio; + f32 xDiff; + f32 distSq; + f32 yDiff; + s32 ret = false; + + xDiff = x2 - x1; + yDiff = y2 - y1; + distSq = SQ(xDiff) + SQ(yDiff); + if (IS_ZERO(distSq)) { + *lineLenSq = 0.0f; + return false; + } + + perpendicularRatio = (((x0 - x1) * xDiff) + (y0 - y1) * yDiff) / distSq; + if (perpendicularRatio >= 0.0f && perpendicularRatio <= 1.0f) { + ret = true; + } + perpendicularPoint.x = (xDiff * perpendicularRatio) + x1; + perpendicularPoint.y = (yDiff * perpendicularRatio) + y1; + *lineLenSq = SQ(perpendicularPoint.x - x0) + SQ(perpendicularPoint.y - y0); return ret; } -s32 func_800CE600(Sphere16* arg0, Linef* arg1) { - static Vec3f D_8016A6C8; +/** + * Determines if the line `line` is touching the sphere `sphere` at any point in the line. + */ +s32 Math3D_LineVsSph(Sphere16* sphere, Linef* line) { + static Vec3f sphLinePerpendicularPoint; - Vec3f t2; + Vec3f lineDiff; f32 temp_f0_2; - f32 temp_f2; + f32 lineLenSq; - if ((Math3D_PointInSphere(arg0, &arg1->a)) || (Math3D_PointInSphere(arg0, &arg1->b))) { - return 1; - } else { - t2.x = arg1->b.x - arg1->a.x; - t2.y = arg1->b.y - arg1->a.y; - t2.z = arg1->b.z - arg1->a.z; + if ((Math3D_PointInSph(sphere, &line->a)) || (Math3D_PointInSph(sphere, &line->b))) { + // either point of the line is in the sphere. + return true; + } + lineDiff.x = line->b.x - line->a.x; + lineDiff.y = line->b.y - line->a.y; + lineDiff.z = line->b.z - line->a.z; - temp_f2 = SQ(t2.x) + SQ(t2.y) + SQ(t2.z); - if (fabsf(temp_f2) < 0.008f) { - return 0; - } - temp_f0_2 = ((((arg0->center.x - arg1->a.x) * t2.x) + ((arg0->center.y - arg1->a.y) * t2.y)) + - ((arg0->center.z - arg1->a.z) * t2.z)) / - temp_f2; - if ((temp_f0_2 < 0.0f) || (1.0f < temp_f0_2)) { - return 0; - } + lineLenSq = SQ(lineDiff.x) + SQ(lineDiff.y) + SQ(lineDiff.z); + if (IS_ZERO(lineLenSq)) { + // line length is "0" + return false; + } + temp_f0_2 = ((((sphere->center.x - line->a.x) * lineDiff.x) + ((sphere->center.y - line->a.y) * lineDiff.y)) + + ((sphere->center.z - line->a.z) * lineDiff.z)) / + lineLenSq; + if ((temp_f0_2 < 0.0f) || (temp_f0_2 > 1.0f)) { + return false; + } - D_8016A6C8.x = (t2.x * temp_f0_2) + arg1->a.x; - D_8016A6C8.y = (t2.y * temp_f0_2) + arg1->a.y; - D_8016A6C8.z = (t2.z * temp_f0_2) + arg1->a.z; + sphLinePerpendicularPoint.x = (lineDiff.x * temp_f0_2) + line->a.x; + sphLinePerpendicularPoint.y = (lineDiff.y * temp_f0_2) + line->a.y; + sphLinePerpendicularPoint.z = (lineDiff.z * temp_f0_2) + line->a.z; - if (SQ(D_8016A6C8.x - arg0->center.x) + SQ(D_8016A6C8.y - arg0->center.y) + SQ(D_8016A6C8.z - arg0->center.z) <= - SQ((f32)arg0->radius)) { - return 1; - } + if (SQ(sphLinePerpendicularPoint.x - sphere->center.x) + SQ(sphLinePerpendicularPoint.y - sphere->center.y) + + SQ(sphLinePerpendicularPoint.z - sphere->center.z) <= + SQ((f32)sphere->radius)) { + return true; } - return 0; + return false; } -void func_800CE800(Sphere16* sphere, TriNorm* tri, Vec3f* ret) { - static Vec3f centroid; +/** + * Gets the surface point of `sphere` intersecting with `tri` generated from the line formed from the + * sphere's surface to the midpoint of the line formed from the first two vertices of the tri + */ +void Math3D_GetSphVsTriIntersectPoint(Sphere16* sphere, TriNorm* tri, Vec3f* intersectPoint) { + static Vec3f v0v1Center; static Vec3f sphereCenter; f32 dist; - f32 fw; + f32 splitRatio; - centroid.x = ((tri->vtx[0].x + tri->vtx[1].x) * 0.5f); - centroid.y = ((tri->vtx[0].y + tri->vtx[1].y) * 0.5f); - centroid.z = ((tri->vtx[0].z + tri->vtx[1].z) * 0.5f); + v0v1Center.x = ((tri->vtx[0].x + tri->vtx[1].x) * 0.5f); + v0v1Center.y = ((tri->vtx[0].y + tri->vtx[1].y) * 0.5f); + v0v1Center.z = ((tri->vtx[0].z + tri->vtx[1].z) * 0.5f); sphereCenter.x = sphere->center.x; sphereCenter.y = sphere->center.y; sphereCenter.z = sphere->center.z; - dist = Math3D_Vec3f_DistXYZ(¢roid, &sphereCenter); - if (fabsf(dist) < 0.008f) { - ret->x = sphereCenter.x; - ret->y = sphereCenter.y; - ret->z = sphereCenter.z; + dist = Math3D_Vec3f_DistXYZ(&v0v1Center, &sphereCenter); + // Distance from the sphere's center to the center of the line formed from v0->v1 + if (IS_ZERO(dist)) { + intersectPoint->x = sphereCenter.x; + intersectPoint->y = sphereCenter.y; + intersectPoint->z = sphereCenter.z; return; } - fw = sphere->radius / dist; - func_800CAFA0(&sphereCenter, ¢roid, fw, ret); + splitRatio = sphere->radius / dist; + Math3D_LineSplitRatio(&sphereCenter, &v0v1Center, splitRatio, intersectPoint); } -s32 func_800CE934(Sphere16* arg0, TriNorm* arg1, Vec3f* arg2) { - static Linef D_8016A6F8; - static Vec3f D_8016A710; - static Vec3f D_8016A720; +/** + * Determines if `sphere` and `tri` and touching, and outputs the intersection point to `intersectPoint` + */ +s32 Math3D_TriVsSphIntersect(Sphere16* sphere, TriNorm* tri, Vec3f* intersectPoint) { + static Linef triTestLine; + static Vec3f sphereCenter; + static Vec3f sphPlanePos; f32 radius; f32 nx; @@ -1282,74 +1533,78 @@ s32 func_800CE934(Sphere16* arg0, TriNorm* arg1, Vec3f* arg2) { f32 nz; f32 planeDist; - D_8016A710.x = arg0->center.x; - D_8016A710.y = arg0->center.y; - D_8016A710.z = arg0->center.z; - radius = arg0->radius; + sphereCenter.x = sphere->center.x; + sphereCenter.y = sphere->center.y; + sphereCenter.z = sphere->center.z; + radius = sphere->radius; - if (func_800CB338(&arg1->vtx[0], &arg1->vtx[1], &arg1->vtx[2], &D_8016A710, radius) == 0) { - return 0; + if (!Math3D_SphCubeVsTriCube(&tri->vtx[0], &tri->vtx[1], &tri->vtx[2], &sphereCenter, radius)) { + return false; } - planeDist = Math3D_UDistPlaneToPos(arg1->plane.normal.x, arg1->plane.normal.y, arg1->plane.normal.z, - arg1->plane.originDist, &D_8016A710); + planeDist = Math3D_UDistPlaneToPos(tri->plane.normal.x, tri->plane.normal.y, tri->plane.normal.z, + tri->plane.originDist, &sphereCenter); if (radius < planeDist) { - return 0; + // the point that lies within the plane of the triangle which is perpendicular to the sphere's center is more + // than the radius of the sphere, the plane never crosses the sphere. + return false; } - D_8016A6F8.a = arg1->vtx[0]; - D_8016A6F8.b = arg1->vtx[1]; - - if (func_800CE600(arg0, &D_8016A6F8)) { - func_800CE800(arg0, arg1, arg2); - return 1; + // tests if any of the edges of the triangle are intersecting the sphere + triTestLine.a = tri->vtx[0]; + triTestLine.b = tri->vtx[1]; + if (Math3D_LineVsSph(sphere, &triTestLine)) { + Math3D_GetSphVsTriIntersectPoint(sphere, tri, intersectPoint); + return true; } - D_8016A6F8.a = arg1->vtx[1]; - D_8016A6F8.b = arg1->vtx[2]; - if (func_800CE600(arg0, &D_8016A6F8)) { - func_800CE800(arg0, arg1, arg2); - return 1; + + triTestLine.a = tri->vtx[1]; + triTestLine.b = tri->vtx[2]; + if (Math3D_LineVsSph(sphere, &triTestLine)) { + Math3D_GetSphVsTriIntersectPoint(sphere, tri, intersectPoint); + return true; } - D_8016A6F8.a = arg1->vtx[2]; - D_8016A6F8.b = arg1->vtx[0]; - if (func_800CE600(arg0, &D_8016A6F8)) { - func_800CE800(arg0, arg1, arg2); - return 1; + + triTestLine.a = tri->vtx[2]; + triTestLine.b = tri->vtx[0]; + if (Math3D_LineVsSph(sphere, &triTestLine)) { + Math3D_GetSphVsTriIntersectPoint(sphere, tri, intersectPoint); + return true; } - nx = arg1->plane.normal.x * planeDist; - ny = arg1->plane.normal.y * planeDist; - nz = arg1->plane.normal.z * planeDist; + nx = tri->plane.normal.x * planeDist; + ny = tri->plane.normal.y * planeDist; + nz = tri->plane.normal.z * planeDist; - if (Math3D_Planef(arg1->plane.normal.x, arg1->plane.normal.y, arg1->plane.normal.z, arg1->plane.originDist, - &D_8016A710) > 0.0f) { - D_8016A720.x = D_8016A710.x - nx; - D_8016A720.y = D_8016A710.y - ny; - D_8016A720.z = D_8016A710.z - nz; + if (Math3D_Planef(tri->plane.normal.x, tri->plane.normal.y, tri->plane.normal.z, tri->plane.originDist, + &sphereCenter) > 0.0f) { + sphPlanePos.x = sphereCenter.x - nx; + sphPlanePos.y = sphereCenter.y - ny; + sphPlanePos.z = sphereCenter.z - nz; } else { - D_8016A720.x = D_8016A710.x + nx; - D_8016A720.y = D_8016A710.y + ny; - D_8016A720.z = D_8016A710.z + nz; + sphPlanePos.x = sphereCenter.x + nx; + sphPlanePos.y = sphereCenter.y + ny; + sphPlanePos.z = sphereCenter.z + nz; } - if (0.5f < fabsf(arg1->plane.normal.y)) { - if (func_800CCF00(&arg1->vtx[0], &arg1->vtx[1], &arg1->vtx[2], D_8016A720.z, D_8016A720.x, 0.0f, - arg1->plane.normal.y)) { - func_800CE800(arg0, arg1, arg2); - return 1; + if (fabsf(tri->plane.normal.y) > 0.5f) { + if (Math3D_TriChkPointParaYDeterminate(&tri->vtx[0], &tri->vtx[1], &tri->vtx[2], sphPlanePos.z, sphPlanePos.x, + 0.0f, tri->plane.normal.y)) { + Math3D_GetSphVsTriIntersectPoint(sphere, tri, intersectPoint); + return true; } - } else if (0.5f < fabsf(arg1->plane.normal.x)) { - if (func_800CD668(&arg1->vtx[0], &arg1->vtx[1], &arg1->vtx[2], D_8016A720.y, D_8016A720.z, 0.0f, - arg1->plane.normal.x)) { - func_800CE800(arg0, arg1, arg2); - return 1; + } else if (fabsf(tri->plane.normal.x) > 0.5f) { + if (Math3D_TriChkPointParaXDeterminate(&tri->vtx[0], &tri->vtx[1], &tri->vtx[2], sphPlanePos.y, sphPlanePos.z, + 0.0f, tri->plane.normal.x)) { + Math3D_GetSphVsTriIntersectPoint(sphere, tri, intersectPoint); + return true; } - } else if (func_800CDD18(&arg1->vtx[0], &arg1->vtx[1], &arg1->vtx[2], D_8016A720.x, D_8016A720.y, 0.0f, - arg1->plane.normal.z)) { - func_800CE800(arg0, arg1, arg2); - return 1; + } else if (Math3D_TriChkPointParaZDeterminate(&tri->vtx[0], &tri->vtx[1], &tri->vtx[2], sphPlanePos.x, + sphPlanePos.y, 0.0f, tri->plane.normal.z)) { + Math3D_GetSphVsTriIntersectPoint(sphere, tri, intersectPoint); + return true; } - return 0; + return false; } /* @@ -1368,93 +1623,312 @@ s32 Math3D_PointInCyl(Cylinder16* cyl, Vec3f* point) { top = cyl->height + bottom; if ((SQ(x) + SQ(z)) < SQ(cyl->radius) && (bottom < point->y) && (point->y < top)) { - return 1; + return true; } else { + return false; + } +} + +#ifdef NON_MATCHING +s32 Math3D_CylVsLineSeg(Cylinder16* cyl, Vec3f* linePointA, Vec3f* linePointB, Vec3f* intersectA, Vec3f* intersectB) { + Vec3f pointACylBottomDiff; + Vec3f pointBCylBottomDiff; + Vec3f spD4; + f32 spD0; + f32 spCC; + f32 spB8; + s32 sp9C; + Vec3f sp6C[4]; + s32 sp68; + f32 sp4C; + f32 sp2C; + f32 sp28; + f32* temp_a0; + f32* temp_a1; + f32* temp_s0; + f32 temp_f0; + f32 temp_f0_2; + f32 temp_f0_3; + f32 temp_f0_4; + f32 temp_f0_5; + f32 temp_f0_6; + f32 temp_f10; + f32 temp_f12; + f32 temp_f12_2; + f32 cylRadiusSq; + f32 temp_f14_2; + f32 temp_f14_3; + f32 temp_f16; + f32 temp_f16_2; + f32 temp_f18; + f32 temp_f2; + f32 temp_f2_2; + f32 temp_f2_3; + f32 temp_f2_4; + f32 temp_f2_5; + f32 temp_f2_6; + f32 temp_f2_7; + s32 temp_a0_2; + s32 temp_t0; + s32 temp_v0; + s32 temp_v1; + void* temp_t2; + s32 phi_a1; + s32 phi_a1_2; + f32 phi_f2; + s32 phi_v0; + s32 phi_v0_2; + s32 phi_v1; + s32 phi_v1_2; + s32 phi_a2; + s32 phi_a1_3; + s32 phi_a2_2; + s32 phi_a1_4; + s32 phi_v0_3; + s32 phi_t0; + s32 phi_v1_3; + s32 phi_v1_4; + s32 phi_a2_3; + s32 phi_a2_4; + s32 phi_t0_2; + s32 phi_v1_5; + s32 phi_t0_3; + + sp9C = 0; + if (Math3D_PointInCyl(cyl, linePointA) && Math3D_PointInCyl(cyl, linePointB)) { + // both points are in the cylinder + *intersectA = *linePointA; + *intersectB = *linePointB; + return 2; + } + + pointACylBottomDiff.x = linePointA->x - cyl->pos.x; + pointACylBottomDiff.y = linePointA->y - cyl->pos.y - cyl->yShift; + pointACylBottomDiff.z = linePointA->z - cyl->pos.z; + pointBCylBottomDiff.x = linePointB->x - cyl->pos.x; + pointBCylBottomDiff.y = linePointB->y - cyl->pos.y - cyl->yShift; + pointBCylBottomDiff.z = linePointB->z - cyl->pos.z; + Math_Vec3f_Diff(&pointBCylBottomDiff, &pointACylBottomDiff, &spD4); + cylRadiusSq = SQ(cyl->radius); + if (!IS_ZERO(spD4.y)) { + if (1) {} + if ((-pointACylBottomDiff.y / spD4.y) >= 0.0f) { + if ((-pointACylBottomDiff.y / spD4.y) <= 1.0f) { + if ((SQ((spD4.x * (-pointACylBottomDiff.y / spD4.y)) + pointACylBottomDiff.x) + + SQ((spD4.z * (-pointACylBottomDiff.y / spD4.y)) + pointACylBottomDiff.z)) < cylRadiusSq) { + sp6C[0].x = + (f32)cyl->pos.x + ((spD4.x * (-pointACylBottomDiff.y / spD4.y)) + pointACylBottomDiff.x); + sp6C[0].y = (f32)cyl->pos.y + (f32)cyl->yShift; + sp6C[0].z = + (f32)cyl->pos.z + ((spD4.z * (-pointACylBottomDiff.y / spD4.y)) + pointACylBottomDiff.z); + sp9C |= 1; + } + } + } + + phi_f2 = ((cyl->height - pointACylBottomDiff.y) / spD4.y); + if (phi_f2 >= 0.0f) { + if (phi_f2 <= 1.0f) { + if ((SQ(pointACylBottomDiff.x + (spD4.x * phi_f2)) + SQ(pointACylBottomDiff.z + (spD4.z * phi_f2))) < + cylRadiusSq) { + sp6C[1].x = (f32)cyl->pos.x + pointACylBottomDiff.x + (spD4.x * phi_f2); + sp6C[1].y = (f32)cyl->pos.y + cyl->height + cyl->yShift; + sp6C[1].z = (f32)cyl->pos.z + pointACylBottomDiff.z + (spD4.x * phi_f2); + sp9C |= 2; + } + } + } + } + + spB8 = SQ(pointACylBottomDiff.x) + SQ(pointACylBottomDiff.z) - cylRadiusSq; // 498c + temp_f12_2 = SQ(spD4.z) + SQ(spD4.x); + temp_f18 = temp_f12_2 * 2.0f; + if (!IS_ZERO(temp_f18)) { + temp_f2_3 = (spD4.x * pointACylBottomDiff.x) + (spD4.z * pointACylBottomDiff.z); + temp_f14_2 = temp_f2_3 + temp_f2_3; + temp_f0_3 = temp_f14_2 * temp_f14_2; + temp_f16_2 = (4.0f * temp_f12_2) * spB8; + if (temp_f0_3 < temp_f16_2) { + return false; + } + + phi_a1 = (temp_f0_3 - temp_f16_2) > 0.0f; + phi_f2 = (sqrtf((temp_f0_3 - temp_f16_2)) - temp_f14_2) / temp_f18; + + if (phi_a1) { + spCC = (-temp_f14_2 - sqrtf((temp_f0_3 - temp_f16_2))) / temp_f18; + } + } else if (!IS_ZERO(((spD4.x * pointACylBottomDiff.x) + (spD4.z * pointACylBottomDiff.z)) + + ((spD4.x * pointACylBottomDiff.x) + (spD4.z * pointACylBottomDiff.z)))) { + phi_f2 = -spB8 / ((spD4.x * pointACylBottomDiff.x) + (spD4.z * pointACylBottomDiff.z)) + + ((spD4.x * pointACylBottomDiff.x) + (spD4.z * pointACylBottomDiff.z)); + phi_a2 = 1; + phi_a1 = 0; + } else { + return 0; + } + + if (!phi_a1) { + if (phi_f2 < 0.0f || phi_f2 > 1.0f) { + return false; + } + } else { + phi_a2 = phi_f2 < 0.0f || phi_f2 > 1.0f; + + phi_a1 = spCC < 0.0f || spCC > 1.0f; + + if (phi_a1 && phi_a2) { + return 0; + } + + if (phi_a2) { + phi_a2 = 0; + } + + if (phi_a1) { + phi_a1 = 0; + } + } + + if ((phi_a2 == 1) && (((phi_f2 * spD4.y) + pointACylBottomDiff.y) < 0.0f || + cyl->height < ((phi_f2 * spD4.y) + pointACylBottomDiff.y))) { + phi_a2 = 0; + } + + if ((phi_a1 == 1) && + (((spCC * spD4.y) + pointACylBottomDiff.y) < 0.0f || cyl->height < ((spCC * spD4.y) + pointACylBottomDiff.y))) { + phi_a1 = 0; + } + if (phi_a2 == 0 && phi_a1 == 0) { return 0; } + + if (phi_a2 == 1 && phi_a1 == 1) { + sp6C[2].x = ((phi_f2 * spD4.x) + pointACylBottomDiff.x) + (f32)cyl->pos.x; + sp6C[2].y = (((phi_f2 * spD4.y) + pointACylBottomDiff.y) + (f32)cyl->pos.y) + (f32)cyl->yShift; + sp6C[2].z = ((phi_f2 * spD4.z) + pointACylBottomDiff.z) + (f32)cyl->pos.z; + sp6C[2].x = ((spCC * spD4.x) + pointACylBottomDiff.x) + (f32)cyl->pos.x; + sp6C[2].y = (((spCC * spD4.y) + pointACylBottomDiff.y) + (f32)cyl->pos.y) + (f32)cyl->yShift; + sp6C[2].z = ((spCC * spD4.z) + pointACylBottomDiff.z) + (f32)cyl->pos.z; + sp9C = (sp9C | 4) | 8; + } else if (phi_a2 == 1) { + sp6C[2].x = ((phi_f2 * spD4.x) + pointACylBottomDiff.x) + (f32)cyl->pos.x; + sp6C[2].y = (((phi_f2 * spD4.y) + pointACylBottomDiff.y) + (f32)cyl->pos.y) + (f32)cyl->yShift; + sp6C[2].z = ((phi_f2 * spD4.z) + pointACylBottomDiff.z) + (f32)cyl->pos.z; + sp9C |= 4; + } else if (phi_a1 == 1) { + sp6C[2].x = ((spCC * spD4.x) + pointACylBottomDiff.x) + (f32)cyl->pos.x; + sp6C[2].y = (((spCC * spD4.y) + pointACylBottomDiff.y) + (f32)cyl->pos.y) + (f32)cyl->yShift; + sp6C[2].z = ((spCC * spD4.z) + pointACylBottomDiff.z) + (f32)cyl->pos.z; + sp9C |= 4; + } + + for (phi_v0_3 = 0, phi_v1_3 = 0; phi_v0_3 < 4; phi_v0_3++) { + if (sp9C & (1 << phi_v0_3)) { + if (phi_v1_3 == 0) { + *intersectA = sp6C[phi_v0_3]; + } else if (phi_v1_3 == 1) { + if (Math3D_Vec3fDistSq(intersectA, linePointA) < Math3D_Vec3fDistSq(intersectA, &sp6C[phi_v0_3])) { + *intersectB = sp6C[phi_v0_3]; + } else { + *intersectB = *intersectA; + *intersectA = sp6C[phi_v0_3]; + } + break; + } + } + phi_v1_3++; + } + + return phi_v1_3; } -#pragma GLOBAL_ASM("asm/non_matchings/code/sys_math3d/func_800CEE0C.s") +#else +#pragma GLOBAL_ASM("asm/non_matchings/code/sys_math3d/Math3D_CylVsLineSeg.s") +#endif /* * Determines if `cyl` and `tri` are touching. The point of intersection * is placed in `intersect` Returns 1 if they are touching, 0 otherwise. */ -s32 Math3D_CylTriTouchingIntersect(Cylinder16* cyl, TriNorm* tri, Vec3f* intersect) { +s32 Math3D_CylTriVsIntersect(Cylinder16* cyl, TriNorm* tri, Vec3f* intersect) { static Sphere16 topSphere; static Sphere16 bottomSphere; - static Vec3f D_8016A740; - static Vec3f D_8016A750; + static Vec3f cylIntersectA; + static Vec3f cylIntersectB; - f32 sp8C; + f32 yIntersect; f32 cylTop; f32 cylBottom; - f32 phi_f2; - f32 t; - f32 temp_ret; - Vec3f sp6C; - Vec3f sp60; - Vec3f sp54; - f32 temp_f14_2; - f32 temp_f2; + f32 minDistSq; + f32 radiusTodistFromCylYIntersectTov0v1; + f32 distFromPointAToIntersectASq; + Vec3f cylIntersectCenter; + Vec3f midpointv0v1; + Vec3f diffMidpointIntersect; + f32 distFromCylYIntersectTov0v1; + s32 pad; cylBottom = (f32)cyl->pos.y + cyl->yShift; cylTop = cyl->height + cylBottom; - // If all of the verticies are below or all of the verticies are above the cylinder. - if (((tri->vtx[0].y < cylBottom) && (tri->vtx[1].y < cylBottom) && (tri->vtx[2].y < cylBottom)) || ((cylTop < tri->vtx[0].y) && (cylTop < tri->vtx[1].y) && (cylTop < tri->vtx[2].y))) { - return 0; + // If all of the verticies are below or all of the verticies are above the cylinder. + return false; } - phi_f2 = 1.e38f; - if (func_800CEE0C(cyl, &tri->vtx[0], &tri->vtx[1], &D_8016A740, &D_8016A750)) { - phi_f2 = func_800CB650(&D_8016A740, &tri->vtx[0]); - *intersect = D_8016A740; + + minDistSq = 1.e38f; + if (Math3D_CylVsLineSeg(cyl, &tri->vtx[0], &tri->vtx[1], &cylIntersectA, &cylIntersectB)) { + distFromPointAToIntersectASq = Math3D_Vec3fDistSq(&cylIntersectA, &tri->vtx[0]); + minDistSq = distFromPointAToIntersectASq; + *intersect = cylIntersectA; } - if (func_800CEE0C(cyl, &tri->vtx[2], &tri->vtx[1], &D_8016A740, &D_8016A750)) { - temp_ret = func_800CB650(&D_8016A740, &tri->vtx[2]); - if (temp_ret < phi_f2) { - *intersect = D_8016A740; - phi_f2 = temp_ret; + if (Math3D_CylVsLineSeg(cyl, &tri->vtx[2], &tri->vtx[1], &cylIntersectA, &cylIntersectB)) { + distFromPointAToIntersectASq = Math3D_Vec3fDistSq(&cylIntersectA, &tri->vtx[2]); + if (distFromPointAToIntersectASq < minDistSq) { + *intersect = cylIntersectA; + minDistSq = distFromPointAToIntersectASq; } } - if (func_800CEE0C(cyl, &tri->vtx[0], &tri->vtx[2], &D_8016A740, &D_8016A750)) { - temp_ret = func_800CB650(&D_8016A740, &tri->vtx[0]); - if (temp_ret < phi_f2) { - *intersect = D_8016A740; - phi_f2 = temp_ret; + if (Math3D_CylVsLineSeg(cyl, &tri->vtx[0], &tri->vtx[2], &cylIntersectA, &cylIntersectB)) { + distFromPointAToIntersectASq = Math3D_Vec3fDistSq(&cylIntersectA, &tri->vtx[0]); + if (distFromPointAToIntersectASq < minDistSq) { + *intersect = cylIntersectA; + minDistSq = distFromPointAToIntersectASq; } } - // what is 1.e38f ? - if (phi_f2 != 1.e38f) { - return 1; + + if (minDistSq != 1.e38f) { + return true; } - if (Math3D_TriVtxCylTouching(&tri->vtx[0], &tri->vtx[1], &tri->vtx[2], tri->plane.normal.x, tri->plane.normal.y, - tri->plane.normal.z, tri->plane.originDist, cyl->pos.z, cyl->pos.x, &sp8C, cylBottom, - cylTop)) { + if (Math3D_TriChkLineSegParaYIntersect(&tri->vtx[0], &tri->vtx[1], &tri->vtx[2], tri->plane.normal.x, + tri->plane.normal.y, tri->plane.normal.z, tri->plane.originDist, cyl->pos.z, + cyl->pos.x, &yIntersect, cylBottom, cylTop)) { - sp6C.x = cyl->pos.x; - sp6C.y = sp8C; - sp6C.z = cyl->pos.z; + cylIntersectCenter.x = cyl->pos.x; + cylIntersectCenter.y = yIntersect; + cylIntersectCenter.z = cyl->pos.z; - sp60.x = (tri->vtx[0].x + tri->vtx[1].x) * 0.5f; - sp60.y = (tri->vtx[0].y + tri->vtx[1].y) * 0.5f; - sp60.z = (tri->vtx[0].z + tri->vtx[1].z) * 0.5f; + midpointv0v1.x = (tri->vtx[0].x + tri->vtx[1].x) * 0.5f; + midpointv0v1.y = (tri->vtx[0].y + tri->vtx[1].y) * 0.5f; + midpointv0v1.z = (tri->vtx[0].z + tri->vtx[1].z) * 0.5f; - Math_Vec3f_Diff(&sp60, &sp6C, &sp54); - temp_f14_2 = sqrtf((sp54.x * sp54.x) + (sp54.z * sp54.z)); + Math_Vec3f_Diff(&midpointv0v1, &cylIntersectCenter, &diffMidpointIntersect); + distFromCylYIntersectTov0v1 = sqrtf(SQ(diffMidpointIntersect.x) + SQ(diffMidpointIntersect.z)); - if (fabsf(temp_f14_2) < 0.008f) { - Math_Vec3f_Copy(intersect, &sp60); - return 1; + if (IS_ZERO(distFromCylYIntersectTov0v1)) { + Math_Vec3f_Copy(intersect, &midpointv0v1); + return true; } - t = cyl->radius / temp_f14_2; - func_800CAF5C(&sp6C, &sp54, t, intersect); - return 1; + + radiusTodistFromCylYIntersectTov0v1 = cyl->radius / distFromCylYIntersectTov0v1; + Math3D_PointOnInfinteLine(&cylIntersectCenter, &diffMidpointIntersect, radiusTodistFromCylYIntersectTov0v1, + intersect); + return true; } topSphere.center.x = bottomSphere.center.x = cyl->pos.x; @@ -1463,48 +1937,45 @@ s32 Math3D_CylTriTouchingIntersect(Cylinder16* cyl, TriNorm* tri, Vec3f* interse bottomSphere.center.y = cylBottom; topSphere.radius = bottomSphere.radius = cyl->radius; - if ((func_800CE934(&topSphere, tri, intersect)) || (func_800CE934(&bottomSphere, tri, intersect))) { - return 1; + if ((Math3D_TriVsSphIntersect(&topSphere, tri, intersect)) || + (Math3D_TriVsSphIntersect(&bottomSphere, tri, intersect))) { + return true; } - return 0; + return false; } /* - * Returns 1 if `cyl` and `tri` and touching + * Determines if `cyl` and `tri` are touching. */ -s32 Math3D_CylTriTouching(Cylinder16* cyl, TriNorm* tri) { +s32 Math3D_CylVsTri(Cylinder16* cyl, TriNorm* tri) { Vec3f intersect; - return Math3D_CylTriTouchingIntersect(cyl, tri, &intersect); + return Math3D_CylTriVsIntersect(cyl, tri, &intersect); } /* - * Deteremines if two spheres are touching. Returns 1 if their closest surface point - * is within 0.008f units. 0 otherwise. + * Deteremines if two spheres are touching. */ -s32 Math3D_SpheresTouching(Sphere16* sphereA, Sphere16* sphereB) { - f32 surfaceDist; +s32 Math3D_SphVsSph(Sphere16* sphereA, Sphere16* sphereB) { + f32 overlapSize; - return Math3D_SpheresTouchingSurface(sphereA, sphereB, &surfaceDist); + return Math3D_SphVsSphOverlap(sphereA, sphereB, &overlapSize); } /* - * Determines if two spheres are within 0.008 units of each other. The distance from - * the closest point on the surface is placed in `surfaceDist` Returns 1 if the surfaces - * are not touching. Returns 0 otherwise. + * Determines if two spheres are touching. The amount that they're overlapping is placed in `overlapSize` */ -s32 Math3D_SpheresTouchingSurface(Sphere16* sphereA, Sphere16* sphereB, f32* surfaceDist) { +s32 Math3D_SphVsSphOverlap(Sphere16* sphereA, Sphere16* sphereB, f32* overlapSize) { f32 centerDist; - return Math3D_SpheresTouchingSurfaceCenter(sphereA, sphereB, surfaceDist, ¢erDist); + return Math3D_SphVsSphOverlapCenter(sphereA, sphereB, overlapSize, ¢erDist); } /* - * Determines if two spheres are within 0.008f units of each other. The distance from - * the centers is placed in `centerDist` and the closest distance to their surfaces is placed - * in `surfaceDist` Returns 1 if the surfaces are not touching. Returns 0 otherwise. + * Determines if two spheres are touching The distance from the centers is placed in `centerDist`, + * and the amount that they're overlapping is placed in `overlapSize` */ -s32 Math3D_SpheresTouchingSurfaceCenter(Sphere16* sphereA, Sphere16* sphereB, f32* surfaceDist, f32* centerDist) { +s32 Math3D_SphVsSphOverlapCenter(Sphere16* sphereA, Sphere16* sphereB, f32* overlapSize, f32* centerDist) { Vec3f diff; diff.x = (f32)sphereA->center.x - (f32)sphereB->center.x; @@ -1513,35 +1984,43 @@ s32 Math3D_SpheresTouchingSurfaceCenter(Sphere16* sphereA, Sphere16* sphereB, f3 *centerDist = sqrt(SQ(diff.x) + SQ(diff.y) + SQ(diff.z)); - *surfaceDist = (((f32)sphereA->radius + (f32)sphereB->radius) - *centerDist); - if (0.008f < *surfaceDist) { - return 1; + *overlapSize = (((f32)sphereA->radius + (f32)sphereB->radius) - *centerDist); + if (*overlapSize > 0.008f) { + return true; } - *surfaceDist = 0.0f; - return 0; + *overlapSize = 0.0f; + return false; } -s32 func_800CFD84(Sphere16* sph, Cylinder16* cyl, f32* surfaceDist) { +/** + * Checks if `sph` and `cyl` are touching, output the amount of overlap to `overlapSize` + */ +s32 Math3D_SphVsCylOverlapDist(Sphere16* sph, Cylinder16* cyl, f32* overlapSize) { f32 centerDist; - return func_800CFDA4(sph, cyl, surfaceDist, ¢erDist); + return Math3D_SphVsCylOverlapCenterDist(sph, cyl, overlapSize, ¢erDist); } -s32 func_800CFDA4(Sphere16* sph, Cylinder16* cyl, f32* surfaceDist, f32* centerDist) { +/** + * Checks if `sph` and `cyl` are touching, output the xz distance of the centers to `centerDist`, and the amount of + * overlap to `overlapSize` + */ +s32 Math3D_SphVsCylOverlapCenterDist(Sphere16* sph, Cylinder16* cyl, f32* overlapSize, f32* centerDist) { static Cylinderf cylf; static Spheref sphf; f32 x; f32 z; - f32 rad; + f32 combinedRadius; f32 cylBottom; f32 cylTop; f32 sphBottom; f32 sphTop; if (sph->radius <= 0 || cyl->radius <= 0) { - return 0; + // either radius is 0 + return false; } sphf.center.y = sph->center.y; sphf.radius = sph->radius; @@ -1550,10 +2029,11 @@ s32 func_800CFDA4(Sphere16* sph, Cylinder16* cyl, f32* surfaceDist, f32* centerD cylf.height = cyl->height; x = (f32)sph->center.x - cyl->pos.x; z = (f32)sph->center.z - cyl->pos.z; - rad = (f32)sph->radius + cyl->radius; + combinedRadius = (f32)sph->radius + cyl->radius; *centerDist = sqrtf(SQ(x) + SQ(z)); - if (rad < *centerDist) { - return 0; + if (combinedRadius < *centerDist) { + // if the combined radii is less than the distance to the centers, they cannot be touching. + return false; } cylBottom = (cylf.pos.y + cylf.yShift); @@ -1562,20 +2042,22 @@ s32 func_800CFDA4(Sphere16* sph, Cylinder16* cyl, f32* surfaceDist, f32* centerD sphTop = sphf.center.y + sphf.radius; if ((sphTop >= cylBottom) && (sphBottom <= cylTop)) { - *surfaceDist = rad - *centerDist; - return 1; + // if the cylinder and sphere are intersecting on the xz plane, check if they're intersecting on + // the y axis. + *overlapSize = combinedRadius - *centerDist; + return true; } - return 0; + return false; } /* * returns 1 if cylinder `ca` is outside cylinder `cb`. * Sets `deadSpace` to the mininum space between the cylinders not occupied by the other. */ -s32 Math3D_CylinderOutCylinder(Cylinder16* ca, Cylinder16* cb, f32* deadSpace) { +s32 Math3D_CylOutsideCyl(Cylinder16* ca, Cylinder16* cb, f32* deadSpace) { f32 xzDist; - Math3D_CylinderOutCylinderDist(ca, cb, deadSpace, &xzDist); + return Math3D_CylOutsideCylDist(ca, cb, deadSpace, &xzDist); } /* @@ -1583,7 +2065,7 @@ s32 Math3D_CylinderOutCylinder(Cylinder16* ca, Cylinder16* cb, f32* deadSpace) { * Sets `xzDist` to the xz distance between the centers of the cylinders. * Sets `deadSpace` to the mininum space between the cylinders not occupied by the other. */ -s32 Math3D_CylinderOutCylinderDist(Cylinder16* ca, Cylinder16* cb, f32* deadSpace, f32* xzDist) { +s32 Math3D_CylOutsideCylDist(Cylinder16* ca, Cylinder16* cb, f32* deadSpace, f32* xzDist) { static Cylinderf caf; static Cylinderf cbf; @@ -1601,17 +2083,17 @@ s32 Math3D_CylinderOutCylinderDist(Cylinder16* ca, Cylinder16* cb, f32* deadSpac // The combined radix are within the xz distance if ((caf.radius + cbf.radius) < *xzDist) { - return 0; + return false; } // top of ca < bottom of cb or top of cb < bottom of ca if (((caf.pos.y + caf.yShift) + caf.height) < (cbf.pos.y + cbf.yShift) || (((cbf.pos.y + cbf.yShift) + cbf.height) < (caf.pos.y + caf.yShift))) { - return 0; + return false; } *deadSpace = caf.radius + cbf.radius - *xzDist; - return 1; + return true; } /* @@ -1620,7 +2102,7 @@ s32 Math3D_CylinderOutCylinderDist(Cylinder16* ca, Cylinder16* cb, f32* deadSpac * Returns 1 is the triangles intersect, 0 otherwise */ -s32 Math3D_TrisIntersect(TriNorm* ta, TriNorm* tb, Vec3f* intersect) { +s32 Math3D_TriVsTriIntersect(TriNorm* ta, TriNorm* tb, Vec3f* intersect) { f32 dist0; f32 dist1; f32 dist2; @@ -1631,7 +2113,7 @@ s32 Math3D_TrisIntersect(TriNorm* ta, TriNorm* tb, Vec3f* intersect) { if (((dist0 > 0.0f) && (dist1 > 0.0f) && (dist2 > 0.0f)) || (((dist0 < 0.0f) && (dist1 < 0.0f)) && (dist2 < 0.0f))) { - return 0; + return false; } dist0 = Math3D_Plane(&tb->plane, &ta->vtx[0]); @@ -1640,77 +2122,77 @@ s32 Math3D_TrisIntersect(TriNorm* ta, TriNorm* tb, Vec3f* intersect) { if ((((dist0 > 0.0f) && (dist1 > 0.0f)) && (dist2 > 0.0f)) || ((dist0 < 0.0f) && (dist1 < 0.0f) && (dist2 < 0.0f))) { - return 0; + return false; } if (Math3D_TriLineIntersect(&tb->vtx[0], &tb->vtx[1], &tb->vtx[2], tb->plane.normal.x, tb->plane.normal.y, tb->plane.normal.z, tb->plane.originDist, &ta->vtx[0], &ta->vtx[1], intersect, 0)) { - return 1; + return true; } if (Math3D_TriLineIntersect(&tb->vtx[0], &tb->vtx[1], &tb->vtx[2], tb->plane.normal.x, tb->plane.normal.y, tb->plane.normal.z, tb->plane.originDist, &ta->vtx[1], &ta->vtx[2], intersect, 0)) { - return 1; + return true; } if (Math3D_TriLineIntersect(&tb->vtx[0], &tb->vtx[1], &tb->vtx[2], tb->plane.normal.x, tb->plane.normal.y, tb->plane.normal.z, tb->plane.originDist, &ta->vtx[2], &ta->vtx[0], intersect, 0)) { - return 1; + return true; } if (Math3D_TriLineIntersect(&ta->vtx[0], &ta->vtx[1], &ta->vtx[2], ta->plane.normal.x, ta->plane.normal.y, ta->plane.normal.z, ta->plane.originDist, &tb->vtx[0], &tb->vtx[1], intersect, 0) == 1) { - return 1; + return true; } if (Math3D_TriLineIntersect(&ta->vtx[0], &ta->vtx[1], &ta->vtx[2], ta->plane.normal.x, ta->plane.normal.y, ta->plane.normal.z, ta->plane.originDist, &tb->vtx[1], &tb->vtx[2], intersect, 0) == 1) { - return 1; + return true; } if (Math3D_TriLineIntersect(&ta->vtx[0], &ta->vtx[1], &ta->vtx[2], ta->plane.normal.x, ta->plane.normal.y, ta->plane.normal.z, ta->plane.originDist, &tb->vtx[2], &tb->vtx[0], intersect, 0) == 1) { - return 1; + return true; } - return 0; + return false; } -s32 func_800D0480(Sphere16* arg0, f32 arg1, f32 arg2) { - f32 temp_f0; - f32 temp_f2; +s32 Math3D_XZInSphere(Sphere16* sphere, f32 x, f32 z) { + f32 xDiff; + f32 zDiff; - temp_f0 = arg0->center.x - arg1; - temp_f2 = arg0->center.z - arg2; - if ((SQ(temp_f0) + SQ(temp_f2)) <= SQ(arg0->radius)) { - return 1; + xDiff = sphere->center.x - x; + zDiff = sphere->center.z - z; + if ((SQ(xDiff) + SQ(zDiff)) <= SQ(sphere->radius)) { + return true; } - return 0; + return false; } -s32 func_800D04F0(Sphere16* arg0, f32 arg1, f32 arg2) { - f32 temp_f0; - f32 temp_f2; +s32 Math3D_XYInSphere(Sphere16* sphere, f32 x, f32 y) { + f32 xDiff; + f32 yDiff; - temp_f0 = arg0->center.x - arg1; - temp_f2 = arg0->center.y - arg2; - if ((SQ(temp_f0) + SQ(temp_f2)) <= SQ(arg0->radius)) { - return 1; + xDiff = sphere->center.x - x; + yDiff = sphere->center.y - y; + if ((SQ(xDiff) + SQ(yDiff)) <= SQ(sphere->radius)) { + return true; } - return 0; + return false; } -s32 func_800D0560(Sphere16* arg0, f32 arg1, f32 arg2) { - f32 temp_f0; - f32 temp_f2; +s32 Math3D_YZInSphere(Sphere16* sphere, f32 y, f32 z) { + f32 yDiff; + f32 zDiff; - temp_f0 = arg0->center.y - arg1; - temp_f2 = arg0->center.z - arg2; - if ((SQ(temp_f0) + SQ(temp_f2)) <= SQ(arg0->radius)) { - return 1; + yDiff = sphere->center.y - y; + zDiff = sphere->center.z - z; + if ((SQ(yDiff) + SQ(zDiff)) <= SQ(sphere->radius)) { + return true; } - return 0; + return false; } -void func_800D05D0(GlobalContext* gctx, Sphere16* sph) { +void Math3D_DrawSphere(GlobalContext* globalCtx, Sphere16* sph) { } -void func_800D05DC(GlobalContext* gctx, Cylinder16* cyl) { +void Math3D_DrawCylinder(GlobalContext* globalCtx, Cylinder16* cyl) { } |
