//////////////////////////////////////////////////////////// //~ 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); } }