collider layer refactor

This commit is contained in:
jacob 2025-07-30 17:31:14 -05:00
parent 9731a5742a
commit 3d863022fb
16 changed files with 418 additions and 341 deletions

View File

@ -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

View File

@ -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);

View File

@ -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;
};

View File

@ -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)
{

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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 */

View File

@ -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;
}
}

View File

@ -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);

View File

@ -49,7 +49,7 @@ Struct(G_RenderCmdDesc)
} ui_rect;
struct
{
V2Array vertices;
Vec2Array vertices;
G_Indices indices;
u32 color;
} ui_shape;

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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 */

View File

@ -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