From 62173526c401936dd5f8362762c60b70649908bf Mon Sep 17 00:00:00 2001 From: Phillip Trudeau-Tavara Date: Tue, 22 Aug 2023 08:15:47 -0400 Subject: [PATCH] Replace AABB collisions with cylinders --- main.c | 87 ++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 29 deletions(-) diff --git a/main.c b/main.c index ad05c1b..4d9df49 100644 --- a/main.c +++ b/main.c @@ -289,6 +289,12 @@ typedef struct AABB Vec2 lower_right; } AABB; +typedef struct Circle +{ + Vec2 center; + float radius; +} Circle; + typedef struct Quad { union @@ -713,6 +719,23 @@ Vec2 entity_aabb_size(Entity *e) } } +float entity_radius(Entity *e) +{ + if (e->is_character) + { + return 0.35f; + } + else if (e->is_npc) + { + return 0.5f; + } + else + { + assert(false); + return 0; + } +} + Vec2 rotate_counter_clockwise(Vec2 v) { return V2(-v.Y, v.X); @@ -1237,17 +1260,17 @@ Armature load_armature(MD_Arena *arena, MD_String8 binary_file, MD_String8 armat return to_return; } -typedef struct CollisionCube +typedef struct CollisionCylinder { - struct CollisionCube *next; - AABB bounds; -} CollisionCube; + struct CollisionCylinder *next; + Circle bounds; +} CollisionCylinder; typedef struct { Mesh *mesh_list; PlacedMesh *placed_mesh_list; - CollisionCube *collision_list; + CollisionCylinder *collision_list; PlacedEntity *placed_entity_list; } ThreeDeeLevel; @@ -1350,13 +1373,14 @@ ThreeDeeLevel load_level(MD_Arena *arena, MD_String8 binary_file) ser_MD_u64(&ser, &num_collision_cubes); for(MD_u64 i = 0; i < num_collision_cubes; i++) { - CollisionCube *new_cube = MD_PushArray(arena, CollisionCube, 1); + CollisionCylinder *new_cylinder = MD_PushArray(arena, CollisionCylinder, 1); Vec2 twodee_pos; Vec2 size; ser_Vec2(&ser, &twodee_pos); ser_Vec2(&ser, &size); - new_cube->bounds = aabb_centered(twodee_pos, size); - MD_StackPush(out.collision_list, new_cube); + new_cylinder->bounds.center = twodee_pos; + new_cylinder->bounds.radius = (size.x + size.y) * 0.5f; // @TODO(Phillip): @Temporary + MD_StackPush(out.collision_list, new_cylinder); } // placed entities @@ -3651,6 +3675,13 @@ bool overlapping(AABB a, AABB b) return true; // both segments overlapping } +bool overlapping_circle(Circle a, Circle b) +{ + Vec2 disp = SubV2(b.center, a.center); + float dist = LenV2(disp); + return (dist < a.radius + b.radius); +} + bool has_point(AABB aabb, Vec2 point) { return @@ -4370,21 +4401,20 @@ Vec2 get_penetration_vector(AABB stable, AABB dynamic) // returns new pos after moving and sliding against collidable things Vec2 move_and_slide(MoveSlideParams p) { - Vec2 collision_aabb_size = entity_aabb_size(p.from); + float collision_radius = entity_radius(p.from); Vec2 new_pos = AddV2(p.position, p.movement_this_frame); - assert(collision_aabb_size.x > 0.0f); - assert(collision_aabb_size.y > 0.0f); - AABB at_new = aabb_centered(new_pos, collision_aabb_size); + assert(collision_radius > 0.0f); + Circle at_new = {new_pos, collision_radius}; typedef struct { - AABB aabb; + Circle circle; Entity *e; // required } CollisionObj; BUFF(CollisionObj, 256) to_check = { 0 }; // add world boxes - for(CollisionCube *cur = level_threedee.collision_list; cur; cur = cur->next) + for(CollisionCylinder *cur = level_threedee.collision_list; cur; cur = cur->next) { BUFF_APPEND(&to_check, ((CollisionObj){cur->bounds, gs.world_entity})); } @@ -4396,7 +4426,7 @@ Vec2 move_and_slide(MoveSlideParams p) { if (it != p.from && !(it->is_npc && it->dead) && !it->is_world) { - BUFF_APPEND(&to_check, ((CollisionObj){aabb_centered(it->pos, entity_aabb_size(it)), it})); + BUFF_APPEND(&to_check, ((CollisionObj){.circle.center = it->pos, .circle.radius = entity_radius(it), it})); } } } @@ -4410,7 +4440,7 @@ Vec2 move_and_slide(MoveSlideParams p) BUFF_ITER(CollisionObj, &to_check) { - if (overlapping(at_new, it->aabb)) + if (overlapping_circle(at_new, it->circle)) { BUFF_APPEND(&actually_overlapping, *it); } @@ -4418,14 +4448,14 @@ Vec2 move_and_slide(MoveSlideParams p) float smallest_distance = FLT_MAX; - int smallest_aabb_index = 0; + int smallest_circle_index = 0; int i = 0; BUFF_ITER(CollisionObj, &actually_overlapping) { - float cur_dist = LenV2(SubV2(aabb_center(at_new), aabb_center(it->aabb))); + float cur_dist = LenV2(SubV2(at_new.center, it->circle.center)); if (cur_dist < smallest_distance) { smallest_distance = cur_dist; - smallest_aabb_index = i; + smallest_circle_index = i; } i++; } @@ -4434,11 +4464,11 @@ Vec2 move_and_slide(MoveSlideParams p) OverlapBuff overlapping_smallest_first = { 0 }; if (actually_overlapping.cur_index > 0) { - BUFF_APPEND(&overlapping_smallest_first, actually_overlapping.data[smallest_aabb_index]); + BUFF_APPEND(&overlapping_smallest_first, actually_overlapping.data[smallest_circle_index]); } BUFF_ITER_I(CollisionObj, &actually_overlapping, i) { - if (i == smallest_aabb_index) + if (i == smallest_circle_index) { } else @@ -4452,7 +4482,7 @@ Vec2 move_and_slide(MoveSlideParams p) { dbgcol(GREEN) { - dbgplanerect(it->aabb); + dbgplanerect(aabb_centered(it->circle.center, (Vec2){it->circle.radius, it->circle.radius})); } } @@ -4461,21 +4491,20 @@ Vec2 move_and_slide(MoveSlideParams p) BUFF_ITER(CollisionObj, &actually_overlapping) dbgcol(WHITE) - dbgplanerect(it->aabb); + dbgplanerect(aabb_centered(it->circle.center, (Vec2){it->circle.radius, it->circle.radius})); BUFF_ITER(CollisionObj, &overlapping_smallest_first) dbgcol(WHITE) - dbgplanesquare(aabb_center(it->aabb)); + dbgplanesquare(it->circle.center); CollisionInfo info = { 0 }; for (int col_iter_i = 0; col_iter_i < 1; col_iter_i++) BUFF_ITER(CollisionObj, &overlapping_smallest_first) { - AABB to_depenetrate_from = it->aabb; + Circle to_depenetrate_from = it->circle; - Vec2 resolution_vector = get_penetration_vector(to_depenetrate_from, at_new); - at_new.upper_left = AddV2(at_new.upper_left , resolution_vector); - at_new.lower_right = AddV2(at_new.lower_right, resolution_vector); + Vec2 resolution_vector = NozV2(SubV2(at_new.center, to_depenetrate_from.center)); + at_new.center = AddV2(to_depenetrate_from.center, MulV2F(resolution_vector, to_depenetrate_from.radius + at_new.radius)); bool happened_with_this_one = true; if(happened_with_this_one) @@ -4508,7 +4537,7 @@ Vec2 move_and_slide(MoveSlideParams p) if (p.col_info_out) *p.col_info_out = info; - Vec2 result_pos = aabb_center(at_new); + Vec2 result_pos = at_new.center; return result_pos; }