From 3149239b9a40ccf54690a08a26d3b113710c86ab Mon Sep 17 00:00:00 2001 From: Arceveti <73617174+Arceveti@users.noreply.github.com> Date: Fri, 22 Jul 2022 06:58:17 -0700 Subject: [PATCH] Clean up gotos from find_wall_collisions_from_list (#288) --- src/engine/surface_collision.c | 126 ++++++++++++++++++++------------- 1 file changed, 78 insertions(+), 48 deletions(-) diff --git a/src/engine/surface_collision.c b/src/engine/surface_collision.c index 73bb7034..9b428e03 100644 --- a/src/engine/surface_collision.c +++ b/src/engine/surface_collision.c @@ -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.