Clean up gotos from find_wall_collisions_from_list (#288)

This commit is contained in:
Arceveti
2022-07-22 06:58:17 -07:00
committed by GitHub
parent a3e831d160
commit 3149239b9a

View File

@@ -14,18 +14,36 @@
* WALLS *
**************************************************/
#define CALC_OFFSET(vert, next_step) { \
if (FLT_IS_NONZERO((vert)[1])) { \
v = (v2[1] / (vert)[1]); \
if ((v < 0.0f) || (v > 1.0f)) next_step;\
d00 = (((vert)[0] * v) - v2[0]); \
d01 = (((vert)[2] * v) - v2[2]); \
invDenom = sqrtf(sqr(d00) + sqr(d01)); \
offset = (invDenom - margin_radius); \
if (offset > 0.0f) next_step; \
goto check_collision; \
} \
next_step; \
static s32 check_wall_vw(f32 d00, f32 d01, f32 d11, f32 d20, f32 d21, f32 invDenom) {
f32 v = ((d11 * d20) - (d01 * d21)) * invDenom;
if (v < 0.0f || v > 1.0f) {
return TRUE;
}
f32 w = ((d00 * d21) - (d01 * d20)) * invDenom;
if (w < 0.0f || w > 1.0f || v + w > 1.0f) {
return TRUE;
}
return FALSE;
}
s32 check_wall_edge(Vec3f vert, Vec3f v2, f32 *d00, f32 *d01, f32 *invDenom, f32 *offset, f32 margin_radius) {
if (FLT_IS_NONZERO(vert[1])) {
f32 v = (v2[1] / vert[1]);
if (v < 0.0f || v > 1.0f) {
return TRUE;
}
*d00 = ((vert[0] * v) - v2[0]);
*d01 = ((vert[2] * v) - v2[2]);
*invDenom = sqrtf(sqr(*d00) + sqr(*d01));
*offset = (*invDenom - margin_radius);
return (*offset > 0.0f);
}
return TRUE;
}
/**
@@ -34,16 +52,15 @@
*/
static s32 find_wall_collisions_from_list(struct SurfaceNode *surfaceNode, struct WallCollisionData *data) {
const f32 corner_threshold = -0.9f;
register struct Surface *surf;
register f32 offset;
register f32 radius = data->radius;
struct Surface *surf;
f32 offset;
f32 radius = data->radius;
Vec3f pos = { data->x, data->y + data->offsetY, data->z };
Vec3f v0, v1, v2;
register f32 d00, d01, d11, d20, d21;
register f32 invDenom;
register f32 v, w;
register TerrainData type = SURFACE_DEFAULT;
f32 d00, d01, d11, d20, d21;
f32 invDenom;
TerrainData type = SURFACE_DEFAULT;
s32 numCols = 0;
// Max collision radius = 200
@@ -79,11 +96,14 @@ static s32 find_wall_collisions_from_list(struct SurfaceNode *surfaceNode, struc
}
// Dot of normal and pos, + origin offset
offset = (surf->normal.x * pos[0]) + (surf->normal.y * pos[1]) + (surf->normal.z * pos[2]) + surf->originOffset;
offset = (surf->normal.x * pos[0])
+ (surf->normal.y * pos[1])
+ (surf->normal.z * pos[2])
+ surf->originOffset;
// Exclude surfaces outside of the radius.
if (offset < -radius || offset > radius) continue;
vec3_diff(v0, surf->vertex2, surf->vertex1);
vec3_diff(v1, surf->vertex3, surf->vertex1);
vec3_diff(v2, pos, surf->vertex1);
@@ -96,38 +116,48 @@ static s32 find_wall_collisions_from_list(struct SurfaceNode *surfaceNode, struc
d21 = vec3_dot(v2, v1);
invDenom = (d00 * d11) - (d01 * d01);
if (FLT_IS_NONZERO(invDenom)) invDenom = 1.0f / invDenom;
if (FLT_IS_NONZERO(invDenom)) {
invDenom = 1.0f / invDenom;
}
v = ((d11 * d20) - (d01 * d21)) * invDenom;
if (v < 0.0f || v > 1.0f) goto edge_1_2;
if (check_wall_vw(d00, d01, d11, d20, d21, invDenom)) {
if (offset < 0) {
continue;
}
w = ((d00 * d21) - (d01 * d20)) * invDenom;
if (w < 0.0f || w > 1.0f || v + w > 1.0f) goto edge_1_2;
// Edge 1-2
if (check_wall_edge(v0, v2, &d00, &d01, &invDenom, &offset, margin_radius)) {
// Edge 1-3
if (check_wall_edge(v1, v2, &d00, &d01, &invDenom, &offset, margin_radius)) {
vec3_diff(v1, surf->vertex3, surf->vertex2);
vec3_diff(v2, pos, surf->vertex2);
// Edge 2-3
if (check_wall_edge(v1, v2, &d00, &d01, &invDenom, &offset, margin_radius)) {
continue;
}
}
}
pos[0] += surf->normal.x * (radius - offset);
pos[2] += surf->normal.z * (radius - offset);
goto hasCollision;
// Check collision
if (FLT_IS_NONZERO(invDenom)) {
invDenom = (offset / invDenom);
}
edge_1_2:
if (offset < 0) continue;
CALC_OFFSET(v0, goto edge_1_3);
// Update pos
pos[0] += (d00 *= invDenom);
pos[2] += (d01 *= invDenom);
margin_radius += 0.01f;
edge_1_3:
CALC_OFFSET(v1, goto edge_2_3);
if ((d00 * surf->normal.x) + (d01 * surf->normal.z) < (corner_threshold * offset)) {
continue;
}
} else {
// Update pos
pos[0] += surf->normal.x * (radius - offset);
pos[2] += surf->normal.z * (radius - offset);
}
edge_2_3:
vec3_diff(v1, surf->vertex3, surf->vertex2);
vec3_diff(v2, pos, surf->vertex2);
CALC_OFFSET(v1, continue);
check_collision:
if (FLT_IS_NONZERO(invDenom)) invDenom = (offset / invDenom);
pos[0] += (d00 *= invDenom);
pos[2] += (d01 *= invDenom);
margin_radius += 0.01f;
if ((d00 * surf->normal.x) + (d01 * surf->normal.z) < (corner_threshold * offset)) continue;
hasCollision:
// Has collision
if (data->numWalls < MAX_REFERENCED_WALLS) {
data->walls[data->numWalls++] = surf;
}
@@ -137,11 +167,11 @@ static s32 find_wall_collisions_from_list(struct SurfaceNode *surfaceNode, struc
break;
}
}
data->x = pos[0];
data->z = pos[2];
return numCols;
}
#undef CALC_OFFSET
/**
* Formats the position and wall search for find_wall_collisions.