power_play/src/pp/pp_vis/pp_vis_draw.c
2025-12-16 16:46:25 -06:00

124 lines
4.8 KiB
C

////////////////////////////////////////////////////////////
//~ Shape helpers
void V_DrawPoly(Arena *verts_arena, Arena *idxs_arena, Vec2Array points, Vec4 color_lin, V_DrawFlag flags)
{
if (flags & V_DrawFlag_Line)
{
i32 verts_count = points.count;
if (verts_count >= 2)
{
TempArena scratch = BeginScratchNoConflict();
{
f32 half_thickness = 1;
i32 lines_count = verts_count == 2 ? 1 : verts_count;
i32 line_verts_count = lines_count * 4;
i32 idx_count = lines_count * 6;
i32 idx_offset = ArenaCount(verts_arena, V_DVert);
/* Push dverts */
V_DVert *dverts = PushStructsNoZero(verts_arena, V_DVert, line_verts_count);
for (i32 line_idx = 0; line_idx < lines_count; ++line_idx)
{
i32 a_idx = line_idx;
i32 b_idx = line_idx + 1;
if (b_idx >= lines_count)
{
b_idx = 0;
}
Vec2 a = points.points[a_idx];
Vec2 b = points.points[b_idx];
Vec2 a_to_b = SubVec2(b, a);
Vec2 perp = Vec2WithLen(PerpVec2(a_to_b), half_thickness);
Vec2 p0 = AddVec2(a, perp);
Vec2 p1 = SubVec2(a, perp);
Vec2 p2 = SubVec2(b, perp);
Vec2 p3 = AddVec2(b, perp);
i32 offset = line_idx * 4;
dverts[offset + 0] = (V_DVert) { .pos = p0, .color_lin = color_lin };
dverts[offset + 1] = (V_DVert) { .pos = p1, .color_lin = color_lin };
dverts[offset + 2] = (V_DVert) { .pos = p2, .color_lin = color_lin };
dverts[offset + 3] = (V_DVert) { .pos = p3, .color_lin = color_lin };
}
/* Generate indices */
i32 *indices = PushStructsNoZero(idxs_arena, i32, idx_count);
for (i32 line_idx = 0; line_idx < lines_count; ++line_idx)
{
i32 indices_offset = line_idx * 6;
i32 vert_idx_offset = idx_offset + (line_idx * 4);
indices[indices_offset + 0] = vert_idx_offset + 0;
indices[indices_offset + 1] = vert_idx_offset + 1;
indices[indices_offset + 2] = vert_idx_offset + 2;
indices[indices_offset + 3] = vert_idx_offset + 0;
indices[indices_offset + 4] = vert_idx_offset + 2;
indices[indices_offset + 5] = vert_idx_offset + 3;
}
}
EndScratch(scratch);
}
}
else
{
i32 verts_count = points.count;
if (verts_count >= 3)
{
i32 idx_offset = ArenaCount(verts_arena, V_DVert);
i32 tris_count = verts_count - 2;
i32 idx_count = tris_count * 3;
/* Push dverts */
V_DVert *dverts = PushStructsNoZero(verts_arena, V_DVert, verts_count);
for (i32 point_idx = 0; point_idx < (i32)points.count; ++point_idx)
{
V_DVert *dvert = &dverts[point_idx];
dvert->pos = points.points[point_idx];
dvert->color_lin = color_lin;
}
/* Generate indices in a fan pattern */
i32 *indices = PushStructsNoZero(idxs_arena, i32, idx_count);
for (i32 i = 0; i < tris_count; ++i)
{
i32 tri_offset = i * 3;
indices[tri_offset + 0] = idx_offset;
indices[tri_offset + 1] = idx_offset + i + 1;
indices[tri_offset + 2] = idx_offset + i + 2;
}
}
}
}
void V_DrawShape(Arena *verts_arena, Arena *idxs_arena, S_Shape shape, Vec4 color_lin, i32 detail, V_DrawFlag flags)
{
if (shape.radius == 0)
{
Vec2Array draw_points = Zi;
draw_points.points = shape.points;
draw_points.count = shape.points_count;
V_DrawPoly(verts_arena, idxs_arena, draw_points, color_lin, flags);
}
else
{
TempArena scratch = BeginScratchNoConflict();
{
Vec2Array draw_points = Zi;
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;
}
V_DrawPoly(verts_arena, idxs_arena, draw_points, color_lin, flags);
}
EndScratch(scratch);
}
}