draw layer refactor

This commit is contained in:
jacob 2025-07-30 17:51:40 -05:00
parent 3d863022fb
commit 2d953cca9b
7 changed files with 493 additions and 375 deletions

View File

@ -245,7 +245,7 @@ void P_AppStartup(String args_str)
S_StartupReceipt sprite_sr = sprite_startup(); S_StartupReceipt sprite_sr = sprite_startup();
M_StartupReceipt mixer_sr = mixer_startup(); M_StartupReceipt mixer_sr = mixer_startup();
SND_StartupReceipt sound_sr = sound_startup(&asset_cache_sr); SND_StartupReceipt sound_sr = sound_startup(&asset_cache_sr);
D_StartupReceipt draw_sr = draw_startup(&font_sr); D_StartupReceipt draw_sr = D_Startup(&font_sr);
SimStartupReceipt sim_sr = sim_startup(); SimStartupReceipt sim_sr = sim_startup();
/* Interface systems */ /* Interface systems */

View File

@ -9,6 +9,7 @@
Struct(Vec2) { Struct(Vec2) {
f32 x, y; f32 x, y;
}; };
#define VEC2(x, y) CppCompatInitListType(Vec2) { (x), (y) }
Struct(Vec2Array) { Struct(Vec2Array) {
Vec2 *points; Vec2 *points;
@ -21,6 +22,7 @@ Struct(Vec2Array) {
Struct(Vec3) { Struct(Vec3) {
f32 x, y, z; f32 x, y, z;
}; };
#define VEC3(x, y, z) CppCompatInitListType(Vec3) { (x), (y), (z) }
Struct(Vec3Array) { Struct(Vec3Array) {
Vec3 *points; Vec3 *points;
@ -33,6 +35,7 @@ Struct(Vec3Array) {
Struct(Vec4) { Struct(Vec4) {
f32 x, y, z, w; f32 x, y, z, w;
}; };
#define VEC4(x, y, z, w) ((Vec4) { (x), (y), (z), (w) })
Struct(Vec4Array) { Struct(Vec4Array) {
Vec4 *points; Vec4 *points;
@ -45,6 +48,7 @@ Struct(Vec4Array) {
Struct(Vec2I32) { Struct(Vec2I32) {
i32 x, y; i32 x, y;
}; };
#define VEC2I32(x, y) CppCompatInitListType(Vec2I32) { (x), (y) }
//////////////////////////////// ////////////////////////////////
//~ Integer vector3 types //~ Integer vector3 types
@ -52,6 +56,7 @@ Struct(Vec2I32) {
Struct(Vec3I32) { Struct(Vec3I32) {
i32 x, y, z; i32 x, y, z;
}; };
#define VEC3I32(x, y, z) CppCompatInitListType(Vec3I32) { (x), (y), (z) }
//////////////////////////////// ////////////////////////////////
//~ Xform types //~ Xform types
@ -245,7 +250,6 @@ i64 LerpI64(i64 val0, i64 val1, f64 t);
//////////////////////////////// ////////////////////////////////
//~ Vec2 operations //~ Vec2 operations
#define VEC2(x, y) CppCompatInitListType(Vec2) { (x), (y) }
#define Vec2FromVec2I32(v) VEC2((v).x, (v).y) #define Vec2FromVec2I32(v) VEC2((v).x, (v).y)
b32 IsVec2Zero(Vec2 a); b32 IsVec2Zero(Vec2 a);
@ -300,30 +304,14 @@ Vec2 ClosestPointFromRay(Vec2 ray_pos, Vec2 ray_dir_norm, Vec2 p);
Vec2 LerpVec2(Vec2 val0, Vec2 val1, f32 t); Vec2 LerpVec2(Vec2 val0, Vec2 val1, f32 t);
Vec2 SlerpVec2(Vec2 val0, Vec2 val1, f32 t); Vec2 SlerpVec2(Vec2 val0, Vec2 val1, f32 t);
////////////////////////////////
//~ Vec3 operations
#define VEC3(x, y, z) ((Vec3) { (x), (y), (z) })
////////////////////////////////
//~ Vec4 operations
#define VEC4(x, y, z, w) ((Vec4) { (x), (y), (z), (w) })
//////////////////////////////// ////////////////////////////////
//~ Vec2I32 Operations //~ Vec2I32 Operations
#define VEC2I32(x, y) CppCompatInitListType(Vec2I32) { (x), (y) }
b32 EqVec2I32(Vec2I32 a, Vec2I32 b); b32 EqVec2I32(Vec2I32 a, Vec2I32 b);
Vec2I32 NegVec2I32(Vec2I32 a); Vec2I32 NegVec2I32(Vec2I32 a);
Vec2I32 AddVec2I32(Vec2I32 a, Vec2I32 b); Vec2I32 AddVec2I32(Vec2I32 a, Vec2I32 b);
Vec2I32 SubVec2I32(Vec2I32 a, Vec2I32 b); Vec2I32 SubVec2I32(Vec2I32 a, Vec2I32 b);
////////////////////////////////
//~ Vec3I32 operations
#define VEC3I32(x, y, z) CppCompatInitListType(Vec3I32) { (x), (y), (z) }
//////////////////////////////// ////////////////////////////////
//~ Xform operations //~ Xform operations

View File

@ -28,7 +28,7 @@ CLD_Shape CLD_ShapeFromQuad(Quad quad)
//////////////////////////////// ////////////////////////////////
//~ Menkowski support point //~ Menkowski support point
CLD_SupportPoint CLD_SupportPointFromDirInternal(CLD_Shape *shape, Xform xf, Vec2 dir, i32 ignore) CLD_SupportPoint CLD_SupportPointFromDirEx(CLD_Shape *shape, Xform xf, Vec2 dir, i32 ignore)
{ {
Vec2 *points = shape->points; Vec2 *points = shape->points;
u32 count = shape->count; u32 count = shape->count;
@ -37,7 +37,8 @@ CLD_SupportPoint CLD_SupportPointFromDirInternal(CLD_Shape *shape, Xform xf, Vec
dir = RotateVec2(dir, -RotationFromXform(xf)); dir = RotateVec2(dir, -RotationFromXform(xf));
dir = MulVec2Vec2(dir, ScaleFromXform(xf)); dir = MulVec2Vec2(dir, ScaleFromXform(xf));
if (count == 1) { if (count == 1)
{
/* Skip 'ignore' on single point colliders */ /* Skip 'ignore' on single point colliders */
ignore = -1; ignore = -1;
} }
@ -45,20 +46,24 @@ CLD_SupportPoint CLD_SupportPointFromDirInternal(CLD_Shape *shape, Xform xf, Vec
Vec2 furthest = ZI; Vec2 furthest = ZI;
u32 furthest_index = 0; u32 furthest_index = 0;
f32 furthest_dot = -F32Infinity; f32 furthest_dot = -F32Infinity;
for (u32 i = 0; i < count; ++i) { for (u32 i = 0; i < count; ++i)
if ((i32)i == ignore) { {
if ((i32)i == ignore)
{
continue; continue;
} }
Vec2 p = points[i]; Vec2 p = points[i];
f32 dot = DotVec2(dir, p); f32 dot = DotVec2(dir, p);
if (dot > furthest_dot) { if (dot > furthest_dot)
{
furthest = p; furthest = p;
furthest_dot = dot; furthest_dot = dot;
furthest_index = i; furthest_index = i;
} }
} }
if (radius > 0.0) { if (radius > 0.0)
{
dir = Vec2WithLen(dir, radius); dir = Vec2WithLen(dir, radius);
furthest = AddVec2(furthest, dir); furthest = AddVec2(furthest, dir);
} }
@ -73,7 +78,7 @@ CLD_SupportPoint CLD_SupportPointFromDirInternal(CLD_Shape *shape, Xform xf, Vec
CLD_SupportPoint CLD_SupportPointFromDir(CLD_Shape *shape, Xform xf, Vec2 dir) CLD_SupportPoint CLD_SupportPointFromDir(CLD_Shape *shape, Xform xf, Vec2 dir)
{ {
return CLD_SupportPointFromDirInternal(shape, xf, dir, -1); return CLD_SupportPointFromDirEx(shape, xf, dir, -1);
} }
CLD_MenkowskiPoint CLD_MenkowskiPointFromDir(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)
@ -119,7 +124,7 @@ b32 CLD_TestAabb(Aabb box0, Aabb box1)
f32 b1_y0 = box1.p0.y; f32 b1_y0 = box1.p0.y;
f32 b1_y1 = box1.p1.y; f32 b1_y1 = box1.p1.y;
return ((b0_x0 >= b1_x0 && b0_x0 <= b1_x1) || (b0_x1 >= b1_x0 && b0_x1 <= b1_x1) || (b1_x0 >= b0_x0 && b1_x0 <= b0_x1) || (b1_x1 >= b0_x0 && b1_x1 <= b0_x1)) && return ((b0_x0 >= b1_x0 && b0_x0 <= b1_x1) || (b0_x1 >= b1_x0 && b0_x1 <= b1_x1) || (b1_x0 >= b0_x0 && b1_x0 <= b0_x1) || (b1_x1 >= b0_x0 && b1_x1 <= b0_x1)) &&
((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)); ((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));
} }
//////////////////////////////// ////////////////////////////////
@ -151,15 +156,19 @@ CLD_GjkData CLD_GjkDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf
Vec2 removed_a = ZI; Vec2 removed_a = ZI;
Vec2 removed_b = ZI; Vec2 removed_b = ZI;
u32 num_removed = 0; u32 num_removed = 0;
for (;;) { for (;;)
if (s.len == 1) { {
if (s.len == 1)
{
//- Find second point in simplex
/* Second point is support point towards origin */ /* Second point is support point towards origin */
dir = NegVec2(s.a.p); dir = NegVec2(s.a.p);
CLD_DBGSTEP; CLD_DBGSTEP;
m = CLD_MenkowskiPointFromDir(shape0, shape1, xf0, xf1, dir); m = CLD_MenkowskiPointFromDir(shape0, shape1, xf0, xf1, dir);
/* Check that new point is far enough away from existing point */ /* Check that new point is far enough away from existing point */
if (Vec2LenSq(SubVec2(m.p, s.a.p)) < min_unique_pt_dist_sq) { if (Vec2LenSq(SubVec2(m.p, s.a.p)) < min_unique_pt_dist_sq)
{
overlapping = 0; overlapping = 0;
break; break;
} }
@ -172,6 +181,7 @@ CLD_GjkData CLD_GjkDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf
} }
{ {
//- Find third point in simplex
CLD_DBGSTEP; CLD_DBGSTEP;
m = CLD_MenkowskiPointFromDir(shape0, shape1, xf0, xf1, dir); m = CLD_MenkowskiPointFromDir(shape0, shape1, xf0, xf1, dir);
/* Check that new point is far enough away from existing points */ /* Check that new point is far enough away from existing points */
@ -182,7 +192,8 @@ CLD_GjkData CLD_GjkDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf
(Vec2LenSq(SubVec2(m.p, removed_a)) < min_unique_pt_dist_sq) || (Vec2LenSq(SubVec2(m.p, removed_a)) < min_unique_pt_dist_sq) ||
(num_removed >= 2 && Vec2LenSq(SubVec2(m.p, removed_b)) < min_unique_pt_dist_sq)) (num_removed >= 2 && Vec2LenSq(SubVec2(m.p, removed_b)) < min_unique_pt_dist_sq))
) || ) ||
AbsF32(WedgeVec2(SubVec2(s.b.p, s.a.p), SubVec2(m.p, s.a.p))) < min_unique_pt_dist_sq) { AbsF32(WedgeVec2(SubVec2(s.b.p, s.a.p), SubVec2(m.p, s.a.p))) < min_unique_pt_dist_sq)
{
overlapping = 0; overlapping = 0;
break; break;
} }
@ -193,14 +204,15 @@ CLD_GjkData CLD_GjkDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf
if ((AbsF32(WedgeVec2(SubVec2(s.b.p, s.a.p), NegVec2(s.a.p))) <= min_unique_pt_dist_sq) || if ((AbsF32(WedgeVec2(SubVec2(s.b.p, s.a.p), NegVec2(s.a.p))) <= min_unique_pt_dist_sq) ||
(AbsF32(WedgeVec2(SubVec2(s.c.p, s.b.p), NegVec2(s.b.p))) <= min_unique_pt_dist_sq) || (AbsF32(WedgeVec2(SubVec2(s.c.p, s.b.p), NegVec2(s.b.p))) <= min_unique_pt_dist_sq) ||
(AbsF32(WedgeVec2(SubVec2(s.c.p, s.a.p), NegVec2(s.a.p))) <= min_unique_pt_dist_sq)) { (AbsF32(WedgeVec2(SubVec2(s.c.p, s.a.p), NegVec2(s.a.p))) <= min_unique_pt_dist_sq))
{
/* Simplex lies on origin */ /* Simplex lies on origin */
overlapping = 1; overlapping = 1;
break; break;
} }
} }
/* Determine region of the simplex in which the origin lies */ //- Determine region of the simplex in which the origin lies
CLD_DBGSTEP; CLD_DBGSTEP;
Vec2 vab = SubVec2(s.b.p, s.a.p); Vec2 vab = SubVec2(s.b.p, s.a.p);
Vec2 vac = SubVec2(s.c.p, s.a.p); Vec2 vac = SubVec2(s.c.p, s.a.p);
@ -218,48 +230,61 @@ CLD_GjkData CLD_GjkDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf
f32 vac_dot = DotVec2(vac, NegVec2(s.a.p)) / Vec2LenSq(vac); f32 vac_dot = DotVec2(vac, NegVec2(s.a.p)) / Vec2LenSq(vac);
f32 vbc_dot = DotVec2(vbc, NegVec2(s.b.p)) / Vec2LenSq(vbc); f32 vbc_dot = DotVec2(vbc, NegVec2(s.b.p)) / Vec2LenSq(vbc);
if (rab_dot >= 0 && vab_dot >= 0 && vab_dot <= 1) { if (rab_dot >= 0 && vab_dot >= 0 && vab_dot <= 1)
/* Region ab, remove c */ {
//- Region ab, remove c
num_removed = 1; num_removed = 1;
removed_a = s.c.p; removed_a = s.c.p;
s.len = 2; s.len = 2;
dir = rab_dir; /* Next third point is in direction of region ab */ dir = rab_dir; /* Next third point is in direction of region ab */
} else if (rac_dot >= 0 && vac_dot >= 0 && vac_dot <= 1) { }
/* Region ac, remove b */ else if (rac_dot >= 0 && vac_dot >= 0 && vac_dot <= 1)
{
//- Region ac, remove b
num_removed = 1; num_removed = 1;
removed_a = s.b.p; removed_a = s.b.p;
s.len = 2; s.len = 2;
s.b = s.c; s.b = s.c;
dir = rac_dir; /* Next third point is in direction of region ac */ dir = rac_dir; /* Next third point is in direction of region ac */
} else if (rbc_dot >= 0 && vbc_dot >= 0 && vbc_dot <= 1) { }
/* Region bc, remove a */ else if (rbc_dot >= 0 && vbc_dot >= 0 && vbc_dot <= 1)
{
//- Region bc, remove a
num_removed = 1; num_removed = 1;
removed_a = s.a.p; removed_a = s.a.p;
s.len = 2; s.len = 2;
s.a = s.b; s.a = s.b;
s.b = s.c; s.b = s.c;
dir = rbc_dir; /* Next third point is in direction of region bc */ dir = rbc_dir; /* Next third point is in direction of region bc */
} else if (vab_dot <= 0 && vac_dot <= 0) { }
/* Region a, remove bc */ else if (vab_dot <= 0 && vac_dot <= 0)
{
//- Region a, remove bc
num_removed = 2; num_removed = 2;
removed_a = s.b.p; removed_a = s.b.p;
removed_b = s.c.p; removed_b = s.c.p;
s.len = 1; s.len = 1;
} else if (vab_dot >= 1 && vbc_dot <= 0) { }
/* Region b, remove ac */ else if (vab_dot >= 1 && vbc_dot <= 0)
{
//- Region b, remove ac
num_removed = 2; num_removed = 2;
removed_a = s.a.p; removed_a = s.a.p;
removed_b = s.c.p; removed_b = s.c.p;
s.len = 1; s.len = 1;
s.a = s.b; s.a = s.b;
} else if (vac_dot >= 1 && vbc_dot >= 1) { }
/* Region c, remove ab */ else if (vac_dot >= 1 && vbc_dot >= 1)
{
//- Region c, remove ab
num_removed = 2; num_removed = 2;
removed_a = s.a.p; removed_a = s.a.p;
removed_b = s.b.p; removed_b = s.b.p;
s.len = 1; s.len = 1;
s.a = s.c; s.a = s.c;
} else { }
else
{
/* No region, must be in simplex */ /* No region, must be in simplex */
overlapping = 1; overlapping = 1;
break; break;
@ -267,7 +292,7 @@ CLD_GjkData CLD_GjkDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf
} }
#if COLLIDER_DEBUG #if COLLIDER_DEBUG
abort: abort :
#endif #endif
CLD_GjkData result = { CLD_GjkData result = {
@ -302,7 +327,8 @@ CLD_EpaData CLD_EpaDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf
CLD_MenkowskiPoint *proto = 0; CLD_MenkowskiPoint *proto = 0;
u32 proto_count = 0; u32 proto_count = 0;
if (gjk_result.overlapping) { if (gjk_result.overlapping)
{
CLD_MenkowskiSimplex s = gjk_result.simplex; CLD_MenkowskiSimplex s = gjk_result.simplex;
proto = PushDry(scratch.arena, CLD_MenkowskiPoint); proto = PushDry(scratch.arena, CLD_MenkowskiPoint);
{ {
@ -317,7 +343,8 @@ CLD_EpaData CLD_EpaDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf
i32 winding = WindingFromVec2(SubVec2(s.c.p, s.a.p), SubVec2(s.b.p, s.a.p)); i32 winding = WindingFromVec2(SubVec2(s.c.p, s.a.p), SubVec2(s.b.p, s.a.p));
u32 epa_iterations = 0; u32 epa_iterations = 0;
for (;;) { for (;;)
{
++epa_iterations; ++epa_iterations;
/* Find dir from origin to closest edge */ /* Find dir from origin to closest edge */
@ -326,7 +353,8 @@ CLD_EpaData CLD_EpaDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf
CLD_MenkowskiPoint closest_a = ZI; CLD_MenkowskiPoint closest_a = ZI;
CLD_MenkowskiPoint closest_b = ZI; CLD_MenkowskiPoint closest_b = ZI;
u32 closest_b_index = 0; u32 closest_b_index = 0;
for (u32 i = 0; i < proto_count; ++i) { for (u32 i = 0; i < proto_count; ++i)
{
u32 a_index = i; u32 a_index = i;
u32 b_index = (i < proto_count - 1) ? (i + 1) : 0; u32 b_index = (i < proto_count - 1) ? (i + 1) : 0;
CLD_MenkowskiPoint a = proto[a_index]; CLD_MenkowskiPoint a = proto[a_index];
@ -339,7 +367,8 @@ CLD_EpaData CLD_EpaDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf
Vec2 proj = AddVec2(a.p, MulVec2(vab, proj_ratio)); Vec2 proj = AddVec2(a.p, MulVec2(vab, proj_ratio));
f32 proj_len_sq = Vec2LenSq(proj); f32 proj_len_sq = Vec2LenSq(proj);
if (proj_len_sq < closest_len_sq - min_unique_pt_dist_sq) { if (proj_len_sq < closest_len_sq - min_unique_pt_dist_sq)
{
closest_a = a; closest_a = a;
closest_b = b; closest_b = b;
closest_b_index = b_index; closest_b_index = b_index;
@ -378,16 +407,20 @@ CLD_EpaData CLD_EpaDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf
f32 dot = DotVec2(vab, vam) / Vec2LenSq(vab); f32 dot = DotVec2(vab, vam) / Vec2LenSq(vab);
if (dot >= -validity_epsilon && dot <= 1 - validity_epsilon && (WedgeVec2(vab, vam) * -winding) >= -validity_epsilon) { if (dot >= -validity_epsilon && dot <= 1 - validity_epsilon && (WedgeVec2(vab, vam) * -winding) >= -validity_epsilon)
{
/* New point is not between edge */ /* New point is not between edge */
valid = 0; valid = 0;
} else if (Vec2LenSq(vam) < min_unique_pt_dist_sq || Vec2LenSq(vbm) < min_unique_pt_dist_sq) { }
else if (Vec2LenSq(vam) < min_unique_pt_dist_sq || Vec2LenSq(vbm) < min_unique_pt_dist_sq)
{
/* New point is too close to existing */ /* New point is too close to existing */
valid = 0; valid = 0;
} }
} }
if (!valid || epa_iterations >= max_iterations) { if (!valid || epa_iterations >= max_iterations)
{
normal = NormVec2(dir); normal = NormVec2(dir);
closest_feature.a = closest_a; closest_feature.a = closest_a;
closest_feature.b = closest_b; closest_feature.b = closest_b;
@ -401,7 +434,8 @@ CLD_EpaData CLD_EpaDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf
++proto_count; ++proto_count;
/* Shift points in prototype to make room */ /* Shift points in prototype to make room */
for (u32 i = proto_count - 1; i > closest_b_index; --i) { for (u32 i = proto_count - 1; i > closest_b_index; --i)
{
u32 shift_from = (i > 0) ? i - 1 : proto_count - 1; u32 shift_from = (i > 0) ? i - 1 : proto_count - 1;
u32 shift_to = i; u32 shift_to = i;
proto[shift_to] = proto[shift_from]; proto[shift_to] = proto[shift_from];
@ -410,7 +444,9 @@ CLD_EpaData CLD_EpaDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf
/* Insert new point into prototype */ /* Insert new point into prototype */
proto[closest_b_index] = m; proto[closest_b_index] = m;
} }
} else { }
else
{
normal = NormVec2(gjk_result.final_dir); normal = NormVec2(gjk_result.final_dir);
closest_feature.len = gjk_result.simplex.len; closest_feature.len = gjk_result.simplex.len;
closest_feature.a = gjk_result.simplex.a; closest_feature.a = gjk_result.simplex.a;
@ -418,7 +454,7 @@ CLD_EpaData CLD_EpaDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf
} }
#if COLLIDER_DEBUG #if COLLIDER_DEBUG
abort: abort :
#endif #endif
CLD_EpaData result = { CLD_EpaData result = {
@ -429,7 +465,8 @@ CLD_EpaData CLD_EpaDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf
#if COLLIDER_DEBUG #if COLLIDER_DEBUG
result.dbg_step = dbg_step; result.dbg_step = dbg_step;
u32 len = MinU32(proto_count, countof(result.prototype.points)); u32 len = MinU32(proto_count, countof(result.prototype.points));
for (u32 i = 0; i < len; ++i) { for (u32 i = 0; i < len; ++i)
{
result.prototype.points[i] = proto[i].p; result.prototype.points[i] = proto[i].p;
} }
result.prototype.len = len; result.prototype.len = len;
@ -538,32 +575,41 @@ CLD_CollisionData CLD_CollisionDataFromShapes(CLD_Shape *shape0, CLD_Shape *shap
CLD_DBGSTEP; CLD_DBGSTEP;
/* Determine collision */ /* Determine collision */
if (gjk_result.overlapping) { if (gjk_result.overlapping)
{
colliding = 1; colliding = 1;
} else { }
else
{
CLD_MenkowskiFeature f = epa_result.closest_feature; CLD_MenkowskiFeature f = epa_result.closest_feature;
/* Shapes not overlapping, determine if distance between shapes within tolerance */ /* Shapes not overlapping, determine if distance between shapes within tolerance */
if (f.len == 1) { if (f.len == 1)
{
Vec2 p = NegVec2(f.a.p); Vec2 p = NegVec2(f.a.p);
if (Vec2LenSq(p) <= (tolerance * tolerance)) { if (Vec2LenSq(p) <= (tolerance * tolerance))
{
colliding = 1; colliding = 1;
} }
} else { }
else
{
/* Project origin to determine if distance is within tolerance. */ /* Project origin to determine if distance is within tolerance. */
Assert(f.len == 2); Assert(f.len == 2);
Vec2 vab = SubVec2(f.b.p, f.a.p); Vec2 vab = SubVec2(f.b.p, f.a.p);
Vec2 vao = NegVec2(f.a.p); Vec2 vao = NegVec2(f.a.p);
f32 ratio = ClampF32(DotVec2(vab, vao) / DotVec2(vab, vab), 0, 1); f32 ratio = ClampF32(DotVec2(vab, vao) / DotVec2(vab, vab), 0, 1);
Vec2 p = AddVec2(f.a.p, MulVec2(vab, ratio)); Vec2 p = AddVec2(f.a.p, MulVec2(vab, ratio));
if (Vec2LenSq(p) <= (tolerance * tolerance)) { if (Vec2LenSq(p) <= (tolerance * tolerance))
{
colliding = 1; colliding = 1;
} }
} }
} }
/* Clip to determine final points */ /* Clip to determine final points */
if (colliding) { if (colliding)
/* Max vertices must be < 16 to fit in 4 bit ids */ {
/* Max vertices must be < 16 to fit in 4 bit ids */
StaticAssert(countof(shape0->points) <= 16); StaticAssert(countof(shape0->points) <= 16);
CLD_MenkowskiFeature f = epa_result.closest_feature; CLD_MenkowskiFeature f = epa_result.closest_feature;
@ -577,24 +623,35 @@ CLD_CollisionData CLD_CollisionDataFromShapes(CLD_Shape *shape0, CLD_Shape *shap
CLD_SupportPoint b0 = f.b.s0; CLD_SupportPoint b0 = f.b.s0;
CLD_SupportPoint b1 = f.b.s1; CLD_SupportPoint b1 = f.b.s1;
/* FIXME: Manually account for shapes w/ 1 & 2 points */ /* FIXME: Manually account for shapes w/ 1 & 2 points */
if (f.len == 2) { if (f.len == 2)
if (a0.i == b0.i) { {
if (shape0->count > 1) { if (a0.i == b0.i)
b0 = CLD_SupportPointFromDirInternal(shape0, xf0, normal, b0.i); {
} else { if (shape0->count > 1)
{
b0 = CLD_SupportPointFromDirEx(shape0, xf0, normal, b0.i);
}
else
{
collapse0 = 1; collapse0 = 1;
b0 = a0; b0 = a0;
} }
} }
if (a1.i == b1.i) { if (a1.i == b1.i)
if (shape1->count > 1) { {
b1 = CLD_SupportPointFromDirInternal(shape1, xf1, NegVec2(normal), b1.i); if (shape1->count > 1)
} else { {
b1 = CLD_SupportPointFromDirEx(shape1, xf1, NegVec2(normal), b1.i);
}
else
{
collapse1 = 1; collapse1 = 1;
b1 = a1; b1 = a1;
} }
} }
} else { }
else
{
collapse0 = 1; collapse0 = 1;
collapse1 = 1; collapse1 = 1;
b0 = a0; b0 = a0;
@ -607,13 +664,15 @@ CLD_CollisionData CLD_CollisionDataFromShapes(CLD_Shape *shape0, CLD_Shape *shap
Vec2 vab1_norm = NormVec2(vab1); Vec2 vab1_norm = NormVec2(vab1);
/* Swap points based on normal direction for consistent clipping */ /* Swap points based on normal direction for consistent clipping */
if (WedgeVec2(normal, vab0) < 0) { if (WedgeVec2(normal, vab0) < 0)
{
CLD_SupportPoint tmp = a0; CLD_SupportPoint tmp = a0;
a0 = b0; a0 = b0;
b0 = tmp; b0 = tmp;
vab0 = NegVec2(vab0); vab0 = NegVec2(vab0);
} }
if (WedgeVec2(normal, vab1) < 0) { if (WedgeVec2(normal, vab1) < 0)
{
CLD_SupportPoint tmp = a1; CLD_SupportPoint tmp = a1;
a1 = b1; a1 = b1;
b1 = tmp; b1 = tmp;
@ -626,18 +685,26 @@ CLD_CollisionData CLD_CollisionDataFromShapes(CLD_Shape *shape0, CLD_Shape *shap
collapse1 = collapse1 || AbsF32(WedgeVec2(normal, vab1_norm)) < collapse_epsilon; collapse1 = collapse1 || AbsF32(WedgeVec2(normal, vab1_norm)) < collapse_epsilon;
/* Collapse lines into deepest point */ /* Collapse lines into deepest point */
if (collapse0) { if (collapse0)
if (DotVec2(normal, vab0) > 0) { {
if (DotVec2(normal, vab0) > 0)
{
a0 = b0; a0 = b0;
} else { }
else
{
/* TODO: Remove this (debugging) */ /* TODO: Remove this (debugging) */
b0 = a0; b0 = a0;
} }
} }
if (collapse1) { if (collapse1)
if (DotVec2(normal, vab1) < 0) { {
if (DotVec2(normal, vab1) < 0)
{
a1 = b1; a1 = b1;
} else { }
else
{
/* TODO: Remove this (debugging) */ /* TODO: Remove this (debugging) */
b1 = a1; b1 = a1;
} }
@ -649,7 +716,8 @@ CLD_CollisionData CLD_CollisionDataFromShapes(CLD_Shape *shape0, CLD_Shape *shap
Vec2 b_midpoint = ZI; Vec2 b_midpoint = ZI;
b32 ignore_a = 1; b32 ignore_a = 1;
b32 ignore_b = 1; b32 ignore_b = 1;
if (!collapse0 && !collapse1) { if (!collapse0 && !collapse1)
{
/* Clip line to line */ /* Clip line to line */
CLD_ClippedLine clip_result = CLD_ClipLineToLine(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 a0_clipped = clip_result.a0_clipped;
@ -666,10 +734,14 @@ CLD_CollisionData CLD_CollisionDataFromShapes(CLD_Shape *shape0, CLD_Shape *shap
ignore_a = 0; ignore_a = 0;
ignore_b = 0; ignore_b = 0;
Vec2 vfin = SubVec2(b_midpoint, a_midpoint); Vec2 vfin = SubVec2(b_midpoint, a_midpoint);
if (Vec2LenSq(vfin) < (0.005 * 0.005)) { if (Vec2LenSq(vfin) < (0.005 * 0.005))
if (a_sep > b_sep) { {
if (a_sep > b_sep)
{
ignore_a = 1; ignore_a = 1;
} else { }
else
{
ignore_b = 1; ignore_b = 1;
} }
} }
@ -677,15 +749,19 @@ CLD_CollisionData CLD_CollisionDataFromShapes(CLD_Shape *shape0, CLD_Shape *shap
result.a1_clipped = a1_clipped; result.a1_clipped = a1_clipped;
result.b0_clipped = b0_clipped; result.b0_clipped = b0_clipped;
result.b1_clipped = b1_clipped; result.b1_clipped = b1_clipped;
} else { }
else
{
Vec2 p0 = a0.p; Vec2 p0 = a0.p;
Vec2 p1 = a1.p; Vec2 p1 = a1.p;
/* TODO: Choose ID based on closest clipped point */ /* TODO: Choose ID based on closest clipped point */
if (collapse1 && !collapse0) { if (collapse1 && !collapse0)
{
/* Project a1 onto vab0 */ /* Project a1 onto vab0 */
p0 = CLD_ClipPointToLine(a0.p, b0.p, a1.p, normal); p0 = CLD_ClipPointToLine(a0.p, b0.p, a1.p, normal);
} }
if (collapse0 && !collapse1) { if (collapse0 && !collapse1)
{
/* Project a0 onto vab1 */ /* Project a0 onto vab1 */
p1 = CLD_ClipPointToLine(a1.p, b1.p, a0.p, normal); p1 = CLD_ClipPointToLine(a1.p, b1.p, a0.p, normal);
} }
@ -701,13 +777,15 @@ CLD_CollisionData CLD_CollisionDataFromShapes(CLD_Shape *shape0, CLD_Shape *shap
} }
/* Insert points */ /* Insert points */
if (!ignore_a && a_sep < tolerance) { if (!ignore_a && a_sep < tolerance)
{
CLD_CollisionPoint *point = &points[num_points++]; CLD_CollisionPoint *point = &points[num_points++];
point->id = a0.i | (a1.i << 4); point->id = a0.i | (a1.i << 4);
point->separation = a_sep; point->separation = a_sep;
point->point = a_midpoint; point->point = a_midpoint;
} }
if (!ignore_b && b_sep < tolerance) { if (!ignore_b && b_sep < tolerance)
{
CLD_CollisionPoint *point = &points[num_points++]; CLD_CollisionPoint *point = &points[num_points++];
point->id = b0.i | (b1.i << 4); point->id = b0.i | (b1.i << 4);
point->separation = b_sep; point->separation = b_sep;
@ -723,7 +801,7 @@ CLD_CollisionData CLD_CollisionDataFromShapes(CLD_Shape *shape0, CLD_Shape *shap
#if COLLIDER_DEBUG #if COLLIDER_DEBUG
result.solved = 1; result.solved = 1;
abort: abort:
result.simplex = gjk_result.simplex; result.simplex = gjk_result.simplex;
result.prototype.len = epa_result.prototype.len; result.prototype.len = epa_result.prototype.len;
CopyBytes(result.prototype.points, epa_result.prototype.points, sizeof(result.prototype.points[0]) * result.prototype.len); CopyBytes(result.prototype.points, epa_result.prototype.points, sizeof(result.prototype.points[0]) * result.prototype.len);
@ -783,11 +861,14 @@ CLD_ClosestPointData CLD_ClosestPointDataFromShapes(CLD_Shape *shape0, CLD_Shape
colliding = gjk_result.overlapping; colliding = gjk_result.overlapping;
CLD_MenkowskiFeature f = epa_result.closest_feature; CLD_MenkowskiFeature f = epa_result.closest_feature;
if (f.len == 1) { if (f.len == 1)
{
p0 = f.a.s0.p; p0 = f.a.s0.p;
p1 = f.a.s1.p; p1 = f.a.s1.p;
colliding = gjk_result.overlapping || Vec2LenSq(NegVec2(f.a.p)) <= (tolerance * tolerance); colliding = gjk_result.overlapping || Vec2LenSq(NegVec2(f.a.p)) <= (tolerance * tolerance);
} else { }
else
{
Assert(f.len == 2); Assert(f.len == 2);
/* FIXME: Winding order dependent? */ /* FIXME: Winding order dependent? */
f32 ratio; f32 ratio;
@ -810,10 +891,10 @@ CLD_ClosestPointData CLD_ClosestPointDataFromShapes(CLD_Shape *shape0, CLD_Shape
#if COLLIDER_DEBUG #if COLLIDER_DEBUG
result.solved = 1; result.solved = 1;
abort: abort:
result.simplex = gjk_result.simplex; result.simplex = gjk_result.simplex;
result.prototype.len = epa_result.prototype.len; result.prototype.len = epa_result.prototype.len;
CopyBytes(result.prototype.points, epa_result.prototype.points, sizeof(result.prototype.points[0]) *result.prototype.len); CopyBytes(result.prototype.points, epa_result.prototype.points, sizeof(result.prototype.points[0]) * result.prototype.len);
result.simplex = gjk_result.simplex; result.simplex = gjk_result.simplex;
#endif #endif
result.p0 = p0; result.p0 = p0;
@ -841,7 +922,8 @@ f32 CLD_TimeOfImpact(CLD_Shape *c0, CLD_Shape *c1, Xform xf0_t0, Xform xf1_t0, X
Vec2 dir_neg; Vec2 dir_neg;
{ {
CLD_ClosestPointData closest_points = CLD_ClosestPointDataFromShapes(c0, c1, xf0_t0, xf1_t0); CLD_ClosestPointData closest_points = CLD_ClosestPointDataFromShapes(c0, c1, xf0_t0, xf1_t0);
if (closest_points.colliding) { if (closest_points.colliding)
{
/* Shapes are penetrating at t=0 */ /* Shapes are penetrating at t=0 */
return 0; return 0;
} }
@ -855,20 +937,25 @@ f32 CLD_TimeOfImpact(CLD_Shape *c0, CLD_Shape *c1, Xform xf0_t0, Xform xf1_t0, X
Vec2 p0 = CLD_SupportPointFromDir(c0, xf0_t1, dir).p; Vec2 p0 = CLD_SupportPointFromDir(c0, xf0_t1, dir).p;
Vec2 p1 = CLD_SupportPointFromDir(c1, xf1_t1, dir_neg).p; Vec2 p1 = CLD_SupportPointFromDir(c1, xf1_t1, dir_neg).p;
t1_sep = DotVec2(dir, SubVec2(p1, p0)); t1_sep = DotVec2(dir, SubVec2(p1, p0));
if (t1_sep > 0) { if (t1_sep > 0)
{
/* Shapes are not penetrating at t=1 */ /* Shapes are not penetrating at t=1 */
return 1; return 1;
} }
} }
u32 iteration = 0; u32 iteration = 0;
while (AbsF32(t_sep) > tolerance && iteration < max_iterations) { while (AbsF32(t_sep) > tolerance && iteration < max_iterations)
{
/* Use mix of bisection & 0 position method to find root /* Use mix of bisection & 0 position method to find root
* (as described in https://box2d.org/files/ErinCatto_ContinuousCollision_GDC2013.pdf) */ * (as described in https://box2d.org/files/ErinCatto_ContinuousCollision_GDC2013.pdf) */
if (iteration & 1) { if (iteration & 1)
{
/* Bisect */ /* Bisect */
t = (t1 + t0) / 2.0; t = (t1 + t0) / 2.0;
} else { }
else
{
/* False position (fastest for linear case) */ /* False position (fastest for linear case) */
f32 m = (t1_sep - t0_sep) / (t1 - t0); f32 m = (t1_sep - t0_sep) / (t1 - t0);
t = (-t1_sep / m) + t1; t = (-t1_sep / m) + t1;
@ -882,10 +969,13 @@ f32 CLD_TimeOfImpact(CLD_Shape *c0, CLD_Shape *c1, Xform xf0_t0, Xform xf1_t0, X
t_sep = DotVec2(dir, SubVec2(p1, p0)); t_sep = DotVec2(dir, SubVec2(p1, p0));
/* Update bracket */ /* Update bracket */
if (t_sep > 0) { if (t_sep > 0)
{
t0 = t; t0 = t;
t0_sep = t_sep; t0_sep = t_sep;
} else { }
else
{
t1 = t; t1 = t;
t1_sep = t_sep; t1_sep = t_sep;
} }
@ -903,11 +993,13 @@ f32 CLD_TimeOfImpact(CLD_Shape *c0, CLD_Shape *c1, Xform xf0_t0, Xform xf1_t0, X
Vec2Array CLD_Menkowski(Arena *arena, CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, u32 detail) Vec2Array CLD_Menkowski(Arena *arena, CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, u32 detail)
{ {
Vec2Array result = { .points = PushDry(arena, Vec2) }; Vec2Array result = { .points = PushDry(arena, Vec2) };
for (u64 i = 0; i < detail; ++i) { for (u64 i = 0; i < detail; ++i)
{
f32 angle = ((f32)i / detail) * (2 * Pi); f32 angle = ((f32)i / detail) * (2 * Pi);
Vec2 dir = Vec2FromAngle(angle); Vec2 dir = Vec2FromAngle(angle);
CLD_MenkowskiPoint m = CLD_MenkowskiPointFromDir(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])) { if (result.count == 0 || !EqVec2(m.p, result.points[result.count - 1]))
{
*PushStructNoZero(arena, Vec2) = m.p; *PushStructNoZero(arena, Vec2) = m.p;
++result.count; ++result.count;
} }
@ -924,9 +1016,11 @@ Vec2Array CLD_PointCloud(Arena *arena, CLD_Shape *shape0, CLD_Shape *shape1, Xfo
Vec2 *points1 = shape1->points; Vec2 *points1 = shape1->points;
u32 count0 = shape0->count; u32 count0 = shape0->count;
u32 count1 = shape1->count; u32 count1 = shape1->count;
for (u64 i = 0; i < count0; ++i) { for (u64 i = 0; i < count0; ++i)
{
Vec2 p0 = MulXformV2(xf0, points0[i]); Vec2 p0 = MulXformV2(xf0, points0[i]);
for (u64 j = 0; j < count1; ++j) { for (u64 j = 0; j < count1; ++j)
{
Vec2 p1 = MulXformV2(xf1, points1[j]); Vec2 p1 = MulXformV2(xf1, points1[j]);
*PushStructNoZero(arena, Vec2) = SubVec2(p0, p1); *PushStructNoZero(arena, Vec2) = SubVec2(p0, p1);
++result.count; ++result.count;
@ -954,14 +1048,17 @@ b32 CLD_GjkBoolean(CLD_Shape *shape0, CLD_Shape *shape1)
/* Second point is support point towards origin */ /* Second point is support point towards origin */
dir = NegVec2(s.a); dir = NegVec2(s.a);
p = CLD_MenkowskiPointFromDir(shape0, shape1, dir); p = CLD_MenkowskiPointFromDir(shape0, shape1, dir);
if (DotVec2(dir, p) >= 0) { if (DotVec2(dir, p) >= 0)
{
s.b = s.a; s.b = s.a;
s.a = p; s.a = p;
for (;;) { for (;;)
{
/* Third point is support point in direction of line normal towards origin */ /* Third point is support point in direction of line normal towards origin */
dir = PerpVec2TowardsDir(SubVec2(s.b, s.a), NegVec2(s.a)); dir = PerpVec2TowardsDir(SubVec2(s.b, s.a), NegVec2(s.a));
p = CLD_MenkowskiPointFromDir(shape0, shape1, dir); p = CLD_MenkowskiPointFromDir(shape0, shape1, dir);
if (DotVec2(dir, p) < 0) { if (DotVec2(dir, p) < 0)
{
/* New point did not cross origin, collision impossible */ /* New point did not cross origin, collision impossible */
break; break;
} }
@ -975,15 +1072,21 @@ b32 CLD_GjkBoolean(CLD_Shape *shape0, CLD_Shape *shape1)
Vec2 a_to_origin = NegVec2(s.a); Vec2 a_to_origin = NegVec2(s.a);
dir = PerpVec2TowardsDir(vab, NegVec2(vac)); /* Normal of ab pointing away from c */ dir = PerpVec2TowardsDir(vab, NegVec2(vac)); /* Normal of ab pointing away from c */
if (DotVec2(dir, a_to_origin) >= 0) { if (DotVec2(dir, a_to_origin) >= 0)
{
/* Point is in region ab, remove c from simplex (will happen automatically next iteration) */ /* Point is in region ab, remove c from simplex (will happen automatically next iteration) */
} else { }
else
{
/* Point is not in region ab */ /* Point is not in region ab */
dir = PerpVec2TowardsDir(vac, NegVec2(vab)); /* Normal of ac pointing away from b */ dir = PerpVec2TowardsDir(vac, NegVec2(vab)); /* Normal of ac pointing away from b */
if (DotVec2(dir, a_to_origin) >= 0) { if (DotVec2(dir, a_to_origin) >= 0)
{
/* Point is in region ac, remove b from simplex */ /* Point is in region ac, remove b from simplex */
s.b = s.c; s.b = s.c;
} else { }
else
{
/* Point is in simplex */ /* Point is in simplex */
return 1; return 1;
} }

View File

@ -19,9 +19,9 @@ Struct(CLD_SupportPoint)
Struct(CLD_MenkowskiPoint) Struct(CLD_MenkowskiPoint)
{ {
Vec2 p; /* Menkowski difference point */ Vec2 p; /* Menkowski difference point */
CLD_SupportPoint s0; /* Support point of first shape in dir */ CLD_SupportPoint s0; /* Support point of first shape in dir */
CLD_SupportPoint s1; /* Support point of second shape in -dir */ CLD_SupportPoint s1; /* Support point of second shape in -dir */
}; };
Struct(CLD_MenkowskiSimplex) Struct(CLD_MenkowskiSimplex)
@ -82,7 +82,8 @@ Struct(CLD_ClosestPointData)
//////////////////////////////// ////////////////////////////////
//~ Clipping types //~ Clipping types
Struct(CLD_ClippedLine) { Struct(CLD_ClippedLine)
{
Vec2 a0_clipped, b0_clipped; Vec2 a0_clipped, b0_clipped;
Vec2 a1_clipped, b1_clipped; Vec2 a1_clipped, b1_clipped;
}; };
@ -158,7 +159,7 @@ CLD_Shape CLD_ShapeFromQuad(Quad quad);
//////////////////////////////// ////////////////////////////////
//~ Menkowski operations //~ Menkowski operations
CLD_SupportPoint CLD_SupportPointFromDirInternal(CLD_Shape *shape, Xform xf, Vec2 dir, i32 ignore); CLD_SupportPoint CLD_SupportPointFromDirEx(CLD_Shape *shape, Xform xf, Vec2 dir, i32 ignore);
CLD_SupportPoint CLD_SupportPointFromDir(CLD_Shape *shape, Xform xf, Vec2 dir); 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); CLD_MenkowskiPoint CLD_MenkowskiPointFromDir(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, Vec2 dir);

View File

@ -1,25 +1,22 @@
Global struct { D_SharedState D_shared_state = ZI;
G_Resource *solid_white_texture;
} G = ZI, DebugAlias(G, G_draw);
/* ========================== * ////////////////////////////////
* Startup //~ Startup
* ========================== */
D_StartupReceipt draw_startup(F_StartupReceipt *font_sr) D_StartupReceipt D_Startup(F_StartupReceipt *font_sr)
{ {
__prof; __prof;
D_SharedState *g = &D_shared_state;
(UNUSED)font_sr; (UNUSED)font_sr;
u32 pixel_white = 0xFFFFFFFF; u32 pixel_white = 0xFFFFFFFF;
G.solid_white_texture = gp_texture_alloc(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM, 0, VEC2I32(1, 1), &pixel_white); g->solid_white_texture = gp_texture_alloc(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM, 0, VEC2I32(1, 1), &pixel_white);
return (D_StartupReceipt) { 0 }; return (D_StartupReceipt) { 0 };
} }
/* ========================== * ////////////////////////////////
* Material //~ Material
* ========================== */
void draw_material(G_RenderSig *sig, D_MaterialParams params) void D_DrawMaterial(G_RenderSig *sig, D_MaterialParams params)
{ {
G_RenderCmdDesc cmd = ZI; G_RenderCmdDesc cmd = ZI;
cmd.kind = GP_RENDER_CMD_KIND_DRAW_MATERIAL; cmd.kind = GP_RENDER_CMD_KIND_DRAW_MATERIAL;
@ -32,11 +29,10 @@ void draw_material(G_RenderSig *sig, D_MaterialParams params)
gp_push_render_cmd(sig, &cmd); gp_push_render_cmd(sig, &cmd);
} }
/* ========================== * ////////////////////////////////
* Fill shapes //~ Solid shapes
* ========================== */
void draw_poly_ex(G_RenderSig *sig, Vec2Array vertices, G_Indices indices, u32 color) void D_DrawPolyEx(G_RenderSig *sig, Vec2Array vertices, G_Indices indices, u32 color)
{ {
G_RenderCmdDesc cmd = ZI; G_RenderCmdDesc cmd = ZI;
cmd.kind = GP_RENDER_CMD_KIND_DRAW_UI_SHAPE; cmd.kind = GP_RENDER_CMD_KIND_DRAW_UI_SHAPE;
@ -47,38 +43,40 @@ void draw_poly_ex(G_RenderSig *sig, Vec2Array vertices, G_Indices indices, u32 c
} }
/* Draws a filled polygon using triangles in a fan pattern */ /* Draws a filled polygon using triangles in a fan pattern */
void draw_poly(G_RenderSig *sig, Vec2Array vertices, u32 color) void D_DrawPoly(G_RenderSig *sig, Vec2Array vertices, u32 color)
{ {
if (vertices.count >= 3) { if (vertices.count >= 3)
{
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
u32 num_tris = vertices.count - 2; u32 num_tris = vertices.count - 2;
u32 num_indices = num_tris * 3; u32 num_indices = num_tris * 3;
/* Generate indices in a fan pattern */ /* Generate indices in a fan pattern */
G_Indices indices = { G_Indices indices = ZI;
.count = num_indices, indices.count = num_indices;
.indices = PushStructsNoZero(scratch.arena, u32, num_indices) indices.indices = PushStructsNoZero(scratch.arena, u32, num_indices);
}; for (u32 i = 0; i < num_tris; ++i)
for (u32 i = 0; i < num_tris; ++i) { {
u32 tri_offset = i * 3; u32 tri_offset = i * 3;
indices.indices[tri_offset + 0] = 0; indices.indices[tri_offset + 0] = 0;
indices.indices[tri_offset + 1] = (i + 1); indices.indices[tri_offset + 1] = (i + 1);
indices.indices[tri_offset + 2] = (i + 2); indices.indices[tri_offset + 2] = (i + 2);
} }
draw_poly_ex(sig, vertices, indices, color); D_DrawPolyEx(sig, vertices, indices, color);
EndScratch(scratch); EndScratch(scratch);
} }
} }
void draw_circle(G_RenderSig *sig, Vec2 pos, f32 radius, u32 color, u32 detail) void D_DrawCircle(G_RenderSig *sig, Vec2 pos, f32 radius, u32 color, u32 detail)
{ {
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
Vec2 *points = PushStructsNoZero(scratch.arena, Vec2, detail); Vec2 *points = PushStructsNoZero(scratch.arena, Vec2, detail);
for (u32 i = 0; i < detail; ++i) { for (u32 i = 0; i < detail; ++i)
{
f32 angle = ((f32)i / (f32)detail) * Tau; f32 angle = ((f32)i / (f32)detail) * Tau;
Vec2 p = VEC2( Vec2 p = VEC2(
radius * CosF32(angle), radius * CosF32(angle),
@ -91,12 +89,12 @@ void draw_circle(G_RenderSig *sig, Vec2 pos, f32 radius, u32 color, u32 detail)
.points = points, .points = points,
.count = detail .count = detail
}; };
draw_poly(sig, vertices, color); D_DrawPoly(sig, vertices, color);
EndScratch(scratch); EndScratch(scratch);
} }
void draw_quad(G_RenderSig *sig, Quad quad, u32 color) void D_DrawQuad(G_RenderSig *sig, Quad quad, u32 color)
{ {
LocalPersist u32 indices_array[6] = { LocalPersist u32 indices_array[6] = {
0, 1, 2, 0, 1, 2,
@ -104,62 +102,66 @@ void draw_quad(G_RenderSig *sig, Quad quad, u32 color)
}; };
Vec2Array vertices = { .count = 4, .points = quad.e }; Vec2Array vertices = { .count = 4, .points = quad.e };
G_Indices indices = { .count = 6, .indices = indices_array }; G_Indices indices = { .count = 6, .indices = indices_array };
draw_poly_ex(sig, vertices, indices, color); D_DrawPolyEx(sig, vertices, indices, color);
} }
/* ========================== * ////////////////////////////////
* Line shapes //~ Line shapes
* ========================== */
void draw_gradient_line(G_RenderSig *sig, Vec2 start, Vec2 end, f32 thickness, u32 start_color, u32 end_color) void D_DrawLineGradient(G_RenderSig *sig, Vec2 start, Vec2 end, f32 thickness, u32 start_color, u32 end_color)
{ {
#if 0 #if 0
D_SharedState *g = &D_shared_state;
Quad quad = QuadFromLine(start, end, thickness); Quad quad = QuadFromLine(start, end, thickness);
draw_material(sig, DRAW_MATERIAL_PARAMS(.texture = G.solid_white_texture, .tint0 = start_color, .tint1 = end_color, .quad = quad)); D_DrawMaterial(sig, D_MATERIALPARAMS(.texture = g->solid_white_texture, .tint0 = start_color, .tint1 = end_color, .quad = quad));
#else #else
/* Placeholder */ /* Placeholder */
(UNUSED)end_color; (UNUSED)end_color;
Quad quad = QuadFromLine(start, end, thickness); Quad quad = QuadFromLine(start, end, thickness);
draw_quad(sig, quad, start_color); D_DrawQuad(sig, quad, start_color);
#endif #endif
} }
void draw_line(G_RenderSig *sig, Vec2 start, Vec2 end, f32 thickness, u32 color) void D_DrawLine(G_RenderSig *sig, Vec2 start, Vec2 end, f32 thickness, u32 color)
{ {
Quad quad = QuadFromLine(start, end, thickness); Quad quad = QuadFromLine(start, end, thickness);
draw_quad(sig, quad, color); D_DrawQuad(sig, quad, color);
} }
void draw_ray(G_RenderSig *sig, Vec2 pos, Vec2 rel, f32 thickness, u32 color) void D_DrawRay(G_RenderSig *sig, Vec2 pos, Vec2 rel, f32 thickness, u32 color)
{ {
Quad quad = QuadFromRay(pos, rel, thickness); Quad quad = QuadFromRay(pos, rel, thickness);
draw_quad(sig, quad, color); D_DrawQuad(sig, quad, color);
} }
void draw_poly_line(G_RenderSig *sig, Vec2Array points, b32 loop, f32 thickness, u32 color) void D_DrawPolyLine(G_RenderSig *sig, Vec2Array points, b32 loop, f32 thickness, u32 color)
{ {
if (points.count >= 2) { if (points.count >= 2)
for (u64 i = 1; i < points.count; ++i) { {
for (u64 i = 1; i < points.count; ++i)
{
Vec2 p1 = points.points[i - 1]; Vec2 p1 = points.points[i - 1];
Vec2 p2 = points.points[i]; Vec2 p2 = points.points[i];
Quad q = QuadFromLine(p1, p2, thickness); Quad q = QuadFromLine(p1, p2, thickness);
draw_quad(sig, q, color); D_DrawQuad(sig, q, color);
} }
if (loop && points.count > 2) { if (loop && points.count > 2)
{
Vec2 p1 = points.points[points.count - 1]; Vec2 p1 = points.points[points.count - 1];
Vec2 p2 = points.points[0]; Vec2 p2 = points.points[0];
Quad q = QuadFromLine(p1, p2, thickness); Quad q = QuadFromLine(p1, p2, thickness);
draw_quad(sig, q, color); D_DrawQuad(sig, q, color);
} }
} }
} }
void draw_circle_line(G_RenderSig *sig, Vec2 pos, f32 radius, f32 thickness, u32 color, u32 detail) void D_DrawCircleLine(G_RenderSig *sig, Vec2 pos, f32 radius, f32 thickness, u32 color, u32 detail)
{ {
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
Vec2 *points = PushStructsNoZero(scratch.arena, Vec2, detail); Vec2 *points = PushStructsNoZero(scratch.arena, Vec2, detail);
for (u32 i = 0; i < detail; ++i) { for (u32 i = 0; i < detail; ++i)
{
f32 angle = ((f32)i / (f32)detail) * Tau; f32 angle = ((f32)i / (f32)detail) * Tau;
Vec2 p = VEC2( Vec2 p = VEC2(
radius * CosF32(angle), radius * CosF32(angle),
@ -172,19 +174,19 @@ void draw_circle_line(G_RenderSig *sig, Vec2 pos, f32 radius, f32 thickness, u32
.points = points, .points = points,
.count = detail .count = detail
}; };
draw_poly_line(sig, a, 1, thickness, color); D_DrawPolyLine(sig, a, 1, thickness, color);
EndScratch(scratch); EndScratch(scratch);
} }
void draw_quad_line(G_RenderSig *sig, Quad quad, f32 thickness, u32 color) void D_DrawQuadLine(G_RenderSig *sig, Quad quad, f32 thickness, u32 color)
{ {
Vec2 points[] = { quad.p0, quad.p1, quad.p2, quad.p3 }; Vec2 points[] = { quad.p0, quad.p1, quad.p2, quad.p3 };
Vec2Array a = { .points = points, .count = countof(points) }; Vec2Array a = { .points = points, .count = countof(points) };
draw_poly_line(sig, a, 1, thickness, color); D_DrawPolyLine(sig, a, 1, thickness, color);
} }
void draw_arrow_line(G_RenderSig *sig, Vec2 start, Vec2 end, f32 thickness, f32 arrowhead_height, u32 color) void D_DrawArrowLine(G_RenderSig *sig, Vec2 start, Vec2 end, f32 thickness, f32 arrowhead_height, u32 color)
{ {
const f32 head_width_ratio = 0.5f; /* Width of arrowhead relative to its length */ const f32 head_width_ratio = 0.5f; /* Width of arrowhead relative to its length */
@ -208,48 +210,52 @@ void draw_arrow_line(G_RenderSig *sig, Vec2 start, Vec2 end, f32 thickness, f32
.points = head_points, .points = head_points,
.count = countof(head_points) .count = countof(head_points)
}; };
draw_poly(sig, head_points_v2_array, color); D_DrawPoly(sig, head_points_v2_array, color);
Quad line_quad = QuadFromLine(start, head_start, thickness); Quad line_quad = QuadFromLine(start, head_start, thickness);
draw_quad(sig, line_quad, color); D_DrawQuad(sig, line_quad, color);
} }
void draw_arrow_ray(G_RenderSig *sig, Vec2 pos, Vec2 rel, f32 thickness, f32 arrowhead_height, u32 color) void D_DrawArrowRay(G_RenderSig *sig, Vec2 pos, Vec2 rel, f32 thickness, f32 arrowhead_height, u32 color)
{ {
Vec2 end = AddVec2(pos, rel); Vec2 end = AddVec2(pos, rel);
draw_arrow_line(sig, pos, end, thickness, arrowhead_height, color); D_DrawArrowLine(sig, pos, end, thickness, arrowhead_height, color);
} }
void draw_collider_line(G_RenderSig *sig, CLD_Shape shape, Xform shape_xf, f32 thickness, u32 color, u32 detail) void D_DrawColliderLine(G_RenderSig *sig, CLD_Shape shape, Xform shape_xf, f32 thickness, u32 color, u32 detail)
{ {
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
Vec2Array poly = ZI; Vec2Array poly = ZI;
if (shape.radius == 0) { if (shape.radius == 0)
{
poly.count = shape.count; poly.count = shape.count;
poly.points = PushStructsNoZero(scratch.arena, Vec2, shape.count); poly.points = PushStructsNoZero(scratch.arena, Vec2, shape.count);
for (u32 i = 0; i < shape.count; ++i) { for (u32 i = 0; i < shape.count; ++i)
{
Vec2 p = MulXformV2(shape_xf, shape.points[i]); Vec2 p = MulXformV2(shape_xf, shape.points[i]);
poly.points[i] = p; poly.points[i] = p;
} }
} else { }
else
{
poly.count = detail; poly.count = detail;
poly.points = PushStructsNoZero(scratch.arena, Vec2, detail); poly.points = PushStructsNoZero(scratch.arena, Vec2, detail);
for (u32 i = 0; i < detail; ++i) { for (u32 i = 0; i < detail; ++i)
{
f32 angle = ((f32)i / (f32)detail) * Tau; f32 angle = ((f32)i / (f32)detail) * Tau;
Vec2 dir = VEC2(CosF32(angle), SinF32(angle)); Vec2 dir = VEC2(CosF32(angle), SinF32(angle));
Vec2 p = CLD_SupportPointFromDir(&shape, shape_xf, dir).p; Vec2 p = CLD_SupportPointFromDir(&shape, shape_xf, dir).p;
poly.points[i] = p; poly.points[i] = p;
} }
} }
draw_poly_line(sig, poly, 1, thickness, color); D_DrawPolyLine(sig, poly, 1, thickness, color);
EndScratch(scratch); EndScratch(scratch);
} }
/* ========================== * ////////////////////////////////
* Grid //~ Grid
* ========================== */
void draw_grid(G_RenderSig *sig, Xform xf, u32 bg0_color, u32 bg1_color, u32 line_color, u32 x_color, u32 y_color, f32 thickness, f32 spacing, Vec2 offset) void D_DrawGrid(G_RenderSig *sig, Xform xf, u32 bg0_color, u32 bg1_color, u32 line_color, u32 x_color, u32 y_color, f32 thickness, f32 spacing, Vec2 offset)
{ {
i32 grid_id = 0; i32 grid_id = 0;
{ {
@ -274,11 +280,10 @@ void draw_grid(G_RenderSig *sig, Xform xf, u32 bg0_color, u32 bg1_color, u32 lin
gp_push_render_cmd(sig, &cmd); gp_push_render_cmd(sig, &cmd);
} }
/* ========================== * ////////////////////////////////
* UI //~ Ui
* ========================== */
void draw_ui_rect(G_RenderSig *sig, D_UiRectParams params) void D_DrawUiRect(G_RenderSig *sig, D_UiRectParams params)
{ {
G_RenderCmdDesc cmd = ZI; G_RenderCmdDesc cmd = ZI;
cmd.kind = GP_RENDER_CMD_KIND_DRAW_UI_RECT; cmd.kind = GP_RENDER_CMD_KIND_DRAW_UI_RECT;
@ -289,9 +294,8 @@ void draw_ui_rect(G_RenderSig *sig, D_UiRectParams params)
gp_push_render_cmd(sig, &cmd); gp_push_render_cmd(sig, &cmd);
} }
/* ========================== * ////////////////////////////////
* Text //~ Text
* ========================== */
/* Returns the rect of the text area */ /* Returns the rect of the text area */
Rect draw_text(G_RenderSig *sig, D_TextParams params) Rect draw_text(G_RenderSig *sig, D_TextParams params)
@ -302,55 +306,46 @@ Rect draw_text(G_RenderSig *sig, D_TextParams params)
f32 inv_font_image_height = 1.0 / (f32)params.font->image_height; f32 inv_font_image_height = 1.0 / (f32)params.font->image_height;
f32 line_spacing = params.font->point_size * 1.5f * params.scale; f32 line_spacing = params.font->point_size * 1.5f * params.scale;
/* ========================== * //- Build line glyphs
* Build line glyphs
* ========================== */
struct drawable_glyph {
f32 off_x;
f32 off_y;
f32 width;
f32 height;
f32 advance;
ClipRect clip;
};
struct drawable_line {
f32 line_width;
u32 num_glyphs;
struct drawable_glyph *glyphs;
struct drawable_line *next;
};
u64 num_lines = 0; u64 num_lines = 0;
f32 widest_line = 0; f32 widest_line = 0;
struct drawable_line *first_line = 0; D_TextLine *first_line = 0;
struct drawable_line *last_line = 0; D_TextLine *last_line = 0;
f32 first_line_top_offset = 0; f32 first_line_top_offset = 0;
f32 last_line_bottom_offset = 0; f32 last_line_bottom_offset = 0;
if (params.str.len > 0) { if (params.str.len > 0)
{
b32 string_done = 0; b32 string_done = 0;
CodepointIter iter = BeginCodepointIter(params.str); CodepointIter iter = BeginCodepointIter(params.str);
while (!string_done) { while (!string_done)
{
f32 line_width = 0; f32 line_width = 0;
f32 top_offset = 0; f32 top_offset = 0;
f32 bottom_offset = 0; f32 bottom_offset = 0;
u64 num_line_glyphs = 0; u64 num_line_glyphs = 0;
struct drawable_glyph *line_glyphs = PushDry(scratch.arena, struct drawable_glyph); D_TextGlyph *line_glyphs = PushDry(scratch.arena, D_TextGlyph);
b32 line_done = 0; b32 line_done = 0;
while (!line_done) { while (!line_done)
{
string_done = !AdvanceCodepointIter(&iter); string_done = !AdvanceCodepointIter(&iter);
if (string_done) { if (string_done)
{
line_done = 1; line_done = 1;
} else { }
else
{
u32 codepoint = iter.codepoint; u32 codepoint = iter.codepoint;
if (codepoint == '\n') { if (codepoint == '\n')
{
line_done = 1; line_done = 1;
} else { }
struct drawable_glyph *tg = PushStruct(scratch.arena, struct drawable_glyph); else
{
D_TextGlyph *tg = PushStruct(scratch.arena, D_TextGlyph);
++num_line_glyphs; ++num_line_glyphs;
F_Glyph *glyph = font_get_glyph(params.font, codepoint); F_Glyph *glyph = font_get_glyph(params.font, codepoint);
tg->off_x = glyph->off_x * params.scale; tg->off_x = glyph->off_x * params.scale;
@ -378,13 +373,16 @@ Rect draw_text(G_RenderSig *sig, D_TextParams params)
/* Line ended */ /* Line ended */
/* TODO: Only create nodes for non-empty lines. Embed line number in the node. */ /* TODO: Only create nodes for non-empty lines. Embed line number in the node. */
struct drawable_line *node = PushStruct(scratch.arena, struct drawable_line); D_TextLine *node = PushStruct(scratch.arena, D_TextLine);
node->line_width = line_width; node->line_width = line_width;
node->num_glyphs = num_line_glyphs; node->num_glyphs = num_line_glyphs;
node->glyphs = line_glyphs; node->glyphs = line_glyphs;
if (last_line) { if (last_line)
{
last_line->next = node; last_line->next = node;
} else { }
else
{
first_line = node; first_line = node;
first_line_top_offset = top_offset; first_line_top_offset = top_offset;
} }
@ -396,9 +394,7 @@ Rect draw_text(G_RenderSig *sig, D_TextParams params)
EndCodepointIter(&iter); EndCodepointIter(&iter);
} }
/* ========================== * //- Determine text bounds
* Determine text bounds
* ========================== */
Rect bounds = ZI; Rect bounds = ZI;
bounds.x = params.pos.x; bounds.x = params.pos.x;
@ -407,7 +403,8 @@ Rect draw_text(G_RenderSig *sig, D_TextParams params)
bounds.height = num_lines * line_spacing + first_line_top_offset + last_line_bottom_offset; bounds.height = num_lines * line_spacing + first_line_top_offset + last_line_bottom_offset;
/* Offset bounds X */ /* Offset bounds X */
switch (params.offset_x) { switch (params.offset_x)
{
case DRAW_TEXT_OFFSET_X_LEFT: break; case DRAW_TEXT_OFFSET_X_LEFT: break;
case DRAW_TEXT_OFFSET_X_CENTER: case DRAW_TEXT_OFFSET_X_CENTER:
{ {
@ -420,7 +417,8 @@ Rect draw_text(G_RenderSig *sig, D_TextParams params)
} }
/* Offset bounds Y */ /* Offset bounds Y */
switch (params.offset_y) { switch (params.offset_y)
{
case DRAW_TEXT_OFFSET_Y_TOP: break; case DRAW_TEXT_OFFSET_Y_TOP: break;
case DRAW_TEXT_OFFSET_Y_CENTER: case DRAW_TEXT_OFFSET_Y_CENTER:
{ {
@ -428,23 +426,24 @@ Rect draw_text(G_RenderSig *sig, D_TextParams params)
} break; } break;
case DRAW_TEXT_OFFSET_Y_BOTTOM: case DRAW_TEXT_OFFSET_Y_BOTTOM:
{ {
if (last_line) { if (last_line)
{
bounds.y -= bounds.height + last_line_bottom_offset; bounds.y -= bounds.height + last_line_bottom_offset;
} }
} break; } break;
} }
/* ========================== * //- Draw lines
* Draw lines
* ========================== */
u64 line_number = 0; u64 line_number = 0;
for (struct drawable_line *line = first_line; line; line = line->next) { for (D_TextLine *line = first_line; line; line = line->next)
{
Vec2 draw_pos = bounds.pos; Vec2 draw_pos = bounds.pos;
draw_pos.y += line_number * line_spacing - first_line_top_offset; draw_pos.y += line_number * line_spacing - first_line_top_offset;
/* Alignment */ /* Alignment */
switch (params.alignment) { switch (params.alignment)
{
case DRAW_TEXT_ALIGNMENT_LEFT: break; case DRAW_TEXT_ALIGNMENT_LEFT: break;
case DRAW_TEXT_ALIGNMENT_CENTER: case DRAW_TEXT_ALIGNMENT_CENTER:
{ {
@ -456,13 +455,14 @@ Rect draw_text(G_RenderSig *sig, D_TextParams params)
} break; } break;
} }
/* Draw glyphs */ /* Draw glyphs in line */
for (u64 i = 0; i < line->num_glyphs; ++i) { for (u64 i = 0; i < line->num_glyphs; ++i)
struct drawable_glyph *tg = &line->glyphs[i]; {
D_TextGlyph *tg = &line->glyphs[i];
Vec2 pos = VEC2(draw_pos.x + tg->off_x, draw_pos.y + tg->off_y); Vec2 pos = VEC2(draw_pos.x + tg->off_x, draw_pos.y + tg->off_y);
Vec2 size = VEC2(tg->width, tg->height); Vec2 size = VEC2(tg->width, tg->height);
Xform xf = XformFromRect(RectFromVec2(pos, size)); Xform xf = XformFromRect(RectFromVec2(pos, size));
draw_ui_rect(sig, DRAW_UI_RECT_PARAMS(.xf = xf, .texture = params.font->texture, .tint = params.color, .clip = tg->clip)); D_DrawUiRect(sig, D_UIRECTPARAMS(.xf = xf, .texture = params.font->texture, .tint = params.color, .clip = tg->clip));
draw_pos.x += tg->advance; draw_pos.x += tg->advance;
} }

View File

@ -1,17 +1,8 @@
Struct(D_StartupReceipt) { i32 _; }; ////////////////////////////////
D_StartupReceipt draw_startup(F_StartupReceipt *font_sr); //~ Material types
/* ========================== * Struct(D_MaterialParams)
* Material {
* ========================== */
#define DRAW_MATERIAL_PARAMS(...) ((D_MaterialParams) { \
.tint = ColorWhite, \
.clip = AllClipped, \
__VA_ARGS__ \
})
Struct(D_MaterialParams) {
Xform xf; Xform xf;
G_Resource *texture; G_Resource *texture;
ClipRect clip; ClipRect clip;
@ -19,83 +10,34 @@ Struct(D_MaterialParams) {
b32 is_light; b32 is_light;
Vec3 light_emittance; Vec3 light_emittance;
}; };
#define D_MATERIALPARAMS(...) ((D_MaterialParams) { \
void draw_material(G_RenderSig *sig, D_MaterialParams params);
/* ========================== *
* Fill shapes
* ========================== */
void draw_poly_ex(G_RenderSig *sig, Vec2Array vertices, G_Indices indices, 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);
void draw_quad(G_RenderSig *sig, Quad quad, u32 color);
/* ========================== *
* Line shapes
* ========================== */
void draw_gradient_line(G_RenderSig *sig, Vec2 start, Vec2 end, f32 thickness, u32 start_color, u32 end_color);
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, 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);
void draw_quad_line(G_RenderSig *sig, Quad quad, f32 thickness, u32 color);
void draw_arrow_line(G_RenderSig *sig, Vec2 start, Vec2 end, f32 thickness, f32 arrowhead_height, u32 color);
void draw_arrow_ray(G_RenderSig *sig, Vec2 pos, Vec2 rel, f32 thickness, f32 arrowhead_height, u32 color);
void draw_collider_line(G_RenderSig *sig, CLD_Shape shape, Xform shape_xf, f32 thickness, u32 color, u32 detail);
/* ========================== *
* Grid
* ========================== */
void draw_grid(G_RenderSig *sig, Xform xf, u32 bg0_color, u32 bg1_color, u32 line_color, u32 x_color, u32 y_color, f32 thickness, f32 spacing, Vec2 offset);
/* ========================== *
* UI
* ========================== */
#define DRAW_UI_RECT_PARAMS(...) ((D_UiRectParams) { \
.tint = ColorWhite, \ .tint = ColorWhite, \
.clip = AllClipped, \ .clip = AllClipped, \
__VA_ARGS__ \ __VA_ARGS__ \
}) })
Struct(D_UiRectParams) { ////////////////////////////////
//~ Ui types
Struct(D_UiRectParams)
{
Xform xf; Xform xf;
G_Resource *texture; G_Resource *texture;
ClipRect clip; ClipRect clip;
u32 tint; u32 tint;
}; };
#define D_UIRECTPARAMS(...) ((D_UiRectParams) { \
void draw_ui_rect(G_RenderSig *sig, D_UiRectParams params); .tint = ColorWhite, \
.clip = AllClipped, \
/* ========================== *
* Text
* ========================== */
#define DRAW_TEXT_PARAMS(...) ((D_TextParams) { \
.scale = 1.0, \
.alignment = DRAW_TEXT_ALIGNMENT_LEFT, \
.offset_x = DRAW_TEXT_OFFSET_X_LEFT, \
.offset_y = DRAW_TEXT_OFFSET_Y_TOP, \
.color = ColorWhite, \
__VA_ARGS__ \ __VA_ARGS__ \
}) })
////////////////////////////////
//~ Text types
/* How is text aligned within its area */ /* How is text aligned within its area */
typedef i32 D_TextAlignment; enum { typedef i32 D_TextAlignment; enum
{
DRAW_TEXT_ALIGNMENT_LEFT, /* Default */ DRAW_TEXT_ALIGNMENT_LEFT, /* Default */
DRAW_TEXT_ALIGNMENT_CENTER, DRAW_TEXT_ALIGNMENT_CENTER,
DRAW_TEXT_ALIGNMENT_RIGHT DRAW_TEXT_ALIGNMENT_RIGHT
@ -104,19 +46,40 @@ typedef i32 D_TextAlignment; enum {
/* How does the specified text position relate to the text area. /* How does the specified text position relate to the text area.
* E.g. BOTTOM & RIGHT means the bottom-right of the text area will snap to * E.g. BOTTOM & RIGHT means the bottom-right of the text area will snap to
* the specified position. */ * the specified position. */
typedef i32 D_TextOffsetX; enum { typedef i32 D_TextOffsetX; enum
{
DRAW_TEXT_OFFSET_X_LEFT, /* Default */ DRAW_TEXT_OFFSET_X_LEFT, /* Default */
DRAW_TEXT_OFFSET_X_CENTER, DRAW_TEXT_OFFSET_X_CENTER,
DRAW_TEXT_OFFSET_X_RIGHT DRAW_TEXT_OFFSET_X_RIGHT
}; };
typedef i32 D_TextOffsetY; enum { typedef i32 D_TextOffsetY; enum
{
DRAW_TEXT_OFFSET_Y_TOP, /* Default */ DRAW_TEXT_OFFSET_Y_TOP, /* Default */
DRAW_TEXT_OFFSET_Y_CENTER, DRAW_TEXT_OFFSET_Y_CENTER,
DRAW_TEXT_OFFSET_Y_BOTTOM DRAW_TEXT_OFFSET_Y_BOTTOM
}; };
Struct(D_TextParams) { Struct(D_TextGlyph)
{
f32 off_x;
f32 off_y;
f32 width;
f32 height;
f32 advance;
ClipRect clip;
};
Struct(D_TextLine)
{
f32 line_width;
u32 num_glyphs;
D_TextGlyph *glyphs;
D_TextLine *next;
};
Struct(D_TextParams)
{
F_Font *font; F_Font *font;
Vec2 pos; Vec2 pos;
f32 scale; f32 scale;
@ -126,5 +89,68 @@ Struct(D_TextParams) {
D_TextOffsetY offset_y; D_TextOffsetY offset_y;
String str; String str;
}; };
#define D_TEXTPARAMS(...) ((D_TextParams) { \
.scale = 1.0, \
.alignment = DRAW_TEXT_ALIGNMENT_LEFT, \
.offset_x = DRAW_TEXT_OFFSET_X_LEFT, \
.offset_y = DRAW_TEXT_OFFSET_Y_TOP, \
.color = ColorWhite, \
__VA_ARGS__ \
})
////////////////////////////////
//~ Shared state
Struct(D_SharedState)
{
G_Resource *solid_white_texture;
};
extern D_SharedState D_shared_state;
////////////////////////////////
//~ Startup
Struct(D_StartupReceipt) { i32 _; };
D_StartupReceipt D_Startup(F_StartupReceipt *font_sr);
////////////////////////////////
//~ Material operations
void D_DrawMaterial(G_RenderSig *sig, D_MaterialParams params);
////////////////////////////////
//~ Solid shape operations
void D_DrawPolyEx(G_RenderSig *sig, Vec2Array vertices, G_Indices indices, u32 color);
void D_DrawPoly(G_RenderSig *sig, Vec2Array points, u32 color);
void D_DrawCircle(G_RenderSig *sig, Vec2 pos, f32 radius, u32 color, u32 detail);
void D_DrawQuad(G_RenderSig *sig, Quad quad, u32 color);
////////////////////////////////
//~ Line shape operations
void D_DrawLineGradient(G_RenderSig *sig, Vec2 start, Vec2 end, f32 thickness, u32 start_color, u32 end_color);
void D_DrawLine(G_RenderSig *sig, Vec2 start, Vec2 end, f32 thickness, u32 color);
void D_DrawRay(G_RenderSig *sig, Vec2 pos, Vec2 rel, f32 thickness, u32 color);
void D_DrawPolyLine(G_RenderSig *sig, Vec2Array points, b32 loop, f32 thickness, u32 color);
void D_DrawCircleLine(G_RenderSig *sig, Vec2 pos, f32 radius, f32 thickness, u32 color, u32 detail);
void D_DrawQuadLine(G_RenderSig *sig, Quad quad, f32 thickness, u32 color);
void D_DrawArrowLine(G_RenderSig *sig, Vec2 start, Vec2 end, f32 thickness, f32 arrowhead_height, u32 color);
void D_DrawArrowRay(G_RenderSig *sig, Vec2 pos, Vec2 rel, f32 thickness, f32 arrowhead_height, u32 color);
void D_DrawColliderLine(G_RenderSig *sig, CLD_Shape shape, Xform shape_xf, f32 thickness, u32 color, u32 detail);
////////////////////////////////
//~ Grid operations
void D_DrawGrid(G_RenderSig *sig, Xform xf, u32 bg0_color, u32 bg1_color, u32 line_color, u32 x_color, u32 y_color, f32 thickness, f32 spacing, Vec2 offset);
////////////////////////////////
//~ Ui operations
void D_DrawUiRect(G_RenderSig *sig, D_UiRectParams params);
////////////////////////////////
//~ Text operations
Rect draw_text(G_RenderSig *sig, D_TextParams params); Rect draw_text(G_RenderSig *sig, D_TextParams params);

View File

@ -266,13 +266,13 @@ internal void debug_draw_xform(Xform xf, u32 color_x, u32 color_y)
x_ray = MulVec2(x_ray, ray_scale); x_ray = MulVec2(x_ray, ray_scale);
y_ray = MulVec2(y_ray, ray_scale); y_ray = MulVec2(y_ray, ray_scale);
draw_arrow_ray(G.render_sig, pos, x_ray, thickness, arrowhead_len, color_x); D_DrawArrowRay(G.render_sig, pos, x_ray, thickness, arrowhead_len, color_x);
draw_arrow_ray(G.render_sig, pos, y_ray, thickness, arrowhead_len, color_y); D_DrawArrowRay(G.render_sig, pos, y_ray, thickness, arrowhead_len, color_y);
//u32 color_quad = Rgba32F(0, 1, 1, 0.3); //u32 color_quad = Rgba32F(0, 1, 1, 0.3);
//Quad quad = QuadFromRect(RectFromScalar(0, 0, 1, -1)); //Quad quad = QuadFromRect(RectFromScalar(0, 0, 1, -1));
//quad = MulXformQuad(xf, ScaleQuad(quad, 0.075f)); //quad = MulXformQuad(xf, ScaleQuad(quad, 0.075f));
//draw_quad(G.render_sig, quad, color); //D_DrawQuad(G.render_sig, quad, color);
} }
internal void debug_draw_movement(Ent *ent) internal void debug_draw_movement(Ent *ent)
@ -289,7 +289,7 @@ internal void debug_draw_movement(Ent *ent)
Vec2 vel_ray = MulXformBasisV2(G.world_to_ui_xf, velocity); Vec2 vel_ray = MulXformBasisV2(G.world_to_ui_xf, velocity);
if (Vec2Len(vel_ray) > 0.00001) { if (Vec2Len(vel_ray) > 0.00001) {
draw_arrow_ray(G.render_sig, pos, vel_ray, thickness, arrow_len, color_vel); D_DrawArrowRay(G.render_sig, pos, vel_ray, thickness, arrow_len, color_vel);
} }
} }
@ -461,7 +461,7 @@ internal void draw_debug_console(i32 level, b32 minimized)
if (log->level <= level) { if (log->level <= level) {
/* Draw background */ /* Draw background */
u32 color = colors[log->level][log->color_index]; u32 color = colors[log->level][log->color_index];
draw_quad(G.render_sig, QuadFromRect(log->bounds), Alpha32F(color, opacity)); D_DrawQuad(G.render_sig, QuadFromRect(log->bounds), Alpha32F(color, opacity));
/* Draw text */ /* Draw text */
String text = log->msg; String text = log->msg;
@ -477,7 +477,7 @@ internal void draw_debug_console(i32 level, b32 minimized)
FmtString(text)); FmtString(text));
} }
D_TextParams params = DRAW_TEXT_PARAMS(.font = font, .pos = draw_pos, .offset_y = DRAW_TEXT_OFFSET_Y_BOTTOM, .color = Alpha32F(ColorWhite, opacity), .str = text); D_TextParams params = D_TEXTPARAMS(.font = font, .pos = draw_pos, .offset_y = DRAW_TEXT_OFFSET_Y_BOTTOM, .color = Alpha32F(ColorWhite, opacity), .str = text);
Rect bounds = draw_text(G.render_sig, params); Rect bounds = draw_text(G.render_sig, params);
Rect draw_bounds = bounds; Rect draw_bounds = bounds;
@ -1031,7 +1031,7 @@ internal void user_update(P_Window *window)
Vec2 size = InvertXformBasisMulV2(G.world_to_render_xf, G.render_size); Vec2 size = InvertXformBasisMulV2(G.world_to_render_xf, G.render_size);
u32 color0 = Rgba32F(0.17f, 0.17f, 0.17f, 1.f); u32 color0 = Rgba32F(0.17f, 0.17f, 0.17f, 1.f);
u32 color1 = Rgba32F(0.15f, 0.15f, 0.15f, 1.f); u32 color1 = Rgba32F(0.15f, 0.15f, 0.15f, 1.f);
draw_grid(G.render_sig, XformFromRect(RectFromVec2(pos, size)), color0, color1, Rgba32(0x3f, 0x3f, 0x3f, 0xFF), ColorRed, ColorGreen, thickness, spacing, offset); D_DrawGrid(G.render_sig, XformFromRect(RectFromVec2(pos, size)), color0, color1, Rgba32(0x3f, 0x3f, 0x3f, 0xFF), ColorRed, ColorGreen, thickness, spacing, offset);
} }
#if 0 #if 0
@ -1215,9 +1215,9 @@ internal void user_update(P_Window *window)
u32 color_end = Rgba32F(1, 0.8, 0.4, opacity_b); u32 color_end = Rgba32F(1, 0.8, 0.4, opacity_b);
if (opacity_b > 0.99f) { if (opacity_b > 0.99f) {
draw_circle(G.render_sig, b, thickness / 2, color_end, 20); D_DrawCircle(G.render_sig, b, thickness / 2, color_end, 20);
} }
draw_gradient_line(G.render_sig, a, b, thickness, color_start, color_end); D_DrawLineGradient(G.render_sig, a, b, thickness, color_start, color_end);
} }
#endif #endif
@ -1232,8 +1232,8 @@ internal void user_update(P_Window *window)
Vec3 emittance = ent->sprite_emittance; Vec3 emittance = ent->sprite_emittance;
u32 tint = ent->sprite_tint; u32 tint = ent->sprite_tint;
S_SheetFrame frame = sprite_sheet_get_frame(sheet, ent->animation_frame); S_SheetFrame frame = sprite_sheet_get_frame(sheet, ent->animation_frame);
D_MaterialParams params = DRAW_MATERIAL_PARAMS(.xf = sprite_xform, .texture = texture->gp_texture, .tint = tint, .clip = frame.clip, .is_light = is_light, .light_emittance = emittance); D_MaterialParams params = D_MATERIALPARAMS(.xf = sprite_xform, .texture = texture->gp_texture, .tint = tint, .clip = frame.clip, .is_light = is_light, .light_emittance = emittance);
draw_material(G.render_sig, params); D_DrawMaterial(G.render_sig, params);
} }
} }
@ -1254,8 +1254,8 @@ internal void user_update(P_Window *window)
Vec2I32 world_tile_index = sim_world_tile_index_from_local_tile_index(chunk_index, local_tile_index); Vec2I32 world_tile_index = sim_world_tile_index_from_local_tile_index(chunk_index, local_tile_index);
Vec2 pos = sim_pos_from_world_tile_index(world_tile_index); Vec2 pos = sim_pos_from_world_tile_index(world_tile_index);
Xform tile_xf = XformFromRect(RectFromVec2(pos, VEC2(tile_size, tile_size))); Xform tile_xf = XformFromRect(RectFromVec2(pos, VEC2(tile_size, tile_size)));
D_MaterialParams params = DRAW_MATERIAL_PARAMS(.xf = tile_xf, .texture = tile_texture->gp_texture, .is_light = 1, .light_emittance = VEC3(0, 0, 0)); D_MaterialParams params = D_MATERIALPARAMS(.xf = tile_xf, .texture = tile_texture->gp_texture, .is_light = 1, .light_emittance = VEC3(0, 0, 0));
draw_material(G.render_sig, params); D_DrawMaterial(G.render_sig, params);
} }
} }
} }
@ -1284,7 +1284,7 @@ internal void user_update(P_Window *window)
u32 color = Rgba32F(1, 0, 1, 0.5); u32 color = Rgba32F(1, 0, 1, 0.5);
Quad quad = QuadFromAabb(aabb); Quad quad = QuadFromAabb(aabb);
quad = MulXformQuad(G.world_to_ui_xf, quad); quad = MulXformQuad(G.world_to_ui_xf, quad);
draw_quad_line(G.render_sig, quad, thickness, color); D_DrawQuadLine(G.render_sig, quad, thickness, color);
} }
/* Draw focus arrow */ /* Draw focus arrow */
@ -1295,7 +1295,7 @@ internal void user_update(P_Window *window)
start = MulXformV2(G.world_to_ui_xf, start); start = MulXformV2(G.world_to_ui_xf, start);
Vec2 end = AddVec2(xf.og, ent->control.focus); Vec2 end = AddVec2(xf.og, ent->control.focus);
end = MulXformV2(G.world_to_ui_xf, end); end = MulXformV2(G.world_to_ui_xf, end);
draw_arrow_line(G.render_sig, start, end, 3, 10, Rgba32F(1, 1, 1, 0.5)); D_DrawArrowLine(G.render_sig, start, end, 3, 10, Rgba32F(1, 1, 1, 0.5));
} }
#if 0 #if 0
@ -1321,16 +1321,16 @@ internal void user_update(P_Window *window)
Quad quad = QuadFromRect(slice.rect); Quad quad = QuadFromRect(slice.rect);
quad = MulXformQuad(sprite_xform, quad); quad = MulXformQuad(sprite_xform, quad);
quad = MulXformQuad(G.world_to_ui_xf, quad); quad = MulXformQuad(G.world_to_ui_xf, quad);
draw_quad_line(G.render_sig, quad, 2, quad_color); D_DrawQuadLine(G.render_sig, quad, 2, quad_color);
} }
draw_circle(G.render_sig, center, 3, point_color, 20); D_DrawCircle(G.render_sig, center, 3, point_color, 20);
if (slice.has_ray) { if (slice.has_ray) {
Vec2 ray = MulXformBasisV2(sprite_xform, slice.dir); Vec2 ray = MulXformBasisV2(sprite_xform, slice.dir);
ray = MulXformBasisV2(G.world_to_ui_xf, ray); ray = MulXformBasisV2(G.world_to_ui_xf, ray);
ray = Vec2WithLen(ray, 25); ray = Vec2WithLen(ray, 25);
draw_arrow_ray(G.render_sig, center, ray, 2, 10, ray_color); D_DrawArrowRay(G.render_sig, center, ray, 2, 10, ray_color);
} }
} }
} }
@ -1347,7 +1347,7 @@ internal void user_update(P_Window *window)
f32 radius = 3; f32 radius = 3;
Vec2 point = MulXformV2(e1_xf, ent->weld_joint_data.point_local_e1); Vec2 point = MulXformV2(e1_xf, ent->weld_joint_data.point_local_e1);
point = MulXformV2(G.world_to_ui_xf, point); point = MulXformV2(G.world_to_ui_xf, point);
draw_circle(G.render_sig, point, radius, color, 10); D_DrawCircle(G.render_sig, point, radius, color, 10);
DEBUGBREAKABLE; DEBUGBREAKABLE;
} }
@ -1362,8 +1362,8 @@ internal void user_update(P_Window *window)
Vec2 point_end = G.world_cursor; Vec2 point_end = G.world_cursor;
point_start = MulXformV2(G.world_to_ui_xf, point_start); point_start = MulXformV2(G.world_to_ui_xf, point_start);
point_end = MulXformV2(G.world_to_ui_xf, point_end); point_end = MulXformV2(G.world_to_ui_xf, point_end);
draw_arrow_line(G.render_sig, point_start, point_end, 3, 10, color); D_DrawArrowLine(G.render_sig, point_start, point_end, 3, 10, color);
draw_circle(G.render_sig, point_start, 4, color, 10); D_DrawCircle(G.render_sig, point_start, 4, color, 10);
} }
/* Draw collider */ /* Draw collider */
@ -1375,13 +1375,13 @@ internal void user_update(P_Window *window)
/* Draw collider using support points */ /* Draw collider using support points */
u32 detail = 32; u32 detail = 32;
Xform collider_draw_xf = MulXform(G.world_to_ui_xf, xf); Xform collider_draw_xf = MulXform(G.world_to_ui_xf, xf);
draw_collider_line(G.render_sig, collider, collider_draw_xf, thickness, color, detail); D_DrawColliderLine(G.render_sig, collider, collider_draw_xf, thickness, color, detail);
} }
{ {
/* Draw collider shape points */ /* Draw collider shape points */
for (u32 i = 0; i < collider.count; ++i) { for (u32 i = 0; i < collider.count; ++i) {
Vec2 p = MulXformV2(MulXform(G.world_to_ui_xf, xf), collider.points[i]); Vec2 p = MulXformV2(MulXform(G.world_to_ui_xf, xf), collider.points[i]);
draw_circle(G.render_sig, p, 3, ColorBlue, 10); D_DrawCircle(G.render_sig, p, 3, ColorBlue, 10);
} }
} }
if (collider.count == 1 && collider.radius > 0) { if (collider.count == 1 && collider.radius > 0) {
@ -1390,14 +1390,14 @@ internal void user_update(P_Window *window)
Vec2 end = CLD_SupportPointFromDir(&collider, xf, NegVec2(xf.by)).p; Vec2 end = CLD_SupportPointFromDir(&collider, xf, NegVec2(xf.by)).p;
start = MulXformV2(G.world_to_ui_xf, start); start = MulXformV2(G.world_to_ui_xf, start);
end = MulXformV2(G.world_to_ui_xf, end); end = MulXformV2(G.world_to_ui_xf, end);
draw_line(G.render_sig, start, end, thickness, color); D_DrawLine(G.render_sig, start, end, thickness, color);
} }
#if 0 #if 0
/* Draw support point at focus dir */ /* Draw support point at focus dir */
{ {
Vec2 p = collider_support_point(&collider, xf, ent->control.focus); Vec2 p = collider_support_point(&collider, xf, ent->control.focus);
p = MulXformV2(G.world_to_ui_xf, p); p = MulXformV2(G.world_to_ui_xf, p);
draw_circle(G.render_sig, p, 3, ColorRed, 10); D_DrawCircle(G.render_sig, p, 3, ColorRed, 10);
} }
#endif #endif
} }
@ -1421,7 +1421,7 @@ internal void user_update(P_Window *window)
/* Draw point */ /* Draw point */
{ {
draw_circle(G.render_sig, MulXformV2(G.world_to_ui_xf, dbg_pt), radius, color, 10); D_DrawCircle(G.render_sig, MulXformV2(G.world_to_ui_xf, dbg_pt), radius, color, 10);
} }
/* Draw normal */ /* Draw normal */
@ -1431,7 +1431,7 @@ internal void user_update(P_Window *window)
f32 arrow_height = 5; f32 arrow_height = 5;
Vec2 start = MulXformV2(G.world_to_ui_xf, dbg_pt); Vec2 start = MulXformV2(G.world_to_ui_xf, dbg_pt);
Vec2 end = MulXformV2(G.world_to_ui_xf, AddVec2(dbg_pt, MulVec2(NormVec2(data->normal), len))); Vec2 end = MulXformV2(G.world_to_ui_xf, AddVec2(dbg_pt, MulVec2(NormVec2(data->normal), len)));
draw_arrow_line(G.render_sig, start, end, arrow_thickness, arrow_height, color); D_DrawArrowLine(G.render_sig, start, end, arrow_thickness, arrow_height, color);
} }
#if 0 #if 0
/* Draw contact info */ /* Draw contact info */
@ -1489,8 +1489,8 @@ internal void user_update(P_Window *window)
u32 color = Rgba32F(1, 1, 0, 0.5); u32 color = Rgba32F(1, 1, 0, 0.5);
Vec2 a = MulXformV2(G.world_to_ui_xf, data->closest0); Vec2 a = MulXformV2(G.world_to_ui_xf, data->closest0);
Vec2 b = MulXformV2(G.world_to_ui_xf, data->closest1); Vec2 b = MulXformV2(G.world_to_ui_xf, data->closest1);
draw_circle(G.render_sig, a, radius, color, 10); D_DrawCircle(G.render_sig, a, radius, color, 10);
draw_circle(G.render_sig, b, radius, color, 10); D_DrawCircle(G.render_sig, b, radius, color, 10);
} }
#endif #endif
@ -1507,28 +1507,28 @@ internal void user_update(P_Window *window)
{ {
Vec2 a = MulXformV2(G.world_to_ui_xf, collision_reuslt.a0); Vec2 a = MulXformV2(G.world_to_ui_xf, collision_reuslt.a0);
Vec2 b = MulXformV2(G.world_to_ui_xf, collision_reuslt.b0); Vec2 b = MulXformV2(G.world_to_ui_xf, collision_reuslt.b0);
draw_line(G.render_sig, a, b, thickness, color_line); D_DrawLine(G.render_sig, a, b, thickness, color_line);
draw_circle(G.render_sig, a, radius, color_a, 10); D_DrawCircle(G.render_sig, a, radius, color_a, 10);
draw_circle(G.render_sig, b, radius, color_b, 10); D_DrawCircle(G.render_sig, b, radius, color_b, 10);
Vec2 a_clipped = MulXformV2(G.world_to_ui_xf, collision_reuslt.a0_clipped); Vec2 a_clipped = MulXformV2(G.world_to_ui_xf, collision_reuslt.a0_clipped);
Vec2 b_clipped = MulXformV2(G.world_to_ui_xf, collision_reuslt.b0_clipped); Vec2 b_clipped = MulXformV2(G.world_to_ui_xf, collision_reuslt.b0_clipped);
draw_line(G.render_sig, a_clipped, b_clipped, thickness, color_line_clipped); D_DrawLine(G.render_sig, a_clipped, b_clipped, thickness, color_line_clipped);
draw_circle(G.render_sig, a_clipped, radius, color_a_clipped, 10); D_DrawCircle(G.render_sig, a_clipped, radius, color_a_clipped, 10);
draw_circle(G.render_sig, b_clipped, radius, color_b_clipped, 10); D_DrawCircle(G.render_sig, b_clipped, radius, color_b_clipped, 10);
} }
{ {
Vec2 a = MulXformV2(G.world_to_ui_xf, collision_reuslt.a1); Vec2 a = MulXformV2(G.world_to_ui_xf, collision_reuslt.a1);
Vec2 b = MulXformV2(G.world_to_ui_xf, collision_reuslt.b1); Vec2 b = MulXformV2(G.world_to_ui_xf, collision_reuslt.b1);
draw_line(G.render_sig, a, b, thickness, color_line); D_DrawLine(G.render_sig, a, b, thickness, color_line);
draw_circle(G.render_sig, a, radius, color_a, 10); D_DrawCircle(G.render_sig, a, radius, color_a, 10);
draw_circle(G.render_sig, b, radius, color_b, 10); D_DrawCircle(G.render_sig, b, radius, color_b, 10);
Vec2 a_clipped = MulXformV2(G.world_to_ui_xf, collision_reuslt.a1_clipped); Vec2 a_clipped = MulXformV2(G.world_to_ui_xf, collision_reuslt.a1_clipped);
Vec2 b_clipped = MulXformV2(G.world_to_ui_xf, collision_reuslt.b1_clipped); Vec2 b_clipped = MulXformV2(G.world_to_ui_xf, collision_reuslt.b1_clipped);
draw_line(G.render_sig, a_clipped, b_clipped, thickness, color_line_clipped); D_DrawLine(G.render_sig, a_clipped, b_clipped, thickness, color_line_clipped);
draw_circle(G.render_sig, a_clipped, radius, color_a_clipped, 10); D_DrawCircle(G.render_sig, a_clipped, radius, color_a_clipped, 10);
draw_circle(G.render_sig, b_clipped, radius, color_b_clipped, 10); D_DrawCircle(G.render_sig, b_clipped, radius, color_b_clipped, 10);
} }
} }
@ -1585,8 +1585,8 @@ internal void user_update(P_Window *window)
Vec2Array m = CLD_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]); 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); D_DrawPolyLine(G.render_sig, m, 1, thickness, color);
//draw_poly(G.render_sig, m, color); //D_DrawPoly(G.render_sig, m, color);
} }
/* Draw CLD_PointCloud */ /* Draw CLD_PointCloud */
@ -1598,7 +1598,7 @@ internal void user_update(P_Window *window)
for (u64 i = 0; i < m.count; ++i) { for (u64 i = 0; i < m.count; ++i) {
Vec2 p = MulXformV2(G.world_to_ui_xf, m.points[i]); Vec2 p = MulXformV2(G.world_to_ui_xf, m.points[i]);
draw_circle(G.render_sig, p, radius, color, 10); D_DrawCircle(G.render_sig, p, radius, color, 10);
} }
} }
@ -1612,8 +1612,8 @@ internal void user_update(P_Window *window)
.count = collision_reuslt.prototype.len .count = collision_reuslt.prototype.len
}; };
for (u64 i = 0; i < m.count; ++i) m.points[i] = MulXformV2(G.world_to_ui_xf, m.points[i]); 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); D_DrawPolyLine(G.render_sig, m, 1, thickness, color);
for (u64 i = 0; i < m.count; ++i) draw_circle(G.render_sig, m.points[i], 10, color, 10); for (u64 i = 0; i < m.count; ++i) D_DrawCircle(G.render_sig, m.points[i], 10, color, 10);
} }
/* Draw simplex */ /* Draw simplex */
@ -1631,18 +1631,18 @@ internal void user_update(P_Window *window)
if (simplex.len >= 1) { if (simplex.len >= 1) {
u32 color = simplex.len == 1 ? color_first : (simplex.len == 2 ? color_second : color_third); u32 color = simplex.len == 1 ? color_first : (simplex.len == 2 ? color_second : color_third);
draw_circle(G.render_sig, simplex_array.points[0], thickness * 3, color, 10); D_DrawCircle(G.render_sig, simplex_array.points[0], thickness * 3, color, 10);
} }
if (simplex.len >= 2) { if (simplex.len >= 2) {
u32 color = simplex.len == 2 ? color_first : color_second; u32 color = simplex.len == 2 ? color_first : color_second;
draw_circle(G.render_sig, simplex_array.points[1], thickness * 3, color, 10); D_DrawCircle(G.render_sig, simplex_array.points[1], thickness * 3, color, 10);
} }
if (simplex.len >= 3) { if (simplex.len >= 3) {
u32 color = color_first; u32 color = color_first;
draw_circle(G.render_sig, simplex_array.points[2], thickness * 3, color, 10); D_DrawCircle(G.render_sig, simplex_array.points[2], thickness * 3, color, 10);
} }
if (simplex.len >= 2) { if (simplex.len >= 2) {
draw_poly_line(G.render_sig, simplex_array, simplex.len > 2, thickness, line_color); D_DrawPolyLine(G.render_sig, simplex_array, simplex.len > 2, thickness, line_color);
} }
} }
@ -1654,7 +1654,7 @@ internal void user_update(P_Window *window)
f32 arrowhead_height = 10; f32 arrowhead_height = 10;
Vec2 start = MulXformV2(G.world_to_ui_xf, VEC2(0, 0)); Vec2 start = MulXformV2(G.world_to_ui_xf, VEC2(0, 0));
Vec2 end = MulXformV2(G.world_to_ui_xf, MulVec2(NormVec2(collision_reuslt.normal), len)); Vec2 end = MulXformV2(G.world_to_ui_xf, MulVec2(NormVec2(collision_reuslt.normal), len));
draw_arrow_line(G.render_sig, start, end, arrow_thickness, arrowhead_height, color); D_DrawArrowLine(G.render_sig, start, end, arrow_thickness, arrowhead_height, color);
} }
} }
#endif #endif
@ -1669,7 +1669,7 @@ internal void user_update(P_Window *window)
Vec2 start = MulXformV2(G.world_to_ui_xf, xf.og); Vec2 start = MulXformV2(G.world_to_ui_xf, xf.og);
Vec2 end = MulXformV2(G.world_to_ui_xf, parent_xf.og); Vec2 end = MulXformV2(G.world_to_ui_xf, parent_xf.og);
draw_arrow_line(G.render_sig, start, end, thickness, arrow_height, color); D_DrawArrowLine(G.render_sig, start, end, thickness, arrow_height, color);
} }
/* Draw camera rect */ /* Draw camera rect */
@ -1681,7 +1681,7 @@ internal void user_update(P_Window *window)
Quad quad = MulXformQuad(quad_xf, CenteredUnitSquareQuad); Quad quad = MulXformQuad(quad_xf, CenteredUnitSquareQuad);
quad = MulXformQuad(G.world_to_ui_xf, quad); quad = MulXformQuad(G.world_to_ui_xf, quad);
draw_quad_line(G.render_sig, quad, thickness, color); D_DrawQuadLine(G.render_sig, quad, thickness, color);
} }
EndTempArena(temp); EndTempArena(temp);
@ -1697,7 +1697,7 @@ internal void user_update(P_Window *window)
S_Texture *t = sprite_texture_from_tag_async(sprite_frame_scope, crosshair); S_Texture *t = sprite_texture_from_tag_async(sprite_frame_scope, crosshair);
Vec2 size = VEC2(t->width, t->height); Vec2 size = VEC2(t->width, t->height);
Xform xf = XformFromTrs(TRS(.t = crosshair_pos, .s = size)); Xform xf = XformFromTrs(TRS(.t = crosshair_pos, .s = size));
draw_ui_rect(G.render_sig, DRAW_UI_RECT_PARAMS(.xf = xf, .texture = t->gp_texture)); D_DrawUiRect(G.render_sig, D_UIRECTPARAMS(.xf = xf, .texture = t->gp_texture));
} }
/* FIXME: Enable this */ /* FIXME: Enable this */
@ -1909,7 +1909,7 @@ internal void user_update(P_Window *window)
String dbg_text = ZI; String dbg_text = ZI;
dbg_text.text = PushDry(temp.arena, u8); dbg_text.text = PushDry(temp.arena, u8);
dbg_text.len += get_ent_debug_text(temp.arena, ent).len; dbg_text.len += get_ent_debug_text(temp.arena, ent).len;
draw_text(G.render_sig, DRAW_TEXT_PARAMS(.font = font, .pos = pos, .str = dbg_text)); draw_text(G.render_sig, D_TEXTPARAMS(.font = font, .pos = pos, .str = dbg_text));
EndTempArena(temp); EndTempArena(temp);
} }
@ -2029,7 +2029,7 @@ internal void user_update(P_Window *window)
Vec2 pos = VEC2(10, G.ui_size.y); Vec2 pos = VEC2(10, G.ui_size.y);
D_TextOffsetY offset_y = DRAW_TEXT_OFFSET_Y_BOTTOM; D_TextOffsetY offset_y = DRAW_TEXT_OFFSET_Y_BOTTOM;
draw_text(G.render_sig, DRAW_TEXT_PARAMS(.font = font, .pos = pos, .str = text, .offset_y = offset_y, .color = ColorWhite)); draw_text(G.render_sig, D_TEXTPARAMS(.font = font, .pos = pos, .str = text, .offset_y = offset_y, .color = ColorWhite));
EndTempArena(temp); EndTempArena(temp);
} }
} }