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();
M_StartupReceipt mixer_sr = mixer_startup();
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();
/* Interface systems */

View File

@ -9,6 +9,7 @@
Struct(Vec2) {
f32 x, y;
};
#define VEC2(x, y) CppCompatInitListType(Vec2) { (x), (y) }
Struct(Vec2Array) {
Vec2 *points;
@ -21,6 +22,7 @@ Struct(Vec2Array) {
Struct(Vec3) {
f32 x, y, z;
};
#define VEC3(x, y, z) CppCompatInitListType(Vec3) { (x), (y), (z) }
Struct(Vec3Array) {
Vec3 *points;
@ -33,6 +35,7 @@ Struct(Vec3Array) {
Struct(Vec4) {
f32 x, y, z, w;
};
#define VEC4(x, y, z, w) ((Vec4) { (x), (y), (z), (w) })
Struct(Vec4Array) {
Vec4 *points;
@ -45,6 +48,7 @@ Struct(Vec4Array) {
Struct(Vec2I32) {
i32 x, y;
};
#define VEC2I32(x, y) CppCompatInitListType(Vec2I32) { (x), (y) }
////////////////////////////////
//~ Integer vector3 types
@ -52,6 +56,7 @@ Struct(Vec2I32) {
Struct(Vec3I32) {
i32 x, y, z;
};
#define VEC3I32(x, y, z) CppCompatInitListType(Vec3I32) { (x), (y), (z) }
////////////////////////////////
//~ Xform types
@ -245,7 +250,6 @@ i64 LerpI64(i64 val0, i64 val1, f64 t);
////////////////////////////////
//~ Vec2 operations
#define VEC2(x, y) CppCompatInitListType(Vec2) { (x), (y) }
#define Vec2FromVec2I32(v) VEC2((v).x, (v).y)
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 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
#define VEC2I32(x, y) CppCompatInitListType(Vec2I32) { (x), (y) }
b32 EqVec2I32(Vec2I32 a, Vec2I32 b);
Vec2I32 NegVec2I32(Vec2I32 a);
Vec2I32 AddVec2I32(Vec2I32 a, Vec2I32 b);
Vec2I32 SubVec2I32(Vec2I32 a, Vec2I32 b);
////////////////////////////////
//~ Vec3I32 operations
#define VEC3I32(x, y, z) CppCompatInitListType(Vec3I32) { (x), (y), (z) }
////////////////////////////////
//~ Xform operations

View File

@ -28,7 +28,7 @@ CLD_Shape CLD_ShapeFromQuad(Quad quad)
////////////////////////////////
//~ 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;
u32 count = shape->count;
@ -37,7 +37,8 @@ CLD_SupportPoint CLD_SupportPointFromDirInternal(CLD_Shape *shape, Xform xf, Vec
dir = RotateVec2(dir, -RotationFromXform(xf));
dir = MulVec2Vec2(dir, ScaleFromXform(xf));
if (count == 1) {
if (count == 1)
{
/* Skip 'ignore' on single point colliders */
ignore = -1;
}
@ -45,20 +46,24 @@ CLD_SupportPoint CLD_SupportPointFromDirInternal(CLD_Shape *shape, Xform xf, Vec
Vec2 furthest = ZI;
u32 furthest_index = 0;
f32 furthest_dot = -F32Infinity;
for (u32 i = 0; i < count; ++i) {
if ((i32)i == ignore) {
for (u32 i = 0; i < count; ++i)
{
if ((i32)i == ignore)
{
continue;
}
Vec2 p = points[i];
f32 dot = DotVec2(dir, p);
if (dot > furthest_dot) {
if (dot > furthest_dot)
{
furthest = p;
furthest_dot = dot;
furthest_index = i;
}
}
if (radius > 0.0) {
if (radius > 0.0)
{
dir = Vec2WithLen(dir, radius);
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)
{
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)
@ -119,7 +124,7 @@ b32 CLD_TestAabb(Aabb box0, Aabb box1)
f32 b1_y0 = box1.p0.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)) &&
((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_b = ZI;
u32 num_removed = 0;
for (;;) {
if (s.len == 1) {
for (;;)
{
if (s.len == 1)
{
//- Find second point in simplex
/* Second point is support point towards origin */
dir = NegVec2(s.a.p);
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) {
if (Vec2LenSq(SubVec2(m.p, s.a.p)) < min_unique_pt_dist_sq)
{
overlapping = 0;
break;
}
@ -172,6 +181,7 @@ CLD_GjkData CLD_GjkDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf
}
{
//- Find third point in simplex
CLD_DBGSTEP;
m = CLD_MenkowskiPointFromDir(shape0, shape1, xf0, xf1, dir);
/* 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) ||
(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;
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) ||
(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 */
overlapping = 1;
break;
}
}
/* Determine region of the simplex in which the origin lies */
//- Determine region of the simplex in which the origin lies
CLD_DBGSTEP;
Vec2 vab = SubVec2(s.b.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 vbc_dot = DotVec2(vbc, NegVec2(s.b.p)) / Vec2LenSq(vbc);
if (rab_dot >= 0 && vab_dot >= 0 && vab_dot <= 1) {
/* Region ab, remove c */
if (rab_dot >= 0 && vab_dot >= 0 && vab_dot <= 1)
{
//- Region ab, remove c
num_removed = 1;
removed_a = s.c.p;
s.len = 2;
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;
removed_a = s.b.p;
s.len = 2;
s.b = s.c;
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;
removed_a = s.a.p;
s.len = 2;
s.a = s.b;
s.b = s.c;
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;
removed_a = s.b.p;
removed_b = s.c.p;
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;
removed_a = s.a.p;
removed_b = s.c.p;
s.len = 1;
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;
removed_a = s.a.p;
removed_b = s.b.p;
s.len = 1;
s.a = s.c;
} else {
}
else
{
/* No region, must be in simplex */
overlapping = 1;
break;
@ -267,7 +292,7 @@ CLD_GjkData CLD_GjkDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf
}
#if COLLIDER_DEBUG
abort:
abort :
#endif
CLD_GjkData result = {
@ -302,7 +327,8 @@ CLD_EpaData CLD_EpaDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf
CLD_MenkowskiPoint *proto = 0;
u32 proto_count = 0;
if (gjk_result.overlapping) {
if (gjk_result.overlapping)
{
CLD_MenkowskiSimplex s = gjk_result.simplex;
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));
u32 epa_iterations = 0;
for (;;) {
for (;;)
{
++epa_iterations;
/* 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_b = ZI;
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 b_index = (i < proto_count - 1) ? (i + 1) : 0;
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));
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_b = b;
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);
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 */
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 */
valid = 0;
}
}
if (!valid || epa_iterations >= max_iterations) {
if (!valid || epa_iterations >= max_iterations)
{
normal = NormVec2(dir);
closest_feature.a = closest_a;
closest_feature.b = closest_b;
@ -401,7 +434,8 @@ CLD_EpaData CLD_EpaDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf
++proto_count;
/* 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_to = i;
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 */
proto[closest_b_index] = m;
}
} else {
}
else
{
normal = NormVec2(gjk_result.final_dir);
closest_feature.len = gjk_result.simplex.len;
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
abort:
abort :
#endif
CLD_EpaData result = {
@ -429,7 +465,8 @@ CLD_EpaData CLD_EpaDataFromShapes(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf
#if COLLIDER_DEBUG
result.dbg_step = dbg_step;
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.len = len;
@ -538,32 +575,41 @@ CLD_CollisionData CLD_CollisionDataFromShapes(CLD_Shape *shape0, CLD_Shape *shap
CLD_DBGSTEP;
/* Determine collision */
if (gjk_result.overlapping) {
if (gjk_result.overlapping)
{
colliding = 1;
} else {
}
else
{
CLD_MenkowskiFeature f = epa_result.closest_feature;
/* Shapes not overlapping, determine if distance between shapes within tolerance */
if (f.len == 1) {
if (f.len == 1)
{
Vec2 p = NegVec2(f.a.p);
if (Vec2LenSq(p) <= (tolerance * tolerance)) {
if (Vec2LenSq(p) <= (tolerance * tolerance))
{
colliding = 1;
}
} else {
}
else
{
/* Project origin to determine if distance is within tolerance. */
Assert(f.len == 2);
Vec2 vab = SubVec2(f.b.p, f.a.p);
Vec2 vao = NegVec2(f.a.p);
f32 ratio = ClampF32(DotVec2(vab, vao) / DotVec2(vab, vab), 0, 1);
Vec2 p = AddVec2(f.a.p, MulVec2(vab, ratio));
if (Vec2LenSq(p) <= (tolerance * tolerance)) {
if (Vec2LenSq(p) <= (tolerance * tolerance))
{
colliding = 1;
}
}
}
/* Clip to determine final points */
if (colliding) {
/* Max vertices must be < 16 to fit in 4 bit ids */
if (colliding)
{
/* Max vertices must be < 16 to fit in 4 bit ids */
StaticAssert(countof(shape0->points) <= 16);
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 b1 = f.b.s1;
/* FIXME: Manually account for shapes w/ 1 & 2 points */
if (f.len == 2) {
if (a0.i == b0.i) {
if (shape0->count > 1) {
b0 = CLD_SupportPointFromDirInternal(shape0, xf0, normal, b0.i);
} else {
if (f.len == 2)
{
if (a0.i == b0.i)
{
if (shape0->count > 1)
{
b0 = CLD_SupportPointFromDirEx(shape0, xf0, normal, b0.i);
}
else
{
collapse0 = 1;
b0 = a0;
}
}
if (a1.i == b1.i) {
if (shape1->count > 1) {
b1 = CLD_SupportPointFromDirInternal(shape1, xf1, NegVec2(normal), b1.i);
} else {
if (a1.i == b1.i)
{
if (shape1->count > 1)
{
b1 = CLD_SupportPointFromDirEx(shape1, xf1, NegVec2(normal), b1.i);
}
else
{
collapse1 = 1;
b1 = a1;
}
}
} else {
}
else
{
collapse0 = 1;
collapse1 = 1;
b0 = a0;
@ -607,13 +664,15 @@ CLD_CollisionData CLD_CollisionDataFromShapes(CLD_Shape *shape0, CLD_Shape *shap
Vec2 vab1_norm = NormVec2(vab1);
/* Swap points based on normal direction for consistent clipping */
if (WedgeVec2(normal, vab0) < 0) {
if (WedgeVec2(normal, vab0) < 0)
{
CLD_SupportPoint tmp = a0;
a0 = b0;
b0 = tmp;
vab0 = NegVec2(vab0);
}
if (WedgeVec2(normal, vab1) < 0) {
if (WedgeVec2(normal, vab1) < 0)
{
CLD_SupportPoint tmp = a1;
a1 = b1;
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;
/* Collapse lines into deepest point */
if (collapse0) {
if (DotVec2(normal, vab0) > 0) {
if (collapse0)
{
if (DotVec2(normal, vab0) > 0)
{
a0 = b0;
} else {
}
else
{
/* TODO: Remove this (debugging) */
b0 = a0;
}
}
if (collapse1) {
if (DotVec2(normal, vab1) < 0) {
if (collapse1)
{
if (DotVec2(normal, vab1) < 0)
{
a1 = b1;
} else {
}
else
{
/* TODO: Remove this (debugging) */
b1 = a1;
}
@ -649,7 +716,8 @@ CLD_CollisionData CLD_CollisionDataFromShapes(CLD_Shape *shape0, CLD_Shape *shap
Vec2 b_midpoint = ZI;
b32 ignore_a = 1;
b32 ignore_b = 1;
if (!collapse0 && !collapse1) {
if (!collapse0 && !collapse1)
{
/* Clip line to line */
CLD_ClippedLine clip_result = CLD_ClipLineToLine(a0.p, b0.p, a1.p, b1.p, normal);
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_b = 0;
Vec2 vfin = SubVec2(b_midpoint, a_midpoint);
if (Vec2LenSq(vfin) < (0.005 * 0.005)) {
if (a_sep > b_sep) {
if (Vec2LenSq(vfin) < (0.005 * 0.005))
{
if (a_sep > b_sep)
{
ignore_a = 1;
} else {
}
else
{
ignore_b = 1;
}
}
@ -677,15 +749,19 @@ CLD_CollisionData CLD_CollisionDataFromShapes(CLD_Shape *shape0, CLD_Shape *shap
result.a1_clipped = a1_clipped;
result.b0_clipped = b0_clipped;
result.b1_clipped = b1_clipped;
} else {
}
else
{
Vec2 p0 = a0.p;
Vec2 p1 = a1.p;
/* TODO: Choose ID based on closest clipped point */
if (collapse1 && !collapse0) {
if (collapse1 && !collapse0)
{
/* Project a1 onto vab0 */
p0 = CLD_ClipPointToLine(a0.p, b0.p, a1.p, normal);
}
if (collapse0 && !collapse1) {
if (collapse0 && !collapse1)
{
/* Project a0 onto vab1 */
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 */
if (!ignore_a && a_sep < tolerance) {
if (!ignore_a && a_sep < tolerance)
{
CLD_CollisionPoint *point = &points[num_points++];
point->id = a0.i | (a1.i << 4);
point->separation = a_sep;
point->point = a_midpoint;
}
if (!ignore_b && b_sep < tolerance) {
if (!ignore_b && b_sep < tolerance)
{
CLD_CollisionPoint *point = &points[num_points++];
point->id = b0.i | (b1.i << 4);
point->separation = b_sep;
@ -723,7 +801,7 @@ CLD_CollisionData CLD_CollisionDataFromShapes(CLD_Shape *shape0, CLD_Shape *shap
#if COLLIDER_DEBUG
result.solved = 1;
abort:
abort:
result.simplex = gjk_result.simplex;
result.prototype.len = epa_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;
CLD_MenkowskiFeature f = epa_result.closest_feature;
if (f.len == 1) {
if (f.len == 1)
{
p0 = f.a.s0.p;
p1 = f.a.s1.p;
colliding = gjk_result.overlapping || Vec2LenSq(NegVec2(f.a.p)) <= (tolerance * tolerance);
} else {
}
else
{
Assert(f.len == 2);
/* FIXME: Winding order dependent? */
f32 ratio;
@ -810,10 +891,10 @@ CLD_ClosestPointData CLD_ClosestPointDataFromShapes(CLD_Shape *shape0, CLD_Shape
#if COLLIDER_DEBUG
result.solved = 1;
abort:
abort:
result.simplex = gjk_result.simplex;
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;
#endif
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;
{
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 */
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 p1 = CLD_SupportPointFromDir(c1, xf1_t1, dir_neg).p;
t1_sep = DotVec2(dir, SubVec2(p1, p0));
if (t1_sep > 0) {
if (t1_sep > 0)
{
/* Shapes are not penetrating at t=1 */
return 1;
}
}
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
* (as described in https://box2d.org/files/ErinCatto_ContinuousCollision_GDC2013.pdf) */
if (iteration & 1) {
if (iteration & 1)
{
/* Bisect */
t = (t1 + t0) / 2.0;
} else {
}
else
{
/* False position (fastest for linear case) */
f32 m = (t1_sep - t0_sep) / (t1 - t0);
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));
/* Update bracket */
if (t_sep > 0) {
if (t_sep > 0)
{
t0 = t;
t0_sep = t_sep;
} else {
}
else
{
t1 = t;
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 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);
Vec2 dir = Vec2FromAngle(angle);
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;
++result.count;
}
@ -924,9 +1016,11 @@ Vec2Array CLD_PointCloud(Arena *arena, CLD_Shape *shape0, CLD_Shape *shape1, Xfo
Vec2 *points1 = shape1->points;
u32 count0 = shape0->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]);
for (u64 j = 0; j < count1; ++j) {
for (u64 j = 0; j < count1; ++j)
{
Vec2 p1 = MulXformV2(xf1, points1[j]);
*PushStructNoZero(arena, Vec2) = SubVec2(p0, p1);
++result.count;
@ -954,14 +1048,17 @@ b32 CLD_GjkBoolean(CLD_Shape *shape0, CLD_Shape *shape1)
/* Second point is support point towards origin */
dir = NegVec2(s.a);
p = CLD_MenkowskiPointFromDir(shape0, shape1, dir);
if (DotVec2(dir, p) >= 0) {
if (DotVec2(dir, p) >= 0)
{
s.b = s.a;
s.a = p;
for (;;) {
for (;;)
{
/* Third point is support point in direction of line normal towards origin */
dir = PerpVec2TowardsDir(SubVec2(s.b, s.a), NegVec2(s.a));
p = CLD_MenkowskiPointFromDir(shape0, shape1, dir);
if (DotVec2(dir, p) < 0) {
if (DotVec2(dir, p) < 0)
{
/* New point did not cross origin, collision impossible */
break;
}
@ -975,15 +1072,21 @@ b32 CLD_GjkBoolean(CLD_Shape *shape0, CLD_Shape *shape1)
Vec2 a_to_origin = NegVec2(s.a);
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) */
} else {
}
else
{
/* Point is not in region ab */
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 */
s.b = s.c;
} else {
}
else
{
/* Point is in simplex */
return 1;
}

View File

@ -19,9 +19,9 @@ Struct(CLD_SupportPoint)
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 */
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)
@ -82,7 +82,8 @@ Struct(CLD_ClosestPointData)
////////////////////////////////
//~ Clipping types
Struct(CLD_ClippedLine) {
Struct(CLD_ClippedLine)
{
Vec2 a0_clipped, b0_clipped;
Vec2 a1_clipped, b1_clipped;
};
@ -158,7 +159,7 @@ CLD_Shape CLD_ShapeFromQuad(Quad quad);
////////////////////////////////
//~ 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_MenkowskiPoint CLD_MenkowskiPointFromDir(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, Vec2 dir);

View File

@ -1,25 +1,22 @@
Global struct {
G_Resource *solid_white_texture;
} G = ZI, DebugAlias(G, G_draw);
D_SharedState D_shared_state = ZI;
/* ========================== *
* Startup
* ========================== */
////////////////////////////////
//~ Startup
D_StartupReceipt draw_startup(F_StartupReceipt *font_sr)
D_StartupReceipt D_Startup(F_StartupReceipt *font_sr)
{
__prof;
D_SharedState *g = &D_shared_state;
(UNUSED)font_sr;
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 };
}
/* ========================== *
* Material
* ========================== */
////////////////////////////////
//~ Material
void draw_material(G_RenderSig *sig, D_MaterialParams params)
void D_DrawMaterial(G_RenderSig *sig, D_MaterialParams params)
{
G_RenderCmdDesc cmd = ZI;
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);
}
/* ========================== *
* 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;
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 */
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();
u32 num_tris = vertices.count - 2;
u32 num_indices = num_tris * 3;
/* Generate indices in a fan pattern */
G_Indices indices = {
.count = num_indices,
.indices = PushStructsNoZero(scratch.arena, u32, num_indices)
};
for (u32 i = 0; i < num_tris; ++i) {
G_Indices indices = ZI;
indices.count = num_indices;
indices.indices = PushStructsNoZero(scratch.arena, u32, num_indices);
for (u32 i = 0; i < num_tris; ++i)
{
u32 tri_offset = i * 3;
indices.indices[tri_offset + 0] = 0;
indices.indices[tri_offset + 1] = (i + 1);
indices.indices[tri_offset + 2] = (i + 2);
}
draw_poly_ex(sig, vertices, indices, color);
D_DrawPolyEx(sig, vertices, indices, color);
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();
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;
Vec2 p = VEC2(
radius * CosF32(angle),
@ -91,12 +89,12 @@ void draw_circle(G_RenderSig *sig, Vec2 pos, f32 radius, u32 color, u32 detail)
.points = points,
.count = detail
};
draw_poly(sig, vertices, color);
D_DrawPoly(sig, vertices, color);
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] = {
0, 1, 2,
@ -104,62 +102,66 @@ void draw_quad(G_RenderSig *sig, Quad quad, u32 color)
};
Vec2Array vertices = { .count = 4, .points = quad.e };
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
D_SharedState *g = &D_shared_state;
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
/* Placeholder */
(UNUSED)end_color;
Quad quad = QuadFromLine(start, end, thickness);
draw_quad(sig, quad, start_color);
D_DrawQuad(sig, quad, start_color);
#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);
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);
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) {
for (u64 i = 1; i < points.count; ++i) {
if (points.count >= 2)
{
for (u64 i = 1; i < points.count; ++i)
{
Vec2 p1 = points.points[i - 1];
Vec2 p2 = points.points[i];
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 p2 = points.points[0];
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();
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;
Vec2 p = VEC2(
radius * CosF32(angle),
@ -172,19 +174,19 @@ void draw_circle_line(G_RenderSig *sig, Vec2 pos, f32 radius, f32 thickness, u32
.points = points,
.count = detail
};
draw_poly_line(sig, a, 1, thickness, color);
D_DrawPolyLine(sig, a, 1, thickness, color);
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 };
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 */
@ -208,48 +210,52 @@ void draw_arrow_line(G_RenderSig *sig, Vec2 start, Vec2 end, f32 thickness, f32
.points = 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);
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);
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();
Vec2Array poly = ZI;
if (shape.radius == 0) {
if (shape.radius == 0)
{
poly.count = 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]);
poly.points[i] = p;
}
} else {
}
else
{
poly.count = 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;
Vec2 dir = VEC2(CosF32(angle), SinF32(angle));
Vec2 p = CLD_SupportPointFromDir(&shape, shape_xf, dir).p;
poly.points[i] = p;
}
}
draw_poly_line(sig, poly, 1, thickness, color);
D_DrawPolyLine(sig, poly, 1, thickness, color);
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;
{
@ -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);
}
/* ========================== *
* 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;
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);
}
/* ========================== *
* Text
* ========================== */
////////////////////////////////
//~ Text
/* Returns the rect of the text area */
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 line_spacing = params.font->point_size * 1.5f * params.scale;
/* ========================== *
* 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;
};
//- Build line glyphs
u64 num_lines = 0;
f32 widest_line = 0;
struct drawable_line *first_line = 0;
struct drawable_line *last_line = 0;
D_TextLine *first_line = 0;
D_TextLine *last_line = 0;
f32 first_line_top_offset = 0;
f32 last_line_bottom_offset = 0;
if (params.str.len > 0) {
if (params.str.len > 0)
{
b32 string_done = 0;
CodepointIter iter = BeginCodepointIter(params.str);
while (!string_done) {
while (!string_done)
{
f32 line_width = 0;
f32 top_offset = 0;
f32 bottom_offset = 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;
while (!line_done) {
while (!line_done)
{
string_done = !AdvanceCodepointIter(&iter);
if (string_done) {
if (string_done)
{
line_done = 1;
} else {
}
else
{
u32 codepoint = iter.codepoint;
if (codepoint == '\n') {
if (codepoint == '\n')
{
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;
F_Glyph *glyph = font_get_glyph(params.font, codepoint);
tg->off_x = glyph->off_x * params.scale;
@ -378,13 +373,16 @@ Rect draw_text(G_RenderSig *sig, D_TextParams params)
/* Line ended */
/* 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->num_glyphs = num_line_glyphs;
node->glyphs = line_glyphs;
if (last_line) {
if (last_line)
{
last_line->next = node;
} else {
}
else
{
first_line = node;
first_line_top_offset = top_offset;
}
@ -396,9 +394,7 @@ Rect draw_text(G_RenderSig *sig, D_TextParams params)
EndCodepointIter(&iter);
}
/* ========================== *
* Determine text bounds
* ========================== */
//- Determine text bounds
Rect bounds = ZI;
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;
/* Offset bounds X */
switch (params.offset_x) {
switch (params.offset_x)
{
case DRAW_TEXT_OFFSET_X_LEFT: break;
case DRAW_TEXT_OFFSET_X_CENTER:
{
@ -420,7 +417,8 @@ Rect draw_text(G_RenderSig *sig, D_TextParams params)
}
/* Offset bounds Y */
switch (params.offset_y) {
switch (params.offset_y)
{
case DRAW_TEXT_OFFSET_Y_TOP: break;
case DRAW_TEXT_OFFSET_Y_CENTER:
{
@ -428,23 +426,24 @@ Rect draw_text(G_RenderSig *sig, D_TextParams params)
} break;
case DRAW_TEXT_OFFSET_Y_BOTTOM:
{
if (last_line) {
if (last_line)
{
bounds.y -= bounds.height + last_line_bottom_offset;
}
} break;
}
/* ========================== *
* Draw lines
* ========================== */
//- Draw lines
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;
draw_pos.y += line_number * line_spacing - first_line_top_offset;
/* Alignment */
switch (params.alignment) {
switch (params.alignment)
{
case DRAW_TEXT_ALIGNMENT_LEFT: break;
case DRAW_TEXT_ALIGNMENT_CENTER:
{
@ -456,13 +455,14 @@ Rect draw_text(G_RenderSig *sig, D_TextParams params)
} break;
}
/* Draw glyphs */
for (u64 i = 0; i < line->num_glyphs; ++i) {
struct drawable_glyph *tg = &line->glyphs[i];
/* Draw glyphs in line */
for (u64 i = 0; i < line->num_glyphs; ++i)
{
D_TextGlyph *tg = &line->glyphs[i];
Vec2 pos = VEC2(draw_pos.x + tg->off_x, draw_pos.y + tg->off_y);
Vec2 size = VEC2(tg->width, tg->height);
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;
}

View File

@ -1,17 +1,8 @@
Struct(D_StartupReceipt) { i32 _; };
D_StartupReceipt draw_startup(F_StartupReceipt *font_sr);
////////////////////////////////
//~ Material types
/* ========================== *
* Material
* ========================== */
#define DRAW_MATERIAL_PARAMS(...) ((D_MaterialParams) { \
.tint = ColorWhite, \
.clip = AllClipped, \
__VA_ARGS__ \
})
Struct(D_MaterialParams) {
Struct(D_MaterialParams)
{
Xform xf;
G_Resource *texture;
ClipRect clip;
@ -19,83 +10,34 @@ Struct(D_MaterialParams) {
b32 is_light;
Vec3 light_emittance;
};
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) { \
#define D_MATERIALPARAMS(...) ((D_MaterialParams) { \
.tint = ColorWhite, \
.clip = AllClipped, \
__VA_ARGS__ \
})
Struct(D_UiRectParams) {
////////////////////////////////
//~ Ui types
Struct(D_UiRectParams)
{
Xform xf;
G_Resource *texture;
ClipRect clip;
u32 tint;
};
void draw_ui_rect(G_RenderSig *sig, D_UiRectParams params);
/* ========================== *
* 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, \
#define D_UIRECTPARAMS(...) ((D_UiRectParams) { \
.tint = ColorWhite, \
.clip = AllClipped, \
__VA_ARGS__ \
})
////////////////////////////////
//~ Text types
/* 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_CENTER,
DRAW_TEXT_ALIGNMENT_RIGHT
@ -104,19 +46,40 @@ typedef i32 D_TextAlignment; enum {
/* 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
* the specified position. */
typedef i32 D_TextOffsetX; enum {
typedef i32 D_TextOffsetX; enum
{
DRAW_TEXT_OFFSET_X_LEFT, /* Default */
DRAW_TEXT_OFFSET_X_CENTER,
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_CENTER,
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;
Vec2 pos;
f32 scale;
@ -126,5 +89,68 @@ Struct(D_TextParams) {
D_TextOffsetY offset_y;
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);

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);
y_ray = MulVec2(y_ray, ray_scale);
draw_arrow_ray(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, x_ray, thickness, arrowhead_len, color_x);
D_DrawArrowRay(G.render_sig, pos, y_ray, thickness, arrowhead_len, color_y);
//u32 color_quad = Rgba32F(0, 1, 1, 0.3);
//Quad quad = QuadFromRect(RectFromScalar(0, 0, 1, -1));
//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)
@ -289,7 +289,7 @@ internal void debug_draw_movement(Ent *ent)
Vec2 vel_ray = MulXformBasisV2(G.world_to_ui_xf, velocity);
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) {
/* Draw background */
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 */
String text = log->msg;
@ -477,7 +477,7 @@ internal void draw_debug_console(i32 level, b32 minimized)
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 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);
u32 color0 = Rgba32F(0.17f, 0.17f, 0.17f, 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
@ -1215,9 +1215,9 @@ internal void user_update(P_Window *window)
u32 color_end = Rgba32F(1, 0.8, 0.4, opacity_b);
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
@ -1232,8 +1232,8 @@ internal void user_update(P_Window *window)
Vec3 emittance = ent->sprite_emittance;
u32 tint = ent->sprite_tint;
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);
draw_material(G.render_sig, params);
D_MaterialParams params = D_MATERIALPARAMS(.xf = sprite_xform, .texture = texture->gp_texture, .tint = tint, .clip = frame.clip, .is_light = is_light, .light_emittance = emittance);
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);
Vec2 pos = sim_pos_from_world_tile_index(world_tile_index);
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));
draw_material(G.render_sig, params);
D_MaterialParams params = D_MATERIALPARAMS(.xf = tile_xf, .texture = tile_texture->gp_texture, .is_light = 1, .light_emittance = VEC3(0, 0, 0));
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);
Quad quad = QuadFromAabb(aabb);
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 */
@ -1295,7 +1295,7 @@ internal void user_update(P_Window *window)
start = MulXformV2(G.world_to_ui_xf, start);
Vec2 end = AddVec2(xf.og, ent->control.focus);
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
@ -1321,16 +1321,16 @@ internal void user_update(P_Window *window)
Quad quad = QuadFromRect(slice.rect);
quad = MulXformQuad(sprite_xform, 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) {
Vec2 ray = MulXformBasisV2(sprite_xform, slice.dir);
ray = MulXformBasisV2(G.world_to_ui_xf, ray);
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;
Vec2 point = MulXformV2(e1_xf, ent->weld_joint_data.point_local_e1);
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;
}
@ -1362,8 +1362,8 @@ internal void user_update(P_Window *window)
Vec2 point_end = G.world_cursor;
point_start = MulXformV2(G.world_to_ui_xf, point_start);
point_end = MulXformV2(G.world_to_ui_xf, point_end);
draw_arrow_line(G.render_sig, point_start, point_end, 3, 10, color);
draw_circle(G.render_sig, point_start, 4, color, 10);
D_DrawArrowLine(G.render_sig, point_start, point_end, 3, 10, color);
D_DrawCircle(G.render_sig, point_start, 4, color, 10);
}
/* Draw collider */
@ -1375,13 +1375,13 @@ internal void user_update(P_Window *window)
/* Draw collider using support points */
u32 detail = 32;
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 */
for (u32 i = 0; i < collider.count; ++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) {
@ -1390,14 +1390,14 @@ internal void user_update(P_Window *window)
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);
D_DrawLine(G.render_sig, start, end, thickness, color);
}
#if 0
/* Draw support point at focus dir */
{
Vec2 p = collider_support_point(&collider, xf, ent->control.focus);
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
}
@ -1421,7 +1421,7 @@ internal void user_update(P_Window *window)
/* 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 */
@ -1431,7 +1431,7 @@ internal void user_update(P_Window *window)
f32 arrow_height = 5;
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)));
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
/* Draw contact info */
@ -1489,8 +1489,8 @@ internal void user_update(P_Window *window)
u32 color = Rgba32F(1, 1, 0, 0.5);
Vec2 a = MulXformV2(G.world_to_ui_xf, data->closest0);
Vec2 b = MulXformV2(G.world_to_ui_xf, data->closest1);
draw_circle(G.render_sig, a, radius, color, 10);
draw_circle(G.render_sig, b, radius, color, 10);
D_DrawCircle(G.render_sig, a, radius, color, 10);
D_DrawCircle(G.render_sig, b, radius, color, 10);
}
#endif
@ -1507,28 +1507,28 @@ internal void user_update(P_Window *window)
{
Vec2 a = MulXformV2(G.world_to_ui_xf, collision_reuslt.a0);
Vec2 b = MulXformV2(G.world_to_ui_xf, collision_reuslt.b0);
draw_line(G.render_sig, a, b, thickness, color_line);
draw_circle(G.render_sig, a, radius, color_a, 10);
draw_circle(G.render_sig, b, radius, color_b, 10);
D_DrawLine(G.render_sig, a, b, thickness, color_line);
D_DrawCircle(G.render_sig, a, radius, color_a, 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 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);
draw_circle(G.render_sig, a_clipped, radius, color_a_clipped, 10);
draw_circle(G.render_sig, b_clipped, radius, color_b_clipped, 10);
D_DrawLine(G.render_sig, a_clipped, b_clipped, thickness, color_line_clipped);
D_DrawCircle(G.render_sig, a_clipped, radius, color_a_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 b = MulXformV2(G.world_to_ui_xf, collision_reuslt.b1);
draw_line(G.render_sig, a, b, thickness, color_line);
draw_circle(G.render_sig, a, radius, color_a, 10);
draw_circle(G.render_sig, b, radius, color_b, 10);
D_DrawLine(G.render_sig, a, b, thickness, color_line);
D_DrawCircle(G.render_sig, a, radius, color_a, 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 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);
draw_circle(G.render_sig, a_clipped, radius, color_a_clipped, 10);
draw_circle(G.render_sig, b_clipped, radius, color_b_clipped, 10);
D_DrawLine(G.render_sig, a_clipped, b_clipped, thickness, color_line_clipped);
D_DrawCircle(G.render_sig, a_clipped, radius, color_a_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);
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);
D_DrawPolyLine(G.render_sig, m, 1, thickness, color);
//D_DrawPoly(G.render_sig, m, color);
}
/* Draw CLD_PointCloud */
@ -1598,7 +1598,7 @@ internal void user_update(P_Window *window)
for (u64 i = 0; i < m.count; ++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
};
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);
for (u64 i = 0; i < m.count; ++i) draw_circle(G.render_sig, m.points[i], 10, color, 10);
D_DrawPolyLine(G.render_sig, m, 1, thickness, color);
for (u64 i = 0; i < m.count; ++i) D_DrawCircle(G.render_sig, m.points[i], 10, color, 10);
}
/* Draw simplex */
@ -1631,18 +1631,18 @@ internal void user_update(P_Window *window)
if (simplex.len >= 1) {
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) {
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) {
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) {
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;
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));
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
@ -1669,7 +1669,7 @@ internal void user_update(P_Window *window)
Vec2 start = MulXformV2(G.world_to_ui_xf, 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 */
@ -1681,7 +1681,7 @@ internal void user_update(P_Window *window)
Quad quad = MulXformQuad(quad_xf, CenteredUnitSquareQuad);
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);
@ -1697,7 +1697,7 @@ internal void user_update(P_Window *window)
S_Texture *t = sprite_texture_from_tag_async(sprite_frame_scope, crosshair);
Vec2 size = VEC2(t->width, t->height);
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 */
@ -1909,7 +1909,7 @@ internal void user_update(P_Window *window)
String dbg_text = ZI;
dbg_text.text = PushDry(temp.arena, u8);
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);
}
@ -2029,7 +2029,7 @@ internal void user_update(P_Window *window)
Vec2 pos = VEC2(10, G.ui_size.y);
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);
}
}