River_Sound OK and Documented + River_Sound Related z_actor/Audio Functions (#661)

* First pass of `func_800BCCDC`

* river_sound OK (copy progress from audio WIP)

* Copy progress from `code_8019AF00.c` (still waiting for data to be imported)

* More docs

* feedback

* Add in `code_8019AF00.c` functions

* format

* params

* Minor cleanup

* Small fix

* one more

* Better names

* Add comment, cleanup Idx

* Fix bss

* Fix BSS
This commit is contained in:
engineer124
2022-03-28 01:42:19 +11:00
committed by GitHub
parent 9e230005b0
commit f1d1173558
14 changed files with 553 additions and 150 deletions
+122 -78
View File
@@ -3908,104 +3908,148 @@ Hilite* func_800BCC68(Vec3f* arg0, GlobalContext* globalCtx) {
return Hilite_DrawXlu(arg0, &globalCtx->view.eye, &lightDir, globalCtx->state.gfxCtx);
}
void func_800BCCDC(Vec3s* points, s32 pathCount, Vec3f* pos1, Vec3f* pos2, s32 arg4) {
s32 spB4;
s32 spB0;
s32 spA8[2] = { 0, 0 };
s32 spA0[2] = { 0, 0 };
Vec3f sp94;
Vec3f sp7C[2];
Vec3f sp70;
Vec3f sp64;
f32 sp60;
f32 sp5C;
f32 sp54[2];
/**
* Calculates the closest position `dstPos` to the input position `srcPos` along the path given by `points`/`numPoints`
* Whether the points provided forms a closed-loop path is indicated by `isPathLoop`
*/
void Actor_GetClosestPosOnPath(Vec3s* points, s32 numPoints, Vec3f* srcPos, Vec3f* dstPos, s32 isPathLoop) {
s32 pointIndex;
s32 closestPointIndex;
s32 useAdjacentLines[2] = {
false, // determines whether to use line connecting to previous point in calculations
false, // determines whether to use line connecting to next point in calculations
};
s32 isRightSideOfAdjacentLines[2] = {
false, // determines whether srcPos is on the right side of the line from prev to curr point
false, // determines whether srcPos is on the right side of the line from curr to next point
};
Vec3f closestPoint;
Vec3f closestPos[2];
Vec3f closestPointNext;
Vec3f closestPointPrev;
f32 distSq; // First used as distSq to closest point, then used as distSq to closest position
f32 closestPointDistSq;
f32 loopDistSq[2];
s32 i;
spB0 = 0;
sp5C = SQ(40000.0f);
closestPointIndex = 0;
closestPointDistSq = SQ(40000.0f);
for (spB4 = 0; spB4 < pathCount; spB4++) {
sp60 = Math3D_XZDistanceSquared(pos1->x, pos1->z, points[spB4].x, points[spB4].z);
if (sp60 < sp5C) {
sp5C = sp60;
spB0 = spB4;
// Find the point closest to srcPos
for (pointIndex = 0; pointIndex < numPoints; pointIndex++) {
distSq = Math3D_XZDistanceSquared(srcPos->x, srcPos->z, points[pointIndex].x, points[pointIndex].z);
if (distSq < closestPointDistSq) {
closestPointDistSq = distSq;
closestPointIndex = pointIndex;
}
}
sp94.x = (points + spB0)->x;
sp94.z = (points + spB0)->z;
pos2->y = (points + spB0)->y;
if (spB0 != 0) {
sp64.x = (points + spB0 - 1)->x;
sp64.z = (points + spB0 - 1)->z;
} else if (arg4) {
sp64.x = (points + pathCount - 1)->x;
sp64.z = (points + pathCount - 1)->z;
closestPoint.x = (points + closestPointIndex)->x;
closestPoint.z = (points + closestPointIndex)->z;
dstPos->y = (points + closestPointIndex)->y;
// Analyze point on path immediately previous to the closest point
if (closestPointIndex != 0) {
// The point previous to the closest point
closestPointPrev.x = (points + closestPointIndex - 1)->x;
closestPointPrev.z = (points + closestPointIndex - 1)->z;
} else if (isPathLoop) {
// Closest point is the first point in the path list
// Set the previous point to loop around to the the final point on the path
closestPointPrev.x = (points + numPoints - 1)->x;
closestPointPrev.z = (points + numPoints - 1)->z;
}
if ((closestPointIndex != 0) || isPathLoop) {
// Use the adjacent line
useAdjacentLines[0] =
Math3D_PointDistToLine2D(srcPos->x, srcPos->z, closestPointPrev.x, closestPointPrev.z, closestPoint.x,
closestPoint.z, &closestPos[0].x, &closestPos[0].z, &distSq);
}
if ((spB0 != 0) || arg4) {
spA8[0] =
Math3D_PointDistToLine2D(pos1->x, pos1->z, sp64.x, sp64.z, sp94.x, sp94.z, &sp7C[0].x, &sp7C[0].z, &sp60);
// Analyze point on path immediately next to the closest point
if (closestPointIndex + 1 != numPoints) {
// The point next to the closest point
closestPointNext.x = (points + closestPointIndex + 1)->x;
closestPointNext.z = (points + closestPointIndex + 1)->z;
} else if (isPathLoop) {
// Closest point is the final point in the path list
// Set the next point to loop around to the the first point on the path
closestPointNext.x = (points + 0)->x;
closestPointNext.z = (points + 0)->z;
}
if ((closestPointIndex + 1 != numPoints) || isPathLoop) {
useAdjacentLines[1] =
Math3D_PointDistToLine2D(srcPos->x, srcPos->z, closestPoint.x, closestPoint.z, closestPointNext.x,
closestPointNext.z, &closestPos[1].x, &closestPos[1].z, &distSq);
}
if (spB0 + 1 != pathCount) {
sp70.x = (points + spB0 + 1)->x;
sp70.z = (points + spB0 + 1)->z;
} else if (arg4) {
sp70.x = points->x;
sp70.z = points->z;
}
/**
* For close-looped paths, they must be defined in a clockwise orientation looking from the top down.
* Therefore, `srcPos` being interior of the loop will lead to both lines of `isRightSideOfAdjacentLines`
* returning true.
*/
if (isPathLoop) {
isRightSideOfAdjacentLines[0] = ((closestPointPrev.x - srcPos->x) * (closestPoint.z - srcPos->z)) <
((closestPointPrev.z - srcPos->z) * (closestPoint.x - srcPos->x));
if ((spB0 + 1 != pathCount) || arg4) {
spA8[1] =
Math3D_PointDistToLine2D(pos1->x, pos1->z, sp94.x, sp94.z, sp70.x, sp70.z, &sp7C[1].x, &sp7C[1].z, &sp60);
}
isRightSideOfAdjacentLines[1] = ((closestPointNext.z - srcPos->z) * (closestPoint.x - srcPos->x)) <
((closestPoint.z - srcPos->z) * (closestPointNext.x - srcPos->x));
if (arg4) {
s32 phi_s0_2;
spA0[0] = ((sp64.x - pos1->x) * (sp94.z - pos1->z)) < ((sp64.z - pos1->z) * (sp94.x - pos1->x));
spA0[1] = ((sp70.z - pos1->z) * (sp94.x - pos1->x)) < ((sp94.z - pos1->z) * (sp70.x - pos1->x));
for (phi_s0_2 = 0; phi_s0_2 < ARRAY_COUNT(sp54); phi_s0_2++) {
if (spA8[phi_s0_2] != 0) {
sp54[phi_s0_2] = Math3D_XZDistanceSquared(pos1->x, pos1->z, sp7C[phi_s0_2].x, sp7C[phi_s0_2].z);
for (i = 0; i < ARRAY_COUNT(loopDistSq); i++) {
if (useAdjacentLines[i]) {
// Get distSq from srcPos to closestPos
loopDistSq[i] = Math3D_XZDistanceSquared(srcPos->x, srcPos->z, closestPos[i].x, closestPos[i].z);
} else {
sp54[phi_s0_2] = SQ(40000.0f);
// The closest Pos is not contained within the line-segment
loopDistSq[i] = SQ(40000.0f);
}
}
}
if (arg4 && (((spA0[0] != 0) && (spA0[1] != 0)) || ((spA0[0] != 0) && (spA8[0] != 0) && (sp54[0] < sp54[1])) ||
((spA0[1] != 0) && (spA8[1] != 0) && (sp54[1] < sp54[0])))) {
pos2->x = pos1->x;
pos2->z = pos1->z;
} else if ((spA8[0] != 0) && (spA8[1] != 0)) {
if ((spA0[0] == 0) && (spA0[1] == 0)) {
if (Math3D_PointDistToLine2D(pos1->x, pos1->z, sp7C[0].x, sp7C[0].z, sp7C[1].x, sp7C[1].z, &pos2->x,
&pos2->z, &sp60) == 0) {
pos2->x = (sp7C[1].x + sp7C[0].x) * 0.5f;
pos2->z = (sp7C[1].z + sp7C[0].z) * 0.5f;
// Calculate closest position along path
if (isPathLoop && ((isRightSideOfAdjacentLines[0] && isRightSideOfAdjacentLines[1]) ||
(isRightSideOfAdjacentLines[0] && useAdjacentLines[0] && (loopDistSq[0] < loopDistSq[1])) ||
(isRightSideOfAdjacentLines[1] && useAdjacentLines[1] && (loopDistSq[1] < loopDistSq[0])))) {
// srcPos is contained within the closed loop
dstPos->x = srcPos->x;
dstPos->z = srcPos->z;
} else if (useAdjacentLines[0] && useAdjacentLines[1]) {
// srcPos is somewhere withing the bend of the path
if (!isRightSideOfAdjacentLines[0] && !isRightSideOfAdjacentLines[1]) {
// srcPos is not inside a loop
if (!Math3D_PointDistToLine2D(srcPos->x, srcPos->z, closestPos[0].x, closestPos[0].z, closestPos[1].x,
closestPos[1].z, &dstPos->x, &dstPos->z, &distSq)) {
// The dstPos calculated in Math3D_PointDistToLine2D was not valid.
// Take the midpoint of the two closest ponits instead
dstPos->x = (closestPos[1].x + closestPos[0].x) * 0.5f;
dstPos->z = (closestPos[1].z + closestPos[0].z) * 0.5f;
}
} else if (sp54[1] < sp54[0]) {
pos2->x = sp7C[1].x;
pos2->z = sp7C[1].z;
} else if (loopDistSq[1] < loopDistSq[0]) {
// Use closest position along the line in the loop connecting the closest point and the next point
dstPos->x = closestPos[1].x;
dstPos->z = closestPos[1].z;
} else {
pos2->x = sp7C[0].x;
pos2->z = sp7C[0].z;
// Use closest position along the ling in the loop connecting the closest point and the prev point
dstPos->x = closestPos[0].x;
dstPos->z = closestPos[0].z;
}
} else if (spA8[0] != 0) {
pos2->x = sp7C[0].x;
pos2->z = sp7C[0].z;
} else if (spA8[1] != 0) {
pos2->x = sp7C[1].x;
pos2->z = sp7C[1].z;
} else if (arg4 && ((((sp64.x - pos1->x) * (sp70.z - pos1->z)) < ((sp64.z - pos1->z) * (sp70.x - pos1->x))))) {
pos2->x = pos1->x;
pos2->z = pos1->z;
} else if (useAdjacentLines[0]) {
// Use closest position along line segment connecting the closest point and the prev point
dstPos->x = closestPos[0].x;
dstPos->z = closestPos[0].z;
} else if (useAdjacentLines[1]) {
// Use closest position along line segment connecting the closest point and the next point
dstPos->x = closestPos[1].x;
dstPos->z = closestPos[1].z;
} else if (isPathLoop && ((((closestPointPrev.x - srcPos->x) * (closestPointNext.z - srcPos->z)) <
((closestPointPrev.z - srcPos->z) * (closestPointNext.x - srcPos->x))))) {
// Inside the line that directly connects the previous point to the next point (inside the bend of a corner)
dstPos->x = srcPos->x;
dstPos->z = srcPos->z;
} else {
pos2->x = sp94.x;
pos2->z = sp94.z;
// The closest point and the closest position are the same (srcPos is near the outer region of a corner)
dstPos->x = closestPoint.x;
dstPos->z = closestPoint.z;
}
}