rounded shape drawing

This commit is contained in:
jacob 2025-11-13 15:02:31 -06:00
parent 03eed624c9
commit 5a3f5ad12b
6 changed files with 108 additions and 39 deletions

View File

@ -348,7 +348,8 @@ PackedVec4 PackVec4(Vec4 v);
b32 MatchXform(Xform xf1, Xform xf2);
//- Initialization
#define XformIdentity (Xform) { .bx = VEC2(1, 0), .by = VEC2(0, 1) }
#define XformIdentity (Xform) { .bx = { .x = 1 }, .by = { .y = 1 } }
#define CompXformIdentity { .bx = { .x = 1 }, .by = { .y = 1 } }
Xform XformFromPos(Vec2 v);
Xform XformFromRot(f32 r);
Xform XformFromScale(Vec2 scale);

View File

@ -1,5 +1,9 @@
S_SharedState S_shared_state = ZI;
Readonly S_Ent S_nil_ent = ZI;
Readonly S_Ent S_nil_ent = {
.local_to_parent_xf = CompXformIdentity,
.final_local_to_world_xf = CompXformIdentity,
};
////////////////////////////////////////////////////////////
//~ Startup
@ -38,7 +42,7 @@ void S_Shutdown(void)
////////////////////////////////////////////////////////////
//~ Nil helpers
b32 S_IsKeyNil(S_EntKey key)
b32 S_IsKeyNil(S_Key key)
{
return key.v.hi == 0 && key.v.lo == 0;
}
@ -48,15 +52,48 @@ b32 S_IsEntNil(S_Ent *ent)
return ent == 0 || ent == &S_nil_ent;
}
b32 S_MatchEntKey(S_EntKey a, S_EntKey b)
b32 S_MatchKey(S_Key a, S_Key b)
{
return a.v.hi == b.v.hi && a.v.lo == b.v.lo;
}
////////////////////////////////////////////////////////////
//~ Shape helpers
S_Shape S_MulXformShape(Xform xf, S_Shape shape)
{
S_Shape result = shape;
for (i32 i = 0; i < shape.points_count; ++i)
{
shape.points[i] = MulXformV2(xf, shape.points[i]);
}
Vec2 scale = ScaleFromXform(xf);
result.radius *= MaxF32(scale.x, scale.y);
return result;
}
Vec2 S_SupportPointFromShape(S_Shape shape, Vec2 dir)
{
Vec2 result = ZI;
f32 max_dot = -F32Infinity;
for (i32 i = 0; i < shape.points_count; ++i)
{
Vec2 p = shape.points[i];
f32 dot = DotVec2(p, dir);
if (dot > max_dot)
{
max_dot = dot;
result = p;
}
}
result = AddVec2(result, MulVec2(dir, shape.radius));
return result;
}
////////////////////////////////////////////////////////////
//~ Lookup helpers
S_Ent *S_EntFromKey(S_World *world, S_EntKey key)
S_Ent *S_EntFromKey(S_World *world, S_Key key)
{
S_Ent *ent = &S_nil_ent;
if (!S_IsKeyNil(key))
@ -64,7 +101,7 @@ S_Ent *S_EntFromKey(S_World *world, S_EntKey key)
S_EntLookupNode *n = world->ent_bins[key.v.lo % world->ent_bins_count];
for (; n; n = n->next)
{
if (S_MatchEntKey(n->ent->key, key))
if (S_MatchKey(n->ent->key, key))
{
ent = n->ent;
break;
@ -94,7 +131,7 @@ S_World *S_WorldFromSnapshot(Arena *arena, S_Snapshot *snapshot)
for (i64 ent_idx = 0; ent_idx < world->allocated_ents_count; ++ent_idx)
{
S_Ent *ent = &world->ents[ent_idx];
S_EntKey key = ent->key;
S_Key key = ent->key;
S_EntLookupNode *n = PushStruct(arena, S_EntLookupNode);
n->ent = ent;
S_EntLookupNode **bin = &world->ent_bins[ent->key.v.lo % world->ent_bins_count];
@ -116,7 +153,7 @@ S_World *S_WorldFromSnapshot(Arena *arena, S_Snapshot *snapshot)
for (i64 ent_idx = 0; ent_idx < world->allocated_ents_count; ++ent_idx)
{
S_Ent *ent = &world->ents[ent_idx];
if (S_MatchEntKey(ent->key, S_RootEntKey))
if (S_MatchKey(ent->key, S_RootKey))
{
n->ent = ent;
break;
@ -180,7 +217,7 @@ JobDef(S_SimWorker, _, __)
S_Ent *root_ent = &empty_ss->ents[empty_ss->ents_count++];
{
*root_ent = S_nil_ent;
root_ent->key = S_RootEntKey;
root_ent->key = S_RootKey;
}
/* Create test ent */
S_Ent *test_ent = &empty_ss->ents[empty_ss->ents_count++];
@ -188,19 +225,16 @@ JobDef(S_SimWorker, _, __)
*test_ent = S_nil_ent;
// test_ent->shape.points_count = 1;
// test_ent->shape.radius = 0.25;
test_ent->key = ((S_EntKey) { .v.hi = 0x66444f20b7e41f3d, .v.lo = 0x5a2df684b9430943 });
test_ent->key = ((S_Key) { .v.hi = 0x66444f20b7e41f3d, .v.lo = 0x5a2df684b9430943 });
{
S_Shape *shape = &test_ent->shape;
S_Shape *shape = &test_ent->local_shape;
shape->points_count = 4;
shape->points[0] = VEC2(100, 100);
shape->points[1] = VEC2(200, 100);
shape->points[2] = VEC2(150, 200);
shape->points[3] = VEC2(125, 200);
// test_ent->shape.radius = 0.25;
// shape->radius = 1;
}
@ -218,7 +252,7 @@ JobDef(S_SimWorker, _, __)
}
//////////////////////////////
//- Begin sim loop
//- Sim loop
b32 shutdown = 0;
while (!shutdown)
@ -260,6 +294,9 @@ JobDef(S_SimWorker, _, __)
}
}
//////////////////////////////
//- Update entities from user control
//////////////////////////////
//- Publish sim state

View File

@ -1,10 +1,10 @@
////////////////////////////////////////////////////////////
//~ Key types
#define S_NilEntKey ((S_EntKey) { 0 })
#define S_RootEntKey ((S_EntKey) { .v.hi = 0x75ebb7a47d1ca753, .v.lo = 0x2d505fc8961e5576 })
#define S_NilKey ((S_Key) { 0 })
#define S_RootKey ((S_Key) { .v.hi = 0x75ebb7a47d1ca753, .v.lo = 0x2d505fc8961e5576 })
Struct(S_EntKey)
Struct(S_Key)
{
U128 v;
};
@ -15,7 +15,7 @@ Struct(S_EntKey)
Struct(S_Shape)
{
f32 radius;
u32 points_count;
i32 points_count;
Vec2 points[8];
};
@ -36,18 +36,22 @@ Enum(S_EntProp)
Struct(S_Ent)
{
//- Tree data
S_EntKey parent;
S_EntKey first;
S_EntKey last;
S_EntKey next;
S_EntKey prev;
S_Key parent;
S_Key first;
S_Key last;
S_Key next;
S_Key prev;
i64 count;
//- Persistent data
S_EntKey key;
S_Key key;
//- Build data
S_Shape shape;
S_Shape local_shape;
Xform local_to_parent_xf;
//- Final data
Xform final_local_to_world_xf;
//- Per-world data
i64 pre_idx;
@ -177,14 +181,20 @@ void S_Shutdown(void);
////////////////////////////////////////////////////////////
//~ Nil helpers
b32 S_IsKeyNil(S_EntKey key);
b32 S_IsKeyNil(S_Key key);
b32 S_IsEntNil(S_Ent *ent);
b32 S_MatchEntKey(S_EntKey a, S_EntKey b);
b32 S_MatchKey(S_Key a, S_Key b);
////////////////////////////////////////////////////////////
//~ Shape helpers
S_Shape S_MulXformShape(Xform xf, S_Shape shape);
Vec2 S_SupportPointFromShape(S_Shape shape, Vec2 dir);
////////////////////////////////////////////////////////////
//~ Lookup helpers
S_Ent *S_EntFromKey(S_World *world, S_EntKey key);
S_Ent *S_EntFromKey(S_World *world, S_Key key);
////////////////////////////////////////////////////////////
//~ Snapshot helpers

View File

@ -352,15 +352,15 @@ JobDef(V_VisWorker, _, __)
// Xform xf = ent->final_to_world_xf;
Xform xf = XformIdentity;
S_Shape shape = ent->shape;
for (u32 point_idx = 0; point_idx < shape.points_count; ++point_idx)
S_Shape shape = S_MulXformShape(ent->final_local_to_world_xf, ent->local_shape);
for (i32 point_idx = 0; point_idx < shape.points_count; ++point_idx)
{
Vec2 *p = &shape.points[point_idx];
*p = MulXformV2(xf, *p);
}
Vec4 color = Color_Red;
V_DrawShape(dverts_arena, dvert_idx_arena, shape, LinearFromSrgb(color));
V_DrawShape(dverts_arena, dvert_idx_arena, shape, LinearFromSrgb(color), 16);
}
//////////////////////////////

View File

@ -1,16 +1,35 @@
void V_DrawShape(Arena *verts_arena, Arena *idx_arena, S_Shape shape, Vec4 color_lin)
void V_DrawShape(Arena *verts_arena, Arena *idx_arena, S_Shape shape, Vec4 color_lin, i32 detail)
{
/* FIXME: Rounding */
TempArena scratch = BeginScratchNoConflict();
i32 verts_count = shape.points_count;
Vec2Array draw_points = ZI;
if (shape.radius == 0)
{
draw_points.points = shape.points;
draw_points.count = shape.points_count;
}
else
{
draw_points.points = PushStructsNoZero(scratch.arena, Vec2, detail);
draw_points.count = detail;
for (i32 i = 0; i < detail; ++i)
{
f32 rad = ((f32)i / (f32)detail) * Tau;
Vec2 dir = Vec2FromAngle(rad);
Vec2 sp = S_SupportPointFromShape(shape, dir);
draw_points.points[i] = sp;
}
}
i32 verts_count = draw_points.count;
if (verts_count >= 3)
{
i32 idx_offset = ArenaCount(verts_arena, V_DVert);
V_DVert *dverts = PushStructsNoZero(verts_arena, V_DVert, verts_count);
for (i32 point_idx = 0; point_idx < (i32)shape.points_count; ++point_idx)
for (i32 point_idx = 0; point_idx < (i32)draw_points.count; ++point_idx)
{
V_DVert *dvert = &dverts[point_idx];
dvert->pos = shape.points[point_idx];
dvert->pos = draw_points.points[point_idx];
dvert->color_lin = color_lin;
}
@ -27,4 +46,6 @@ void V_DrawShape(Arena *verts_arena, Arena *idx_arena, S_Shape shape, Vec4 color
indices[tri_offset + 2] = i + 2;
}
}
EndScratch(scratch);
}

View File

@ -1 +1 @@
void V_DrawShape(Arena *verts_arena, Arena *idx_arena, S_Shape shape, Vec4 color_lin);
void V_DrawShape(Arena *verts_arena, Arena *idx_arena, S_Shape shape, Vec4 color_lin, i32 detail);