optimize collision detection

This commit is contained in:
Lephenixnoir 2023-04-29 12:16:41 +02:00
parent 9c0287fbc4
commit 0fd05c5aea
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
3 changed files with 26 additions and 11 deletions

View File

@ -155,6 +155,9 @@ struct game {
struct element_mirror *mirror;
struct element_plane *plane;
struct element_text *text;
/* A dynamic plane y value; mostly redundant from plane->y, used to optimize
away some checks during collisions with the plane */
num plane_collision[2];
/* Distance traversed within the current level */
num depth;

View File

@ -459,6 +459,19 @@ int game_update(struct game *g, bool *debug)
game_next_level_or_menu(g);
}
// Pre-compute plane collision info
num pc = g->plane ? g->plane->y - g->depth : num(0x7fff);
if(g->plane->type == ELEMENT_PLANE_INVIS) {
g->plane_collision[0] = num(0x7fff);
g->plane_collision[1] = pc;
}
else {
g->plane_collision[0] = pc;
g->plane_collision[1] = pc;
}
return 0;
}
@ -504,6 +517,8 @@ int main(void)
g.blank_frames = 0;
g.neon_position = 0;
g.neon_period = 64;
g.plane_collision[0] = num(0x7fff);
g.plane_collision[1] = num(0x7fff);
game_load_menu(&g);
game = &g;

View File

@ -79,16 +79,16 @@ static int cast_ray(struct game const *g, svec3 const &origin,
if(hitz && (!hitx || (tz_rx_rz < tx_rx_rz) ^ rx_rz_sign)) {
if(hitz == TOP)
*t = num16::div_positive(num16(WORLD_SIZE) - origin.z, rayDir.z);
*t = (num16(WORLD_SIZE) - origin.z) / rayDir.z;
else
*t = num16::div_positive(origin.z + num16(WORLD_SIZE), -rayDir.z);
*t = (origin.z + num16(WORLD_SIZE)) / -rayDir.z;
hit = hitz;
}
else if(__builtin_expect(hitx, 1)) {
if(hitx == RIGHT)
*t = num16::div_positive(num16(WORLD_SIZE) - origin.x, rayDir.x);
*t = (num16(WORLD_SIZE) - origin.x) / rayDir.x;
else
*t = num16::div_positive(origin.x + num16(WORLD_SIZE), -rayDir.x);
*t = (origin.x + num16(WORLD_SIZE)) / -rayDir.x;
hit = hitx;
}
@ -101,19 +101,16 @@ static int cast_ray(struct game const *g, svec3 const &origin,
/* Determine if there is an intersection with the object plane */
if(__builtin_expect(
g->plane
&& (*collision_y > g->plane->y - g->depth)
&& (g->plane->type != ELEMENT_PLANE_INVIS || secondary),
0)) {
num16 plane_y = num16(g->plane->y - g->depth);
num pc = g->plane_collision[secondary];
if(__builtin_expect(*collision_y > pc, 0)) {
num16 plane_y = num16(pc);
num16 plane_t = (plane_y - origin.y) / rayDir.y;
num16 plane_x = origin.x + plane_t * rayDir.x;
num16 plane_z = origin.z + plane_t * rayDir.z;
if(level_plane_collides(plane_x, plane_z, g->plane->shape)) {
*t = plane_t;
*collision_y = g->plane->y - g->depth;
*collision_y = pc;
return OBJECT_PLANE;
}
}