From 3d863022fb5ae52f3b031b6612df852a9df6327c Mon Sep 17 00:00:00 2001 From: jacob Date: Wed, 30 Jul 2025 17:31:14 -0500 Subject: [PATCH] collider layer refactor --- src/app/app_core.c | 2 +- src/ase/ase_core.h | 167 ++++++++++--------- src/base/base_math.h | 6 +- src/bitbuff/bitbuff_core.c | 16 +- src/bitbuff/bitbuff_core.h | 12 +- src/collider/collider_core.c | 300 +++++++++++++++-------------------- src/collider/collider_core.h | 172 +++++++++++++++++--- src/config.h | 4 +- src/draw/draw_core.c | 20 +-- src/draw/draw_core.h | 6 +- src/gp/gp_core.h | 2 +- src/sim/sim_phys.c | 16 +- src/sim/sim_phys.h | 2 +- src/sim/sim_space.c | 2 +- src/sim/sim_step.c | 10 +- src/user/user_core.c | 22 +-- 16 files changed, 418 insertions(+), 341 deletions(-) diff --git a/src/app/app_core.c b/src/app/app_core.c index 2d149b3a..d2a935fe 100644 --- a/src/app/app_core.c +++ b/src/app/app_core.c @@ -160,7 +160,7 @@ void P_AppStartup(String args_str) #if !RtcIsEnabled /* Verify test modes aren't left on by accident in release mode */ - StaticAssert(BB_DebugIsEnabled == 0); + StaticAssert(BITBUFF_DEBUG == 0); StaticAssert(BITBUFF_TEST == 0); #endif diff --git a/src/ase/ase_core.h b/src/ase/ase_core.h index 8d570762..07105a3e 100644 --- a/src/ase/ase_core.h +++ b/src/ase/ase_core.h @@ -1,3 +1,82 @@ +//////////////////////////////// +//~ Sheet types + +Struct(Ase_Slice) +{ + u32 start; + i32 x1; + i32 y1; + i32 x2; + i32 y2; + Ase_Slice *next; +}; + +Struct(Ase_SliceKey) +{ + String name; + u32 num_slices; + Ase_Slice *slice_head; + Ase_SliceKey *next; +}; + +Struct(Ase_Span) +{ + String name; + u32 start; + u32 end; + Ase_Span *next; +}; + +Struct(Ase_Frame) +{ + u32 index; + u32 x1; + u32 y1; + u32 x2; + u32 y2; + f64 duration; + Ase_Frame *next; +}; + +//////////////////////////////// +//~ Decoder result types + +Struct(Ase_Error) +{ + String msg; + Ase_Error *next; +}; + +Struct(Ase_ErrorList) +{ + u64 count; + Ase_Error *first; + Ase_Error *last; +}; + +Struct(Ase_DecodedImage) +{ + u32 width; + u32 height; + u32 *pixels; /* Array of [width * height] pixels */ + Ase_ErrorList errors; + b32 success; +}; + +Struct(Ase_DecodedSheet) +{ + Vec2 image_size; + Vec2 frame_size; + u32 num_frames; + u32 num_spans; + u32 num_slice_keys; + Ase_Frame *frame_head; + Ase_Span *span_head; + Ase_SliceKey *slice_key_head; + Ase_ErrorList errors; + b32 success; +}; + //////////////////////////////// //~ Inflator types @@ -131,88 +210,6 @@ Struct(Ace_Cel) Ace_Cel *next; }; -//////////////////////////////// -//~ Error types - -Struct(Ase_Error) -{ - String msg; - Ase_Error *next; -}; - -Struct(Ase_ErrorList) -{ - u64 count; - Ase_Error *first; - Ase_Error *last; -}; - -//////////////////////////////// -//~ Sheet types - -Struct(Ase_Slice) -{ - u32 start; - i32 x1; - i32 y1; - i32 x2; - i32 y2; - Ase_Slice *next; -}; - -Struct(Ase_SliceKey) -{ - String name; - u32 num_slices; - Ase_Slice *slice_head; - Ase_SliceKey *next; -}; - -Struct(Ase_Span) -{ - String name; - u32 start; - u32 end; - Ase_Span *next; -}; - -Struct(Ase_Frame) -{ - u32 index; - u32 x1; - u32 y1; - u32 x2; - u32 y2; - f64 duration; - Ase_Frame *next; -}; - -//////////////////////////////// -//~ Decoder result types - -Struct(Ase_DecodedImage) -{ - u32 width; - u32 height; - u32 *pixels; /* Array of [width * height] pixels */ - Ase_ErrorList errors; - b32 success; -}; - -Struct(Ase_DecodedSheet) -{ - Vec2 image_size; - Vec2 frame_size; - u32 num_frames; - u32 num_spans; - u32 num_slice_keys; - Ase_Frame *frame_head; - Ase_Span *span_head; - Ase_SliceKey *slice_key_head; - Ase_ErrorList errors; - b32 success; -}; - //////////////////////////////// //~ Ase bitbuff operations @@ -231,12 +228,8 @@ void Ase_Inflate(u8 *dst, u8 *encoded); //////////////////////////////// //~ Error handling operations -void Ase_PushError(Arena *arena, Ase_ErrorList *list, String msg_src); - -//////////////////////////////// -//~ Decoder operations - //- Helpers +void Ase_PushError(Arena *arena, Ase_ErrorList *list, String msg_src); u32 Ase_BlendMulU8(u32 a, u32 b); u32 Ase_Blend(u32 src, u32 dst, u8 opacity); void Ase_MakeDimensionsSquareish(Ase_Header *header, u32 *frames_x, u32 *frames_y, u64 *image_width, u64 *image_height); diff --git a/src/base/base_math.h b/src/base/base_math.h index 36f40e01..5230c03b 100644 --- a/src/base/base_math.h +++ b/src/base/base_math.h @@ -10,7 +10,7 @@ Struct(Vec2) { f32 x, y; }; -Struct(V2Array) { +Struct(Vec2Array) { Vec2 *points; u64 count; }; @@ -22,7 +22,7 @@ Struct(Vec3) { f32 x, y, z; }; -Struct(V3Array) { +Struct(Vec3Array) { Vec3 *points; u64 count; }; @@ -34,7 +34,7 @@ Struct(Vec4) { f32 x, y, z, w; }; -Struct(V4Array) { +Struct(Vec4Array) { Vec4 *points; u64 count; }; diff --git a/src/bitbuff/bitbuff_core.c b/src/bitbuff/bitbuff_core.c index 3037c078..9a47cc8d 100644 --- a/src/bitbuff/bitbuff_core.c +++ b/src/bitbuff/bitbuff_core.c @@ -43,7 +43,7 @@ BB_Writer BB_WriterFromBuff(BB_Buff *bb) result.base = bb->fixed_buffer.text; } result.cur_bit = 0; -#if BB_DebugIsEnabled +#if BITBUFF_DEBUG result.debug_enabled = 1; #endif return result; @@ -53,7 +53,7 @@ BB_Writer BB_WriterFromBuff(BB_Buff *bb) BB_Writer BB_WriterFromBuffNoDebug(BB_Buff *bb) { BB_Writer result = BB_WriterFromBuff(bb); -#if BB_DebugIsEnabled +#if BITBUFF_DEBUG result.debug_enabled = 0; #endif return result; @@ -131,7 +131,7 @@ b32 BB_CheckWriterOverflowBits(BB_Writer *bw, u64 num_bits) /* Align the pos to the next byte */ void BB_AlignWriter(BB_Writer *bw) { -#if BB_DebugIsEnabled +#if BITBUFF_DEBUG if ((bw->cur_bit & 7) != 0) { BB_WriteDebugMagic(bw, BB_DebugMagicKind_Align, 0); @@ -317,7 +317,7 @@ void BB_WriteBytes(BB_Writer *bw, String bytes) //////////////////////////////// //~ Writer debug -#if BB_DebugIsEnabled +#if BITBUFF_DEBUG void BB_WriteDebugMarker(BB_Writer *bw, String name) { bw->cur_bit += (8 - (bw->cur_bit & 7)) & 7; @@ -359,7 +359,7 @@ BB_Reader BB_ReaderFromBuff(BB_Buff *bb) result.base_len = arena->pos; } result.cur_bit = 0; -#if BB_DebugIsEnabled +#if BITBUFF_DEBUG result.debug_enabled = 1; #endif return result; @@ -369,7 +369,7 @@ BB_Reader BB_ReaderFromBuff(BB_Buff *bb) BB_Reader BB_ReaderFromBuffNoDebug(BB_Buff *bb) { BB_Reader result = BB_ReaderFromBuff(bb); -#if BB_DebugIsEnabled +#if BITBUFF_DEBUG result.debug_enabled = 0; #endif return result; @@ -432,7 +432,7 @@ b32 BB_CheckReaderOverflowBits(BB_Reader *br, u64 num_bits) /* Align the pos to the next byte */ void BB_AlignReader(BB_Reader *br) { -#if BB_DebugIsEnabled +#if BITBUFF_DEBUG if ((br->cur_bit & 7) != 0) { BB_ReadDebugMagic(br, BB_DebugMagicKind_Align, 0); @@ -676,7 +676,7 @@ void BB_SeekToByte(BB_Reader *br, u64 pos) //////////////////////////////// //~ Reader debug -#if BB_DebugIsEnabled +#if BITBUFF_DEBUG void BB_ReadDebugMagic(BB_Reader *br, BB_DebugMagicKind expected_magic, u8 expected_num_bits) { diff --git a/src/bitbuff/bitbuff_core.h b/src/bitbuff/bitbuff_core.h index 671dd35f..4587d45e 100644 --- a/src/bitbuff/bitbuff_core.h +++ b/src/bitbuff/bitbuff_core.h @@ -1,8 +1,6 @@ //////////////////////////////// //~ Bitbuff types -#define BB_DebugIsEnabled DebugBitbuff - //- Buff Struct(BB_Buff) { @@ -24,7 +22,7 @@ Struct(BB_Writer) BB_Buff *bb; u8 *base; u64 cur_bit; -#if BB_DebugIsEnabled +#if BITBUFF_DEBUG b32 debug_enabled; #endif }; @@ -36,7 +34,7 @@ Struct(BB_Reader) u64 base_len; u8 *base; u64 cur_bit; -#if BB_DebugIsEnabled +#if BITBUFF_DEBUG b32 debug_enabled; #endif }; @@ -44,7 +42,7 @@ Struct(BB_Reader) //////////////////////////////// //~ Debug types -#if BB_DebugIsEnabled +#if BITBUFF_DEBUG /* Magic numbers inserted to verify read/write type & length */ typedef u32 BB_DebugMagicKind; enum @@ -114,7 +112,7 @@ void BB_WriteBytes(BB_Writer *bw, String bytes); //////////////////////////////// //~ Writer debug -#if BB_DebugIsEnabled +#if BITBUFF_DEBUG void BB_WriteDebugMagic(BB_Writer *bw, BB_DebugMagicKind magic, u8 num_bits); void BB_WriteDebugMarker(BB_Writer *bw, String name); #else @@ -169,7 +167,7 @@ void BB_SeekToByte(BB_Reader *br, u64 pos); //////////////////////////////// //~ Reader debug -#if BB_DebugIsEnabled +#if BITBUFF_DEBUG void BB_ReadDebugMagic(BB_Reader *br, BB_DebugMagicKind expected_magic, u8 expected_num_bits); void BB_ReadDebugMarker(BB_Reader *br, String name); #else diff --git a/src/collider/collider_core.c b/src/collider/collider_core.c index 8d406d36..e592c926 100644 --- a/src/collider/collider_core.c +++ b/src/collider/collider_core.c @@ -1,32 +1,34 @@ -/* How close can non-overlapping shapes be before collision is considered */ -#define COLLISION_TOLERANCE 0.005f - -/* NOTE: Should always be less than tolerance, since colliding = 1 if origin is within this distance. */ -#define MIN_UNIQUE_PT_DIST_SQ (0.001f * 0.001f) - -/* To prevent extremely large prototypes when origin is in exact center of rounded feature */ -#define MAX_EPA_ITERATIONS 64 +//////////////////////////////// +//~ Debug #if COLLIDER_DEBUG -internal void _dbgbreakable(void) +void CLD_DebugBreakable(void) { #if RtcIsEnabled DEBUGBREAKABLE; #endif } - -#define DBGSTEP \ - dbg_step++; \ - if (dbg_step >= GetGstat(GSTAT_DEBUG_STEPS)) { \ - goto abort; \ - } else if (dbg_step >= GetGstat(GSTAT_DEBUG_STEPS) - 1) { \ - _dbgbreakable(); \ - } (void)0 -#else -#define DBGSTEP #endif -internal CLD_SupportPoint collider_get_support_point_internal(CLD_Shape *shape, Xform xf, Vec2 dir, i32 ignore) +//////////////////////////////// +//~ Shape + +CLD_Shape CLD_ShapeFromQuad(Quad quad) +{ + CLD_Shape result; + result.points[0] = quad.p0; + result.points[1] = quad.p1; + result.points[2] = quad.p2; + result.points[3] = quad.p3; + result.count = 4; + result.radius = 0; + return result; +} + +//////////////////////////////// +//~ Menkowski support point + +CLD_SupportPoint CLD_SupportPointFromDirInternal(CLD_Shape *shape, Xform xf, Vec2 dir, i32 ignore) { Vec2 *points = shape->points; u32 count = shape->count; @@ -69,47 +71,34 @@ internal CLD_SupportPoint collider_get_support_point_internal(CLD_Shape *shape, return result; } -CLD_Shape collider_from_quad(Quad quad) +CLD_SupportPoint CLD_SupportPointFromDir(CLD_Shape *shape, Xform xf, Vec2 dir) { - CLD_Shape result; - result.points[0] = quad.p0; - result.points[1] = quad.p1; - result.points[2] = quad.p2; - result.points[3] = quad.p3; - result.count = 4; - result.radius = 0; - return result; + return CLD_SupportPointFromDirInternal(shape, xf, dir, -1); } -CLD_SupportPoint collider_get_support_point(CLD_Shape *shape, Xform xf, Vec2 dir) -{ - return collider_get_support_point_internal(shape, xf, dir, -1); -} - -internal CLD_MenkowskiPoint get_menkowski_point(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, Vec2 dir) +CLD_MenkowskiPoint CLD_MenkowskiPointFromDir(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, Vec2 dir) { CLD_MenkowskiPoint result; - result.s0 = collider_get_support_point(shape0, xf0, dir); - result.s1 = collider_get_support_point(shape1, xf1, NegVec2(dir)); + result.s0 = CLD_SupportPointFromDir(shape0, xf0, dir); + result.s1 = CLD_SupportPointFromDir(shape1, xf1, NegVec2(dir)); result.p = SubVec2(result.s0.p, result.s1.p); return result; } -/* ========================== * - * AABB - * ========================== */ +//////////////////////////////// +//~ Aabb -Aabb collider_aabb_from_collider(CLD_Shape *shape, Xform xf) +Aabb CLD_AabbFromShape(CLD_Shape *shape, Xform xf) { Aabb result; - result.p0.x = collider_get_support_point(shape, xf, VEC2(-1, 0)).p.x - COLLISION_TOLERANCE; - result.p0.y = collider_get_support_point(shape, xf, VEC2(0, -1)).p.y - COLLISION_TOLERANCE; - result.p1.x = collider_get_support_point(shape, xf, VEC2(1, 0)).p.x + COLLISION_TOLERANCE; - result.p1.y = collider_get_support_point(shape, xf, VEC2(0, 1)).p.y + COLLISION_TOLERANCE; + result.p0.x = CLD_SupportPointFromDir(shape, xf, VEC2(-1, 0)).p.x - CLD_CollisionTolerance; + result.p0.y = CLD_SupportPointFromDir(shape, xf, VEC2(0, -1)).p.y - CLD_CollisionTolerance; + result.p1.x = CLD_SupportPointFromDir(shape, xf, VEC2(1, 0)).p.x + CLD_CollisionTolerance; + result.p1.y = CLD_SupportPointFromDir(shape, xf, VEC2(0, 1)).p.y + CLD_CollisionTolerance; return result; } -Aabb collider_aabb_from_combined_aabb(Aabb b0, Aabb b1) +Aabb CLD_CombineAabb(Aabb b0, Aabb b1) { Aabb result; result.p0.x = MinF32(MinF32(b0.p0.x, b0.p1.x), MinF32(b1.p0.x, b1.p1.x)); @@ -119,7 +108,7 @@ Aabb collider_aabb_from_combined_aabb(Aabb b0, Aabb b1) return result; } -b32 collider_test_aabb(Aabb box0, Aabb box1) +b32 CLD_TestAabb(Aabb box0, Aabb box1) { f32 b0_x0 = box0.p0.x; f32 b0_x1 = box0.p1.x; @@ -133,32 +122,19 @@ b32 collider_test_aabb(Aabb box0, Aabb box1) ((b0_y0 >= b1_y0 && b0_y0 <= b1_y1) || (b0_y1 >= b1_y0 && b0_y1 <= b1_y1) || (b1_y0 >= b0_y0 && b1_y0 <= b0_y1) || (b1_y1 >= b0_y0 && b1_y1 <= b0_y1)); } -/* ========================== * - * GJK - * +//////////////////////////////// +//~ Gjk + +/* * Determine simplex in menkowksi difference that encapsulates origin if shapes - * overlap, or closest edge / point to origin on menkowski difference if they + * overlap, or closest edge / point to origin on CLD_Menkowski difference if they * do not. - * ========================== */ - -struct gjk_result { - CLD_MenkowskiSimplex simplex; - Vec2 final_dir; - - /* If 1, simplex represents triangle inside of menkowski difference - * encapsulating the origin. If 0, simplex represents the closest - * feature on menkowski difference to the origin. */ - b32 overlapping; + */ #if COLLIDER_DEBUG - u32 dbg_step; -#endif -}; - -#if COLLIDER_DEBUG -internal struct gjk_result gjk_get_simplex(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, f32 min_unique_pt_dist_sq, u32 dbg_step) +CLD_GjkData CLD_GjkDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, f32 min_unique_pt_dist_sq, u32 dbg_step) #else -internal struct gjk_result gjk_get_simplex(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, f32 min_unique_pt_dist_sq) +CLD_GjkData CLD_GjkDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, f32 min_unique_pt_dist_sq) #endif { b32 overlapping = 0; @@ -169,7 +145,7 @@ internal struct gjk_result gjk_get_simplex(CLD_Shape *shape0, CLD_Shape *shape1, /* First point is support point in shape's general directions to eachother */ dir = SubVec2(xf1.og, xf0.og); if (IsVec2Zero(dir)) dir = VEC2(1, 0); - s.a = get_menkowski_point(shape0, shape1, xf0, xf1, dir); + s.a = CLD_MenkowskiPointFromDir(shape0, shape1, xf0, xf1, dir); s.len = 1; Vec2 removed_a = ZI; @@ -180,8 +156,8 @@ internal struct gjk_result gjk_get_simplex(CLD_Shape *shape0, CLD_Shape *shape1, /* Second point is support point towards origin */ dir = NegVec2(s.a.p); - DBGSTEP; - m = get_menkowski_point(shape0, shape1, xf0, xf1, dir); + CLD_DBGSTEP; + m = CLD_MenkowskiPointFromDir(shape0, shape1, xf0, xf1, dir); /* Check that new point is far enough away from existing point */ if (Vec2LenSq(SubVec2(m.p, s.a.p)) < min_unique_pt_dist_sq) { overlapping = 0; @@ -196,8 +172,8 @@ internal struct gjk_result gjk_get_simplex(CLD_Shape *shape0, CLD_Shape *shape1, } { - DBGSTEP; - m = get_menkowski_point(shape0, shape1, xf0, xf1, dir); + CLD_DBGSTEP; + m = CLD_MenkowskiPointFromDir(shape0, shape1, xf0, xf1, dir); /* Check that new point is far enough away from existing points */ if (Vec2LenSq(SubVec2(m.p, s.a.p)) < min_unique_pt_dist_sq || Vec2LenSq(SubVec2(m.p, s.b.p)) < min_unique_pt_dist_sq || @@ -225,7 +201,7 @@ internal struct gjk_result gjk_get_simplex(CLD_Shape *shape0, CLD_Shape *shape1, } /* Determine region of the simplex in which the origin lies */ - DBGSTEP; + CLD_DBGSTEP; Vec2 vab = SubVec2(s.b.p, s.a.p); Vec2 vac = SubVec2(s.c.p, s.a.p); Vec2 vbc = SubVec2(s.c.p, s.b.p); @@ -294,7 +270,7 @@ internal struct gjk_result gjk_get_simplex(CLD_Shape *shape0, CLD_Shape *shape1, abort: #endif - struct gjk_result result = { + CLD_GjkData result = { .simplex = s, .overlapping = overlapping, .final_dir = dir, @@ -306,26 +282,17 @@ internal struct gjk_result gjk_get_simplex(CLD_Shape *shape0, CLD_Shape *shape1, return result; } -/* ========================== * - * EPA - * - * Expands upon result of GJK calculation to determine collision normal & closest edge when shapes are overlapping - * ========================== */ +//////////////////////////////// +//~ Epa -struct epa_result { - Vec2 normal; - CLD_MenkowskiFeature closest_feature; /* Represents closest feature (edge or point) to origin on menkowski difference */ +/* Expands upon result of GJK calculation to determine collision normal & + * closest edge when shapes are overlapping + */ #if COLLIDER_DEBUG - CLD_Prototype prototype; - u32 dbg_step; -#endif -}; - -#if COLLIDER_DEBUG -internal struct epa_result epa_get_normal_from_gjk(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, struct gjk_result gjk_result, f32 min_unique_pt_dist_sq, u32 max_iterations, u32 dbg_step) +CLD_EpaData CLD_EpaDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, CLD_GjkData gjk_result, f32 min_unique_pt_dist_sq, u32 max_iterations, u32 dbg_step) #else -internal struct epa_result epa_get_normal_from_gjk(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, struct gjk_result gjk_result, f32 min_unique_pt_dist_sq, u32 max_iterations) +CLD_EpaData CLD_EpaDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, CLD_GjkData gjk_result, f32 min_unique_pt_dist_sq, u32 max_iterations) #endif { TempArena scratch = BeginScratchNoConflict(); @@ -383,7 +350,7 @@ internal struct epa_result epa_get_normal_from_gjk(CLD_Shape *shape0, CLD_Shape /* Find new point in dir */ Vec2 dir = MulVec2(PerpVec2(vab), winding); - CLD_MenkowskiPoint m = get_menkowski_point(shape0, shape1, xf0, xf1, dir); + CLD_MenkowskiPoint m = CLD_MenkowskiPointFromDir(shape0, shape1, xf0, xf1, dir); #if COLLIDER_DEBUG { @@ -396,7 +363,7 @@ internal struct epa_result epa_get_normal_from_gjk(CLD_Shape *shape0, CLD_Shape #endif /* Check validity of new point */ - DBGSTEP; + CLD_DBGSTEP; { b32 valid = 1; @@ -454,7 +421,7 @@ internal struct epa_result epa_get_normal_from_gjk(CLD_Shape *shape0, CLD_Shape abort: #endif - struct epa_result result = { + CLD_EpaData result = { .normal = normal, .closest_feature = closest_feature }; @@ -472,16 +439,10 @@ internal struct epa_result epa_get_normal_from_gjk(CLD_Shape *shape0, CLD_Shape return result; } -/* ========================== * - * Clipping - * ========================== */ +//////////////////////////////// +//~ Clipping -struct clip_line_to_line_result { - Vec2 a0_clipped, b0_clipped; - Vec2 a1_clipped, b1_clipped; -}; - -internal struct clip_line_to_line_result clip_line_to_line(Vec2 a0, Vec2 b0, Vec2 a1, Vec2 b1, Vec2 normal) +CLD_ClippedLine CLD_ClipLineToLine(Vec2 a0, Vec2 b0, Vec2 a1, Vec2 b1, Vec2 normal) { Vec2 vab0 = SubVec2(b0, a0); Vec2 vab1 = SubVec2(b1, a1); @@ -508,7 +469,7 @@ internal struct clip_line_to_line_result clip_line_to_line(Vec2 a0, Vec2 b0, Vec b1t = ClampF32(-vb0b1_w * -w, 0, 1); } - struct clip_line_to_line_result result; + CLD_ClippedLine result; result.a0_clipped = AddVec2(a0, MulVec2(vab0, a0t)); result.a1_clipped = AddVec2(a1, MulVec2(vab1, a1t)); result.b0_clipped = AddVec2(b0, MulVec2(vab0, -b0t)); @@ -516,7 +477,7 @@ internal struct clip_line_to_line_result clip_line_to_line(Vec2 a0, Vec2 b0, Vec return result; } -internal Vec2 clip_point_to_line(Vec2 a, Vec2 b, Vec2 p, Vec2 normal) +Vec2 CLD_ClipPointToLine(Vec2 a, Vec2 b, Vec2 p, Vec2 normal) { Vec2 vab = SubVec2(b, a); Vec2 vap = SubVec2(p, a); @@ -534,17 +495,16 @@ internal Vec2 clip_point_to_line(Vec2 a, Vec2 b, Vec2 p, Vec2 normal) return result; } -/* ========================== * - * Collision points - * ========================== */ +//////////////////////////////// +//~ Collision points -CLD_CollisionResult collider_collision_points(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1) +CLD_CollisionData CLD_CollisionDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1) { - CLD_CollisionResult result = ZI; + CLD_CollisionData result = ZI; - const f32 tolerance = COLLISION_TOLERANCE; - const f32 min_unique_pt_dist_sq = MIN_UNIQUE_PT_DIST_SQ; - const u32 max_epa_iterations = MAX_EPA_ITERATIONS; + const f32 tolerance = CLD_CollisionTolerance; + const f32 min_unique_pt_dist_sq = CLD_MinUniquePtDistSq; + const u32 max_epa_iterations = CLD_MaxEpaIterations; CLD_CollisionPoint points[2] = ZI; u32 num_points = 0; @@ -555,27 +515,27 @@ CLD_CollisionResult collider_collision_points(CLD_Shape *shape0, CLD_Shape *shap u32 dbg_step = 0; #endif - struct gjk_result gjk_result = ZI; - struct epa_result epa_result = ZI; + CLD_GjkData gjk_result = ZI; + CLD_EpaData epa_result = ZI; /* Run GJK */ #if COLLIDER_DEBUG - gjk_result = gjk_get_simplex(shape0, shape1, xf0, xf1, min_unique_pt_dist_sq, dbg_step); + gjk_result = CLD_GjkDataFromShapes(shape0, shape1, xf0, xf1, min_unique_pt_dist_sq, dbg_step); dbg_step = gjk_result.dbg_step; #else - gjk_result = gjk_get_simplex(shape0, shape1, xf0, xf1, min_unique_pt_dist_sq); + gjk_result = CLD_GjkDataFromShapes(shape0, shape1, xf0, xf1, min_unique_pt_dist_sq); #endif - DBGSTEP; + CLD_DBGSTEP; /* Run EPA */ #if COLLIDER_DEBUG - epa_result = epa_get_normal_from_gjk(shape0, shape1, xf0, xf1, gjk_result, min_unique_pt_dist_sq, max_epa_iterations, dbg_step); + epa_result = CLD_EpaDataFromShapes(shape0, shape1, xf0, xf1, gjk_result, min_unique_pt_dist_sq, max_epa_iterations, dbg_step); dbg_step = epa_result.dbg_step; #else - epa_result = epa_get_normal_from_gjk(shape0, shape1, xf0, xf1, gjk_result, min_unique_pt_dist_sq, max_epa_iterations); + epa_result = CLD_EpaDataFromShapes(shape0, shape1, xf0, xf1, gjk_result, min_unique_pt_dist_sq, max_epa_iterations); #endif normal = epa_result.normal; - DBGSTEP; + CLD_DBGSTEP; /* Determine collision */ if (gjk_result.overlapping) { @@ -620,7 +580,7 @@ CLD_CollisionResult collider_collision_points(CLD_Shape *shape0, CLD_Shape *shap if (f.len == 2) { if (a0.i == b0.i) { if (shape0->count > 1) { - b0 = collider_get_support_point_internal(shape0, xf0, normal, b0.i); + b0 = CLD_SupportPointFromDirInternal(shape0, xf0, normal, b0.i); } else { collapse0 = 1; b0 = a0; @@ -628,7 +588,7 @@ CLD_CollisionResult collider_collision_points(CLD_Shape *shape0, CLD_Shape *shap } if (a1.i == b1.i) { if (shape1->count > 1) { - b1 = collider_get_support_point_internal(shape1, xf1, NegVec2(normal), b1.i); + b1 = CLD_SupportPointFromDirInternal(shape1, xf1, NegVec2(normal), b1.i); } else { collapse1 = 1; b1 = a1; @@ -691,7 +651,7 @@ CLD_CollisionResult collider_collision_points(CLD_Shape *shape0, CLD_Shape *shap b32 ignore_b = 1; if (!collapse0 && !collapse1) { /* Clip line to line */ - struct clip_line_to_line_result clip_result = clip_line_to_line(a0.p, b0.p, a1.p, b1.p, normal); + CLD_ClippedLine clip_result = CLD_ClipLineToLine(a0.p, b0.p, a1.p, b1.p, normal); Vec2 a0_clipped = clip_result.a0_clipped; Vec2 a1_clipped = clip_result.a1_clipped; Vec2 b0_clipped = clip_result.b0_clipped; @@ -723,11 +683,11 @@ CLD_CollisionResult collider_collision_points(CLD_Shape *shape0, CLD_Shape *shap /* TODO: Choose ID based on closest clipped point */ if (collapse1 && !collapse0) { /* Project a1 onto vab0 */ - p0 = clip_point_to_line(a0.p, b0.p, a1.p, normal); + p0 = CLD_ClipPointToLine(a0.p, b0.p, a1.p, normal); } if (collapse0 && !collapse1) { /* Project a0 onto vab1 */ - p1 = clip_point_to_line(a1.p, b1.p, a0.p, normal); + p1 = CLD_ClipPointToLine(a1.p, b1.p, a0.p, normal); } /* Calc midpoint */ Vec2 vsep = SubVec2(p1, p0); @@ -775,19 +735,18 @@ CLD_CollisionResult collider_collision_points(CLD_Shape *shape0, CLD_Shape *shap return result; } -/* ========================== * - * Closest points - * ========================== */ +//////////////////////////////// +//~ Closest points - /* TODO: De-duplicate code between collider_closest_points & collider_collision_points */ +/* TODO: De-duplicate code between CLD_ClosestPointDataFromShapes & CLD_CollisionDataFromShapes */ -CLD_ClosestResult collider_closest_points(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1) +CLD_ClosestPointData CLD_ClosestPointDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1) { - CLD_ClosestResult result = ZI; + CLD_ClosestPointData result = ZI; - const f32 tolerance = COLLISION_TOLERANCE; - const f32 min_unique_pt_dist_sq = MIN_UNIQUE_PT_DIST_SQ; - const u32 max_epa_iterations = MAX_EPA_ITERATIONS; + const f32 tolerance = CLD_CollisionTolerance; + const f32 min_unique_pt_dist_sq = CLD_MinUniquePtDistSq; + const u32 max_epa_iterations = CLD_MaxEpaIterations; Vec2 p0 = ZI; Vec2 p1 = ZI; @@ -797,26 +756,26 @@ CLD_ClosestResult collider_closest_points(CLD_Shape *shape0, CLD_Shape *shape1, u32 dbg_step = 0; #endif - struct gjk_result gjk_result = ZI; - struct epa_result epa_result = ZI; + CLD_GjkData gjk_result = ZI; + CLD_EpaData epa_result = ZI; /* Run GJK */ #if COLLIDER_DEBUG - gjk_result = gjk_get_simplex(shape0, shape1, xf0, xf1, min_unique_pt_dist_sq, dbg_step); + gjk_result = CLD_GjkDataFromShapes(shape0, shape1, xf0, xf1, min_unique_pt_dist_sq, dbg_step); dbg_step = gjk_result.dbg_step; #else - gjk_result = gjk_get_simplex(shape0, shape1, xf0, xf1, min_unique_pt_dist_sq); + gjk_result = CLD_GjkDataFromShapes(shape0, shape1, xf0, xf1, min_unique_pt_dist_sq); #endif - DBGSTEP; + CLD_DBGSTEP; /* Run EPA */ #if COLLIDER_DEBUG - epa_result = epa_get_normal_from_gjk(shape0, shape1, xf0, xf1, gjk_result, min_unique_pt_dist_sq, max_epa_iterations, dbg_step); + epa_result = CLD_EpaDataFromShapes(shape0, shape1, xf0, xf1, gjk_result, min_unique_pt_dist_sq, max_epa_iterations, dbg_step); dbg_step = epa_result.dbg_step; #else - epa_result = epa_get_normal_from_gjk(shape0, shape1, xf0, xf1, gjk_result, min_unique_pt_dist_sq, max_epa_iterations); + epa_result = CLD_EpaDataFromShapes(shape0, shape1, xf0, xf1, gjk_result, min_unique_pt_dist_sq, max_epa_iterations); #endif - DBGSTEP; + CLD_DBGSTEP; /* ========================== * * Resolve points @@ -863,16 +822,12 @@ CLD_ClosestResult collider_closest_points(CLD_Shape *shape0, CLD_Shape *shape1, return result; } -/* ========================== * - * Time of impact - * ========================== */ +//////////////////////////////// +//~ Time of impact - /* Takes 2 shapes and their xforms at t=0 and t=1. - * Returns time of impact in range [0, 1]. */ -f32 collider_time_of_impact(CLD_Shape *c0, CLD_Shape *c1, - Xform xf0_t0, Xform xf1_t0, - Xform xf0_t1, Xform xf1_t1, - f32 tolerance, u32 max_iterations) +/* Takes 2 shapes and their xforms at t=0 and t=1. + * Returns time of impact in range [0, 1]. */ +f32 CLD_TimeOfImpact(CLD_Shape *c0, CLD_Shape *c1, Xform xf0_t0, Xform xf1_t0, Xform xf0_t1, Xform xf1_t1, f32 tolerance, u32 max_iterations) { f32 t0 = 0; f32 t1 = 1; @@ -885,7 +840,7 @@ f32 collider_time_of_impact(CLD_Shape *c0, CLD_Shape *c1, Vec2 dir; Vec2 dir_neg; { - CLD_ClosestResult closest_points = collider_closest_points(c0, c1, xf0_t0, xf1_t0); + CLD_ClosestPointData closest_points = CLD_ClosestPointDataFromShapes(c0, c1, xf0_t0, xf1_t0); if (closest_points.colliding) { /* Shapes are penetrating at t=0 */ return 0; @@ -897,8 +852,8 @@ f32 collider_time_of_impact(CLD_Shape *c0, CLD_Shape *c1, } { - Vec2 p0 = collider_get_support_point(c0, xf0_t1, dir).p; - Vec2 p1 = collider_get_support_point(c1, xf1_t1, dir_neg).p; + Vec2 p0 = CLD_SupportPointFromDir(c0, xf0_t1, dir).p; + Vec2 p1 = CLD_SupportPointFromDir(c1, xf1_t1, dir_neg).p; t1_sep = DotVec2(dir, SubVec2(p1, p0)); if (t1_sep > 0) { /* Shapes are not penetrating at t=1 */ @@ -922,8 +877,8 @@ f32 collider_time_of_impact(CLD_Shape *c0, CLD_Shape *c1, Xform xf0 = LerpXform(xf0_t0, xf0_t1, t); Xform xf1 = LerpXform(xf1_t0, xf1_t1, t); - Vec2 p0 = collider_get_support_point(c0, xf0, dir).p; - Vec2 p1 = collider_get_support_point(c1, xf1, dir_neg).p; + Vec2 p0 = CLD_SupportPointFromDir(c0, xf0, dir).p; + Vec2 p1 = CLD_SupportPointFromDir(c1, xf1, dir_neg).p; t_sep = DotVec2(dir, SubVec2(p1, p0)); /* Update bracket */ @@ -941,19 +896,17 @@ f32 collider_time_of_impact(CLD_Shape *c0, CLD_Shape *c1, return t; } -/* ========================== * - * Debug functions - * TODO: Remove these - * ========================== */ +//////////////////////////////// +//~ Point cloud debugging - /* TODO: Remove this (debugging) */ -V2Array menkowski(Arena *arena, CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, u32 detail) +/* TODO: Remove this (debugging) */ +Vec2Array CLD_Menkowski(Arena *arena, CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, u32 detail) { - V2Array result = { .points = PushDry(arena, Vec2) }; + Vec2Array result = { .points = PushDry(arena, Vec2) }; for (u64 i = 0; i < detail; ++i) { f32 angle = ((f32)i / detail) * (2 * Pi); Vec2 dir = Vec2FromAngle(angle); - CLD_MenkowskiPoint m = get_menkowski_point(shape0, shape1, xf0, xf1, dir); + CLD_MenkowskiPoint m = CLD_MenkowskiPointFromDir(shape0, shape1, xf0, xf1, dir); if (result.count == 0 || !EqVec2(m.p, result.points[result.count - 1])) { *PushStructNoZero(arena, Vec2) = m.p; ++result.count; @@ -963,10 +916,10 @@ V2Array menkowski(Arena *arena, CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, } /* TODO: Remove this (debugging) */ -V2Array cloud(Arena *arena, CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1) +Vec2Array CLD_PointCloud(Arena *arena, CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1) { /* FIXME: Account for radius */ - V2Array result = { .points = PushDry(arena, Vec2) }; + Vec2Array result = { .points = PushDry(arena, Vec2) }; Vec2 *points0 = shape0->points; Vec2 *points1 = shape1->points; u32 count0 = shape0->count; @@ -982,12 +935,11 @@ V2Array cloud(Arena *arena, CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xfo return result; } -/* ========================== * - * Boolean GJK (UNUSED) - * ========================== */ +//////////////////////////////// +//~ Boolean GJK (unused) #if 0 -b32 collider_collision_boolean(CLD_Shape *shape0, CLD_Shape *shape1) +b32 CLD_GjkBoolean(CLD_Shape *shape0, CLD_Shape *shape1) { struct { Vec2 a, b, c; } s = ZI; @@ -997,18 +949,18 @@ b32 collider_collision_boolean(CLD_Shape *shape0, CLD_Shape *shape1) /* First point is support point in shape's general directions to eachother */ dir = SubVec2(starting_point(shape1), starting_point(shape0)); if (IsVec2Zero(dir)) dir = VEC2(1, 0); - s.a = get_menkowski_point(shape0, shape1, dir); + s.a = CLD_MenkowskiPointFromDir(shape0, shape1, dir); /* Second point is support point towards origin */ dir = NegVec2(s.a); - p = get_menkowski_point(shape0, shape1, dir); + p = CLD_MenkowskiPointFromDir(shape0, shape1, dir); if (DotVec2(dir, p) >= 0) { s.b = s.a; s.a = p; for (;;) { /* Third point is support point in direction of line normal towards origin */ dir = PerpVec2TowardsDir(SubVec2(s.b, s.a), NegVec2(s.a)); - p = get_menkowski_point(shape0, shape1, dir); + p = CLD_MenkowskiPointFromDir(shape0, shape1, dir); if (DotVec2(dir, p) < 0) { /* New point did not cross origin, collision impossible */ break; diff --git a/src/collider/collider_core.h b/src/collider/collider_core.h index bbef767a..d84a4c5c 100644 --- a/src/collider/collider_core.h +++ b/src/collider/collider_core.h @@ -1,42 +1,59 @@ -Struct(CLD_Shape) { +//////////////////////////////// +//~ Shape types + +Struct(CLD_Shape) +{ Vec2 points[8]; u32 count; f32 radius; }; -Struct(CLD_SupportPoint) { +//////////////////////////////// +//~ Menkowski types + +Struct(CLD_SupportPoint) +{ Vec2 p; u32 i; /* Index of original point in shape */ }; -Struct(CLD_MenkowskiPoint) { +Struct(CLD_MenkowskiPoint) +{ Vec2 p; /* Menkowski difference point */ CLD_SupportPoint s0; /* Support point of first shape in dir */ CLD_SupportPoint s1; /* Support point of second shape in -dir */ }; -Struct(CLD_MenkowskiSimplex) { +Struct(CLD_MenkowskiSimplex) +{ u32 len; CLD_MenkowskiPoint a, b, c; }; -Struct(CLD_MenkowskiFeature) { +Struct(CLD_MenkowskiFeature) +{ u32 len; CLD_MenkowskiPoint a, b; }; -Struct(CLD_CollisionPoint) { +//////////////////////////////// +//~ Collision types + +Struct(CLD_CollisionPoint) +{ Vec2 point; f32 separation; u32 id; /* Based on polygon edge-to-edge */ }; -Struct(CLD_Prototype) { +Struct(CLD_Prototype) +{ Vec2 points[64]; u32 len; }; -Struct(CLD_CollisionResult) { +Struct(CLD_CollisionData) +{ Vec2 normal; CLD_CollisionPoint points[2]; u32 num_points; @@ -51,7 +68,8 @@ Struct(CLD_CollisionResult) { Vec2 a0_clipped, b0_clipped, a1_clipped, b1_clipped; }; -Struct(CLD_ClosestResult) { +Struct(CLD_ClosestPointData) +{ Vec2 p0, p1; b32 colliding; @@ -61,21 +79,137 @@ Struct(CLD_ClosestResult) { CLD_Prototype prototype; }; -CLD_Shape collider_from_quad(Quad quad); +//////////////////////////////// +//~ Clipping types -CLD_SupportPoint collider_get_support_point(CLD_Shape *shape, Xform xf, Vec2 dir); +Struct(CLD_ClippedLine) { + Vec2 a0_clipped, b0_clipped; + Vec2 a1_clipped, b1_clipped; +}; -Aabb collider_aabb_from_collider(CLD_Shape *shape, Xform xf); +//////////////////////////////// +//~ Gjk types -Aabb collider_aabb_from_combined_aabb(Aabb b0, Aabb b1); +Struct(CLD_GjkData) +{ + CLD_MenkowskiSimplex simplex; + Vec2 final_dir; -b32 collider_test_aabb(Aabb box0, Aabb box1); + /* If 1, simplex represents triangle inside of CLD_Menkowski difference + * encapsulating the origin. If 0, simplex represents the closest + * feature on CLD_Menkowski difference to the origin. */ + b32 overlapping; -CLD_CollisionResult collider_collision_points(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1); +#if COLLIDER_DEBUG + u32 dbg_step; +#endif +}; -CLD_ClosestResult collider_closest_points(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1); +//////////////////////////////// +//~ Epa types -f32 collider_time_of_impact(CLD_Shape *c0, CLD_Shape *c1, Xform xf0_t0, Xform xf1_t0, Xform xf0_t1, Xform xf1_t1, f32 tolerance, u32 max_iterations); +Struct(CLD_EpaData) +{ + Vec2 normal; + CLD_MenkowskiFeature closest_feature; /* Represents closest feature (edge or point) to origin on CLD_Menkowski difference */ -V2Array menkowski(Arena *arena, CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, u32 detail); -V2Array cloud(Arena *arena, CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1); +#if COLLIDER_DEBUG + CLD_Prototype prototype; + u32 dbg_step; +#endif +}; + +//////////////////////////////// +//~ Shared state + +/* How close can non-overlapping shapes be before collision is considered */ +#define CLD_CollisionTolerance 0.005f + +/* NOTE: Should always be less than tolerance, since colliding = 1 if origin is within this distance. */ +#define CLD_MinUniquePtDistSq (0.001f * 0.001f) + +/* To prevent extremely large prototypes when origin is in exact center of rounded feature */ +#define CLD_MaxEpaIterations 64 + +//////////////////////////////// +//~ Debug helpers + +#if COLLIDER_DEBUG +void CLD_DebugBreakable(void); + +#define CLD_DBGSTEP \ + dbg_step++; \ + if (dbg_step >= GetGstat(GSTAT_DEBUG_STEPS)) \ + { \ + goto abort; \ + } else if (dbg_step >= GetGstat(GSTAT_DEBUG_STEPS) - 1) \ + { \ + CLD_DebugBreakable(); \ + } (void)0 +#else +#define CLD_DBGSTEP +#endif + +//////////////////////////////// +//~ Shape operations + +CLD_Shape CLD_ShapeFromQuad(Quad quad); + +//////////////////////////////// +//~ Menkowski operations + +CLD_SupportPoint CLD_SupportPointFromDirInternal(CLD_Shape *shape, Xform xf, Vec2 dir, i32 ignore); +CLD_SupportPoint CLD_SupportPointFromDir(CLD_Shape *shape, Xform xf, Vec2 dir); +CLD_MenkowskiPoint CLD_MenkowskiPointFromDir(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, Vec2 dir); + +//////////////////////////////// +//~ Aabb operations + +Aabb CLD_AabbFromShape(CLD_Shape *shape, Xform xf); +Aabb CLD_CombineAabb(Aabb b0, Aabb b1); +b32 CLD_TestAabb(Aabb box0, Aabb box1); + +//////////////////////////////// +//~ Gjk operations + +#if COLLIDER_DEBUG +CLD_GjkData CLD_GjkDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, f32 min_unique_pt_dist_sq, u32 dbg_step); +#else +CLD_GjkData CLD_GjkDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, f32 min_unique_pt_dist_sq); +#endif + +//////////////////////////////// +//~ Epa operations + +#if COLLIDER_DEBUG +CLD_EpaData CLD_EpaDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, CLD_GjkData gjk_result, f32 min_unique_pt_dist_sq, u32 max_iterations, u32 dbg_step); +#else +CLD_EpaData CLD_EpaDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, CLD_GjkData gjk_result, f32 min_unique_pt_dist_sq, u32 max_iterations); +#endif + +//////////////////////////////// +//~ Clipping operations + +CLD_ClippedLine CLD_ClipLineToLine(Vec2 a0, Vec2 b0, Vec2 a1, Vec2 b1, Vec2 normal); +Vec2 CLD_ClipPointToLine(Vec2 a, Vec2 b, Vec2 p, Vec2 normal); + +//////////////////////////////// +//~ Collision point operations + +CLD_CollisionData CLD_CollisionDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1); + +//////////////////////////////// +//~ Closest point operations + +CLD_ClosestPointData CLD_ClosestPointDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1); + +//////////////////////////////// +//~ Time of impact operations + +f32 CLD_TimeOfImpact(CLD_Shape *c0, CLD_Shape *c1, Xform xf0_t0, Xform xf1_t0, Xform xf0_t1, Xform xf1_t1, f32 tolerance, u32 max_iterations); + +//////////////////////////////// +//~ Point cloud debugging operations + +Vec2Array CLD_Menkowski(Arena *arena, CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, u32 detail); +Vec2Array CLD_PointCloud(Arena *arena, CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1); diff --git a/src/config.h b/src/config.h index 1db7bf16..692fa6f7 100644 --- a/src/config.h +++ b/src/config.h @@ -69,14 +69,14 @@ # define SIM_MAX_ANGULAR_VELOCITY F32Infinity #endif -#define COLLIDER_DEBUG 1 +#define COLLIDER_DEBUG 0 #define COLLIDER_DEBUG_DETAILED 1 #define COLLIDER_DEBUG_DETAILED_DRAW_MENKOWSKI 1 #define FLOOD_DEBUG 0 /* If enabled, bitbuffs will insert/verify magic numbers & length for each read & write */ -#define DebugBitbuff 0 +#define BITBUFF_DEBUG 0 #define BITBUFF_TEST RtcIsEnabled /* If enabled, things like network writes & memory allocations will be tracked in a global statistics struct */ diff --git a/src/draw/draw_core.c b/src/draw/draw_core.c index 1316fdc5..c09d613b 100644 --- a/src/draw/draw_core.c +++ b/src/draw/draw_core.c @@ -36,7 +36,7 @@ void draw_material(G_RenderSig *sig, D_MaterialParams params) * Fill shapes * ========================== */ -void draw_poly_ex(G_RenderSig *sig, V2Array vertices, G_Indices indices, u32 color) +void draw_poly_ex(G_RenderSig *sig, Vec2Array vertices, G_Indices indices, u32 color) { G_RenderCmdDesc cmd = ZI; cmd.kind = GP_RENDER_CMD_KIND_DRAW_UI_SHAPE; @@ -47,7 +47,7 @@ void draw_poly_ex(G_RenderSig *sig, V2Array vertices, G_Indices indices, u32 col } /* Draws a filled polygon using triangles in a fan pattern */ -void draw_poly(G_RenderSig *sig, V2Array vertices, u32 color) +void draw_poly(G_RenderSig *sig, Vec2Array vertices, u32 color) { if (vertices.count >= 3) { TempArena scratch = BeginScratchNoConflict(); @@ -87,7 +87,7 @@ void draw_circle(G_RenderSig *sig, Vec2 pos, f32 radius, u32 color, u32 detail) points[i] = AddVec2(pos, p); } - V2Array vertices = { + Vec2Array vertices = { .points = points, .count = detail }; @@ -102,7 +102,7 @@ void draw_quad(G_RenderSig *sig, Quad quad, u32 color) 0, 1, 2, 0, 2, 3 }; - V2Array vertices = { .count = 4, .points = quad.e }; + Vec2Array vertices = { .count = 4, .points = quad.e }; G_Indices indices = { .count = 6, .indices = indices_array }; draw_poly_ex(sig, vertices, indices, color); } @@ -136,7 +136,7 @@ void draw_ray(G_RenderSig *sig, Vec2 pos, Vec2 rel, f32 thickness, u32 color) draw_quad(sig, quad, color); } -void draw_poly_line(G_RenderSig *sig, V2Array points, b32 loop, f32 thickness, u32 color) +void draw_poly_line(G_RenderSig *sig, Vec2Array points, b32 loop, f32 thickness, u32 color) { if (points.count >= 2) { for (u64 i = 1; i < points.count; ++i) { @@ -168,7 +168,7 @@ void draw_circle_line(G_RenderSig *sig, Vec2 pos, f32 radius, f32 thickness, u32 points[i] = AddVec2(pos, p); } - V2Array a = { + Vec2Array a = { .points = points, .count = detail }; @@ -180,7 +180,7 @@ void draw_circle_line(G_RenderSig *sig, Vec2 pos, f32 radius, f32 thickness, u32 void draw_quad_line(G_RenderSig *sig, Quad quad, f32 thickness, u32 color) { Vec2 points[] = { quad.p0, quad.p1, quad.p2, quad.p3 }; - V2Array a = { .points = points, .count = countof(points) }; + Vec2Array a = { .points = points, .count = countof(points) }; draw_poly_line(sig, a, 1, thickness, color); } @@ -204,7 +204,7 @@ void draw_arrow_line(G_RenderSig *sig, Vec2 start, Vec2 end, f32 thickness, f32 Vec2 head_p2 = AddVec2(head_start, head_p2_dir); Vec2 head_points[] = { end, head_p1, head_p2 }; - V2Array head_points_v2_array = { + Vec2Array head_points_v2_array = { .points = head_points, .count = countof(head_points) }; @@ -223,7 +223,7 @@ void draw_arrow_ray(G_RenderSig *sig, Vec2 pos, Vec2 rel, f32 thickness, f32 arr void draw_collider_line(G_RenderSig *sig, CLD_Shape shape, Xform shape_xf, f32 thickness, u32 color, u32 detail) { TempArena scratch = BeginScratchNoConflict(); - V2Array poly = ZI; + Vec2Array poly = ZI; if (shape.radius == 0) { poly.count = shape.count; poly.points = PushStructsNoZero(scratch.arena, Vec2, shape.count); @@ -237,7 +237,7 @@ void draw_collider_line(G_RenderSig *sig, CLD_Shape shape, Xform shape_xf, f32 t for (u32 i = 0; i < detail; ++i) { f32 angle = ((f32)i / (f32)detail) * Tau; Vec2 dir = VEC2(CosF32(angle), SinF32(angle)); - Vec2 p = collider_get_support_point(&shape, shape_xf, dir).p; + Vec2 p = CLD_SupportPointFromDir(&shape, shape_xf, dir).p; poly.points[i] = p; } } diff --git a/src/draw/draw_core.h b/src/draw/draw_core.h index 497a5a87..fcb72a93 100644 --- a/src/draw/draw_core.h +++ b/src/draw/draw_core.h @@ -26,9 +26,9 @@ void draw_material(G_RenderSig *sig, D_MaterialParams params); * Fill shapes * ========================== */ -void draw_poly_ex(G_RenderSig *sig, V2Array vertices, G_Indices indices, u32 color); +void draw_poly_ex(G_RenderSig *sig, Vec2Array vertices, G_Indices indices, u32 color); -void draw_poly(G_RenderSig *sig, V2Array points, u32 color); +void draw_poly(G_RenderSig *sig, Vec2Array points, u32 color); void draw_circle(G_RenderSig *sig, Vec2 pos, f32 radius, u32 color, u32 detail); @@ -44,7 +44,7 @@ void draw_line(G_RenderSig *sig, Vec2 start, Vec2 end, f32 thickness, u32 color) void draw_ray(G_RenderSig *sig, Vec2 pos, Vec2 rel, f32 thickness, u32 color); -void draw_poly_line(G_RenderSig *sig, V2Array points, b32 loop, f32 thickness, u32 color); +void draw_poly_line(G_RenderSig *sig, Vec2Array points, b32 loop, f32 thickness, u32 color); void draw_circle_line(G_RenderSig *sig, Vec2 pos, f32 radius, f32 thickness, u32 color, u32 detail); diff --git a/src/gp/gp_core.h b/src/gp/gp_core.h index 6678d89c..a6a9b253 100644 --- a/src/gp/gp_core.h +++ b/src/gp/gp_core.h @@ -49,7 +49,7 @@ Struct(G_RenderCmdDesc) } ui_rect; struct { - V2Array vertices; + Vec2Array vertices; G_Indices indices; u32 color; } ui_shape; diff --git a/src/sim/sim_phys.c b/src/sim/sim_phys.c index 01c574f1..d404c154 100644 --- a/src/sim/sim_phys.c +++ b/src/sim/sim_phys.c @@ -34,7 +34,7 @@ void phys_create_and_update_contacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_ Xform check0_xf = sim_ent_get_xform(check0); CLD_Shape check0_collider = check0->local_collider; - Aabb aabb = collider_aabb_from_collider(&check0_collider, check0_xf); + Aabb aabb = CLD_AabbFromShape(&check0_collider, check0_xf); SpaceIter iter = space_iter_begin_aabb(space, aabb); SpaceEntry *space_entry; @@ -81,7 +81,7 @@ void phys_create_and_update_contacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_ } /* Calculate collision */ - CLD_CollisionResult collision_result = collider_collision_points(&e0_collider, &e1_collider, e0_xf, e1_xf); + CLD_CollisionData collision_result = CLD_CollisionDataFromShapes(&e0_collider, &e1_collider, e0_xf, e1_xf); /* Parts of algorithm are hard-coded to support 2 contact points */ StaticAssert(countof(constraint_ent->contact_constraint_data.points) == 2); @@ -254,7 +254,7 @@ void phys_create_and_update_contacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_ /* Update closest points */ { - CLD_ClosestResult closest_points = collider_closest_points(&e0_collider, &e1_collider, e0_xf, e1_xf); + CLD_ClosestPointData closest_points = CLD_ClosestPointDataFromShapes(&e0_collider, &e1_collider, e0_xf, e1_xf); dbg->closest0 = closest_points.p0; dbg->closest1 = closest_points.p1; } @@ -1177,9 +1177,9 @@ f32 phys_determine_earliest_toi(PhysStepCtx *ctx, f32 step_dt, f32 tolerance, u3 Xform e0_xf_t1 = get_derived_xform(e0, step_dt); /* TODO: Use swept aabb rather than combined aabb. This should prevent spikes from bullets returning 0 positive TOIs with irrelevant entities. */ - Aabb aabb_t0 = collider_aabb_from_collider(&e0_collider, e0_xf_t0); - Aabb aabb_t1 = collider_aabb_from_collider(&e0_collider, e0_xf_t1); - Aabb combined_aabb = collider_aabb_from_combined_aabb(aabb_t0, aabb_t1); + Aabb aabb_t0 = CLD_AabbFromShape(&e0_collider, e0_xf_t0); + Aabb aabb_t1 = CLD_AabbFromShape(&e0_collider, e0_xf_t1); + Aabb combined_aabb = CLD_CombineAabb(aabb_t0, aabb_t1); SpaceIter iter = space_iter_begin_aabb(space, combined_aabb); SpaceEntry *entry; @@ -1194,7 +1194,7 @@ f32 phys_determine_earliest_toi(PhysStepCtx *ctx, f32 step_dt, f32 tolerance, u3 Xform e1_xf_t0 = sim_ent_get_xform(e1); Xform e1_xf_t1 = get_derived_xform(e1, step_dt); - f32 t = collider_time_of_impact(&e0_collider, &e1_collider, e0_xf_t0, e1_xf_t0, e0_xf_t1, e1_xf_t1, tolerance, max_iterations); + f32 t = CLD_TimeOfImpact(&e0_collider, &e1_collider, e0_xf_t0, e1_xf_t0, e0_xf_t1, e1_xf_t1, tolerance, max_iterations); if (t != 0 && t < smallest_t) { smallest_t = t; } @@ -1224,7 +1224,7 @@ void phys_update_aabbs(PhysStepCtx *ctx) space_entry = space_entry_alloc(space, ent->id); ent->space_handle = space_entry->handle; } - Aabb aabb = collider_aabb_from_collider(&ent->local_collider, xf); + Aabb aabb = CLD_AabbFromShape(&ent->local_collider, xf); space_entry_update_aabb(space_entry, aabb); } } diff --git a/src/sim/sim_phys.h b/src/sim/sim_phys.h index 7d45403c..3df21f47 100644 --- a/src/sim/sim_phys.h +++ b/src/sim/sim_phys.h @@ -77,7 +77,7 @@ typedef struct CollisionDebugData CollisionDebugData; struct CollisionDebugData { EntId e0; EntId e1; - CLD_CollisionResult collision_result; + CLD_CollisionData collision_result; ContactPoint points[2]; u32 num_points; diff --git a/src/sim/sim_space.c b/src/sim/sim_space.c index 0c9526d5..584114c9 100644 --- a/src/sim/sim_space.c +++ b/src/sim/sim_space.c @@ -400,7 +400,7 @@ SpaceEntry *space_iter_next(SpaceIter *iter) if (next_node) { SpaceEntry *entry = next_node->entry; Aabb entry_aabb = entry->aabb; - if (collider_test_aabb(entry_aabb, iter_aabb)) { + if (CLD_TestAabb(entry_aabb, iter_aabb)) { break; } else { next_node = next_node->next_in_cell; diff --git a/src/sim/sim_step.c b/src/sim/sim_step.c index b16bd509..8c2e4ab6 100644 --- a/src/sim/sim_step.c +++ b/src/sim/sim_step.c @@ -263,7 +263,7 @@ internal void test_spawn_entities2(Ent *parent, Vec2 pos) sim_ent_enable_prop(e, SEPROP_SOLID); Quad collider_quad = QuadFromRect(RectFromScalar(-0.5, -0.5, 1, 1)); - e->local_collider = collider_from_quad(collider_quad); + e->local_collider = CLD_ShapeFromQuad(collider_quad); sim_ent_enable_prop(e, SEPROP_LIGHT_TEST); @@ -332,7 +332,7 @@ internal void test_spawn_entities3(Ent *parent, Vec2 pos) sim_ent_enable_prop(e, SEPROP_SOLID); Quad collider_quad = QuadFromRect(RectFromScalar(-0.5, -0.5, 1, 1)); - e->local_collider = collider_from_quad(collider_quad); + e->local_collider = CLD_ShapeFromQuad(collider_quad); } } @@ -390,7 +390,7 @@ internal void test_spawn_tile(Snapshot *world, Vec2 world_pos) sim_ent_enable_prop(e, SEPROP_SOLID); Quad collider_quad = QuadFromRect(RectFromScalar(-tile_size.x / 2, -tile_size.y / 2, tile_size.y, tile_size.y)); - e->local_collider = collider_from_quad(collider_quad); + e->local_collider = CLD_ShapeFromQuad(collider_quad); #else Vec2I32 tile_index = sim_world_tile_index_from_pos(world_pos); sim_snapshot_set_tile(world, tile_index, SIM_TILE_KIND_WALL); @@ -792,7 +792,7 @@ internal PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx) origin_collider.count = 1; Xform victim_xf = sim_ent_get_xform(victim); - CLD_ClosestResult closest_points = collider_closest_points(&origin_collider, &victim->local_collider, xf, victim_xf); + CLD_ClosestPointData closest_points = CLD_ClosestPointDataFromShapes(&origin_collider, &victim->local_collider, xf, victim_xf); Vec2 dir = SubVec2(closest_points.p1, closest_points.p0); Vec2 point = closest_points.p1; f32 distance = Vec2Len(dir); @@ -1224,7 +1224,7 @@ void sim_step(SimStepCtx *ctx) Xform cxf = ent->sprite_local_xform; S_SheetSlice slice = sprite_sheet_get_slice(sheet, ent->sprite_collider_slice, ent->animation_frame); - ent->local_collider = collider_from_quad(MulXformQuad(cxf, QuadFromRect(slice.rect))); + ent->local_collider = CLD_ShapeFromQuad(MulXformQuad(cxf, QuadFromRect(slice.rect))); } /* Test collider */ diff --git a/src/user/user_core.c b/src/user/user_core.c index 80f1b0d1..b9c3bc8d 100644 --- a/src/user/user_core.c +++ b/src/user/user_core.c @@ -766,7 +766,7 @@ internal void user_update(P_Window *window) if (ent_collider.count > 0) { /* TODO: Can just use boolean GJK */ Xform ent_xf = sim_ent_get_xform(ent); - CLD_CollisionResult collision_result = collider_collision_points(&ent_collider, &mouse_shape, ent_xf, mouse_xf); + CLD_CollisionData collision_result = CLD_CollisionDataFromShapes(&ent_collider, &mouse_shape, ent_xf, mouse_xf); if (collision_result.num_points > 0) { hovered_ent = sim_ent_from_id(G.ss_blended, ent->top); break; @@ -1279,7 +1279,7 @@ internal void user_update(P_Window *window) /* Draw AABB */ if (ent->local_collider.count > 0) { - Aabb aabb = collider_aabb_from_collider(&ent->local_collider, xf); + Aabb aabb = CLD_AabbFromShape(&ent->local_collider, xf); f32 thickness = 1; u32 color = Rgba32F(1, 0, 1, 0.5); Quad quad = QuadFromAabb(aabb); @@ -1387,7 +1387,7 @@ internal void user_update(P_Window *window) if (collider.count == 1 && collider.radius > 0) { /* Draw upwards line for circle */ Vec2 start = xf.og; - Vec2 end = collider_get_support_point(&collider, xf, NegVec2(xf.by)).p; + Vec2 end = CLD_SupportPointFromDir(&collider, xf, NegVec2(xf.by)).p; start = MulXformV2(G.world_to_ui_xf, start); end = MulXformV2(G.world_to_ui_xf, end); draw_line(G.render_sig, start, end, thickness, color); @@ -1474,7 +1474,7 @@ internal void user_update(P_Window *window) #if COLLIDER_DEBUG if (sim_ent_has_prop(ent, SEPROP_COLLISION_DEBUG)) { CollisionDebugData *data = &ent->collision_debug_data; - CLD_CollisionResult collision_reuslt = data->collision_result; + CLD_CollisionData collision_reuslt = data->collision_result; Ent *e0 = sim_ent_from_id(G.ss_blended, data->e0); Ent *e1 = sim_ent_from_id(G.ss_blended, data->e1); CLD_Shape e0_collider = e0->local_collider; @@ -1574,7 +1574,7 @@ internal void user_update(P_Window *window) } #endif - /* Draw menkowski */ + /* Draw CLD_Menkowski */ { u32 color = collision_reuslt.solved ? Rgba32F(0, 0, 0.25, 1) : Rgba32F(0, 0.25, 0.25, 1); @@ -1582,19 +1582,19 @@ internal void user_update(P_Window *window) u32 detail = 512; (UNUSED)thickness; - V2Array m = menkowski(temp.arena, &e0_collider, &e1_collider, e0_xf, e1_xf, detail); + Vec2Array m = CLD_Menkowski(temp.arena, &e0_collider, &e1_collider, e0_xf, e1_xf, detail); for (u64 i = 0; i < m.count; ++i) m.points[i] = MulXformV2(G.world_to_ui_xf, m.points[i]); draw_poly_line(G.render_sig, m, 1, thickness, color); //draw_poly(G.render_sig, m, color); } - /* Draw cloud */ + /* Draw CLD_PointCloud */ { u32 color = Rgba32F(1, 1, 1, 1); f32 radius = 2; - V2Array m = cloud(temp.arena, &e0_collider, &e1_collider, e0_xf, e1_xf); + Vec2Array m = CLD_PointCloud(temp.arena, &e0_collider, &e1_collider, e0_xf, e1_xf); for (u64 i = 0; i < m.count; ++i) { Vec2 p = MulXformV2(G.world_to_ui_xf, m.points[i]); @@ -1607,7 +1607,7 @@ internal void user_update(P_Window *window) f32 thickness = 2; u32 color = Rgba32F(1, 1, 1, 0.25); - V2Array m = { + Vec2Array m = { .points = collision_reuslt.prototype.points, .count = collision_reuslt.prototype.len }; @@ -1627,7 +1627,7 @@ internal void user_update(P_Window *window) CLD_MenkowskiSimplex simplex = collision_reuslt.simplex; Vec2 simplex_points[] = { simplex.a.p, simplex.b.p, simplex.c.p }; for (u64 i = 0; i < countof(simplex_points); ++i) simplex_points[i] = MulXformV2(G.world_to_ui_xf, simplex_points[i]); - V2Array simplex_array = { .count = simplex.len, .points = simplex_points }; + Vec2Array simplex_array = { .count = simplex.len, .points = simplex_points }; if (simplex.len >= 1) { u32 color = simplex.len == 1 ? color_first : (simplex.len == 2 ? color_second : color_third); @@ -1933,7 +1933,7 @@ internal void user_update(P_Window *window) String text = ZI; text.text = PushDry(temp.arena, u8); -#if BB_DebugIsEnabled +#if BITBUFF_DEBUG text.len += CopyString(temp.arena, Lit("(bitbuff debug enabled)")).len; text.len += CopyString(temp.arena, Lit("\n")).len; #endif