7 constexpr uint32_t k_min_segments = 3;
8 constexpr uint32_t k_min_sides = 3;
10 [[nodiscard]] Kakshya::Vertex vert2(glm::vec2 p, glm::vec3 c)
noexcept
12 return Kakshya::Vertex {
13 .position = { p.x, p.y, 0.F },
18 [[nodiscard]] Kakshya::LineVertex lvert2(glm::vec2 p, glm::vec3 c,
float t)
noexcept
20 return Kakshya::LineVertex {
21 .position = { p.x, p.y, 0.F },
27 [[nodiscard]] glm::vec2 ring_point(glm::vec2 center,
float r,
float angle)
noexcept
29 return center + r * glm::vec2(std::cos(angle), std::sin(angle));
39 glm::vec2 center,
float radius, uint32_t segments, glm::vec3 color)
41 segments = std::max<uint32_t>(segments, k_min_segments);
42 const float step = glm::two_pi<float>() /
static_cast<float>(segments);
44 std::vector<Kakshya::Vertex> out;
45 out.reserve(
static_cast<size_t>(segments) * 3);
47 for (uint32_t i = 0; i < segments; ++i) {
48 const float a0 =
static_cast<float>(i) * step;
49 const float a1 =
static_cast<float>(i + 1) * step;
50 out.push_back(vert2(center, color));
51 out.push_back(vert2(ring_point(center, radius, a0), color));
52 out.push_back(vert2(ring_point(center, radius, a1), color));
59 glm::vec2 center,
float inner_r,
float outer_r,
60 uint32_t segments, glm::vec3 color)
62 segments = std::max<uint32_t>(segments, k_min_segments);
63 const float step = glm::two_pi<float>() /
static_cast<float>(segments);
65 std::vector<Kakshya::Vertex> out;
66 out.reserve(
static_cast<size_t>(segments) * 6);
68 for (uint32_t i = 0; i < segments; ++i) {
69 const float a0 =
static_cast<float>(i) * step;
70 const float a1 =
static_cast<float>(i + 1) * step;
72 const glm::vec2 oi0 = ring_point(center, inner_r, a0);
73 const glm::vec2 oo0 = ring_point(center, outer_r, a0);
74 const glm::vec2 oi1 = ring_point(center, inner_r, a1);
75 const glm::vec2 oo1 = ring_point(center, outer_r, a1);
77 out.push_back(vert2(oi0, color));
78 out.push_back(vert2(oo0, color));
79 out.push_back(vert2(oo1, color));
81 out.push_back(vert2(oi0, color));
82 out.push_back(vert2(oo1, color));
83 out.push_back(vert2(oi1, color));
90 glm::vec2 center,
float radius, uint32_t sides,
91 float rotation_rad, glm::vec3 color)
93 sides = std::max<uint32_t>(sides, k_min_sides);
94 const float step = glm::two_pi<float>() /
static_cast<float>(sides);
96 std::vector<Kakshya::Vertex> out;
97 out.reserve((
size_t)sides * 3);
99 for (uint32_t i = 0; i < sides; ++i) {
100 const float a0 = rotation_rad +
static_cast<float>(i) * step;
101 const float a1 = rotation_rad +
static_cast<float>(i + 1) * step;
102 out.push_back(vert2(center, color));
103 out.push_back(vert2(ring_point(center, radius, a0), color));
104 out.push_back(vert2(ring_point(center, radius, a1), color));
112 glm::vec3 color_bl, glm::vec3 color_br,
113 glm::vec3 color_tl, glm::vec3 color_tr)
116 { .position = { region.
min.x, region.
min.y, 0.F }, .color = color_bl },
117 { .position = { region.
min.x, region.
max.y, 0.F }, .color = color_tl },
118 { .position = { region.
max.x, region.
min.y, 0.F }, .color = color_br },
119 { .position = { region.
max.x, region.
max.y, 0.F }, .color = color_tr },
124 AABB2D region,
float corner_radius,
125 uint32_t corner_segments, glm::vec3 color)
127 corner_segments = std::max<uint32_t>(corner_segments, 1U);
128 const float max_r = std::min(region.
width(), region.
height()) * 0.5F;
129 const float r = std::min(corner_radius, max_r);
131 const glm::vec2 bl { region.
min.x + r, region.
min.y + r };
132 const glm::vec2 br { region.
max.x - r, region.
min.y + r };
133 const glm::vec2 tl { region.
min.x + r, region.
max.y - r };
134 const glm::vec2 tr { region.
max.x - r, region.
max.y - r };
136 std::vector<Kakshya::Vertex> out;
138 out.reserve(18 + 4 * (
size_t)corner_segments * 3);
141 auto push_quad = [&](glm::vec2
a, glm::vec2
b, glm::vec2 c, glm::vec2 d) {
142 out.push_back(vert2(
a, color));
143 out.push_back(vert2(
b, color));
144 out.push_back(vert2(c, color));
145 out.push_back(vert2(
b, color));
146 out.push_back(vert2(d, color));
147 out.push_back(vert2(c, color));
150 push_quad({ bl.x, region.
min.y }, { tl.x, region.
max.y }, { tr.x, region.
min.y }, { tr.x, region.
max.y });
151 push_quad({ region.
min.x, bl.y }, { region.
min.x, tl.y }, { bl.x, bl.y }, { bl.x, tl.y });
152 push_quad({ tr.x, br.y }, { tr.x, tr.y }, { region.
max.x, br.y }, { region.
max.x, tr.y });
159 const auto half_pi = glm::half_pi<float>();
160 const Corner corners[4] = {
161 { .c = bl, .a0 = glm::pi<float>() },
162 { .c = br, .a0 = -half_pi },
163 { .c = tl, .a0 = half_pi },
164 { .c = tr, .a0 = 0.F },
167 const float step = half_pi /
static_cast<float>(corner_segments);
168 for (
const auto& [c, a0] : corners) {
169 for (uint32_t i = 0; i < corner_segments; ++i) {
170 const float a1 = a0 +
static_cast<float>(i) * step;
171 const float a2 = a0 +
static_cast<float>(i + 1) * step;
172 out.push_back(vert2(c, color));
173 out.push_back(vert2(ring_point(c, r, a1), color));
174 out.push_back(vert2(ring_point(c, r, a2), color));
182 glm::vec2 center,
float radius,
183 float angle_start,
float angle_end,
184 uint32_t segments, glm::vec3 color)
186 segments = std::max<uint32_t>(segments, 1U);
187 const float step = (angle_end - angle_start) /
static_cast<float>(segments);
189 std::vector<Kakshya::Vertex> out;
190 out.reserve(
static_cast<size_t>(segments) * 3);
192 for (uint32_t i = 0; i < segments; ++i) {
193 const float a0 = angle_start +
static_cast<float>(i) * step;
194 const float a1 = angle_start +
static_cast<float>(i + 1) * step;
195 out.push_back(vert2(center, color));
196 out.push_back(vert2(ring_point(center, radius, a0), color));
197 out.push_back(vert2(ring_point(center, radius, a1), color));
205 float radius_x,
float radius_y,
206 float angle_start,
float angle_end,
209 segments = std::max<uint32_t>(segments, 1U);
210 const float step = (angle_end - angle_start) /
static_cast<float>(segments);
212 std::vector<glm::vec2> out;
213 out.reserve(
static_cast<size_t>(segments) + 1);
214 for (uint32_t i = 0; i <= segments; ++i) {
215 const float a = angle_start +
static_cast<float>(i) * step;
216 out.push_back(center + glm::vec2(radius_x * std::cos(
a), radius_y * std::sin(
a)));
226 glm::vec2 center,
float radius, uint32_t segments,
227 glm::vec3 color,
float thickness)
229 segments = std::max<uint32_t>(segments, k_min_segments);
230 const float step = glm::two_pi<float>() /
static_cast<float>(segments);
232 std::vector<Kakshya::LineVertex> out;
233 out.reserve(
static_cast<size_t>(segments) * 2);
235 for (uint32_t i = 0; i < segments; ++i) {
236 const float a0 =
static_cast<float>(i) * step;
237 const float a1 =
static_cast<float>((i + 1) % segments) * step;
238 out.push_back(lvert2(ring_point(center, radius, a0), color, thickness));
239 out.push_back(lvert2(ring_point(center, radius, a1), color, thickness));
246 glm::vec2 center,
float radius,
247 float angle_start,
float angle_end,
248 uint32_t segments, glm::vec3 color,
float thickness)
250 segments = std::max<uint32_t>(segments, 1U);
251 const float step = (angle_end - angle_start) /
static_cast<float>(segments);
253 std::vector<Kakshya::LineVertex> out;
254 out.reserve(
static_cast<size_t>(segments) * 2);
256 for (uint32_t i = 0; i < segments; ++i) {
257 const float a0 = angle_start +
static_cast<float>(i) * step;
258 const float a1 = angle_start +
static_cast<float>(i + 1) * step;
259 out.push_back(lvert2(ring_point(center, radius, a0), color, thickness));
260 out.push_back(lvert2(ring_point(center, radius, a1), color, thickness));
267 AABB2D region, glm::vec3 color,
float thickness)
269 const glm::vec2 bl { region.
min.x, region.
min.y };
270 const glm::vec2 br { region.
max.x, region.
min.y };
271 const glm::vec2 tl { region.
min.x, region.
max.y };
272 const glm::vec2 tr { region.
max.x, region.
max.y };
275 lvert2(bl, color, thickness),
276 lvert2(br, color, thickness),
277 lvert2(br, color, thickness),
278 lvert2(tr, color, thickness),
279 lvert2(tr, color, thickness),
280 lvert2(tl, color, thickness),
281 lvert2(tl, color, thickness),
282 lvert2(bl, color, thickness),
287 std::span<const glm::vec2> pts, glm::vec3 color,
float thickness)
292 std::vector<Kakshya::LineVertex> out;
293 out.reserve((pts.size() - 1) * 2);
295 for (
size_t i = 0; i + 1 < pts.size(); ++i) {
296 out.push_back(lvert2(pts[i], color, thickness));
297 out.push_back(lvert2(pts[i + 1], color, thickness));
304 std::span<const glm::vec2> pts,
305 std::span<const glm::vec3> colors,
308 if (pts.size() < 2 || colors.size() != pts.size())
311 std::vector<Kakshya::LineVertex> out;
312 out.reserve((pts.size() - 1) * 2);
314 for (
size_t i = 0; i + 1 < pts.size(); ++i) {
315 out.push_back(lvert2(pts[i], colors[i], thickness));
316 out.push_back(lvert2(pts[i + 1], colors[i + 1], thickness));
323 glm::vec2 center,
float radius, uint32_t sides,
324 float rotation_rad, glm::vec3 color,
float thickness)
326 sides = std::max<uint32_t>(sides, k_min_sides);
327 const float step = glm::two_pi<float>() /
static_cast<float>(sides);
329 std::vector<Kakshya::LineVertex> out;
330 out.reserve((
size_t)sides * 2);
332 for (uint32_t i = 0; i < sides; ++i) {
333 const float a0 = rotation_rad +
static_cast<float>(i) * step;
334 const float a1 = rotation_rad +
static_cast<float>((i + 1) % sides) * step;
335 out.push_back(lvert2(ring_point(center, radius, a0), color, thickness));
336 out.push_back(lvert2(ring_point(center, radius, a1), color, thickness));
std::vector< Kakshya::LineVertex > polygon_outline(glm::vec2 center, float radius, uint32_t sides, float rotation_rad, glm::vec3 color, float thickness)
Regular n-gon outline as a LINE_LIST (closed loop, 2 * sides vertices).
std::vector< Kakshya::Vertex > filled_circle(glm::vec2 center, float radius, uint32_t segments, glm::vec3 color)
Filled circle as a TRIANGLE_LIST triangle fan.
std::vector< Kakshya::Vertex > filled_ring(glm::vec2 center, float inner_r, float outer_r, uint32_t segments, glm::vec3 color)
Filled annulus (ring) as a TRIANGLE_LIST quad strip.
std::array< Kakshya::Vertex, 4 > filled_rect_gradient(AABB2D region, glm::vec3 color_bl, glm::vec3 color_br, glm::vec3 color_tl, glm::vec3 color_tr)
Filled rect with per-corner colors, TRIANGLE_STRIP (4 vertices).
std::array< Kakshya::LineVertex, 8 > rect_outline(AABB2D region, glm::vec3 color, float thickness)
Rectangle outline as a LINE_LIST (4 edges, 8 vertices).
std::vector< Kakshya::LineVertex > arc_outline(glm::vec2 center, float radius, float angle_start, float angle_end, uint32_t segments, glm::vec3 color, float thickness)
Arc outline as a LINE_LIST (open curve, 2 * segments vertices).
std::vector< Kakshya::LineVertex > polyline(std::span< const glm::vec2 > pts, glm::vec3 color, float thickness)
Polyline as a LINE_LIST (open path, 2 * (pts.size() - 1) vertices).
std::vector< Kakshya::LineVertex > circle_outline(glm::vec2 center, float radius, uint32_t segments, glm::vec3 color, float thickness)
Circle outline as a LINE_LIST (closed loop, 2 * segments vertices).
std::vector< Kakshya::Vertex > filled_polygon(glm::vec2 center, float radius, uint32_t sides, float rotation_rad, glm::vec3 color)
Filled regular n-gon as a TRIANGLE_LIST triangle fan.
std::vector< Kakshya::Vertex > filled_arc(glm::vec2 center, float radius, float angle_start, float angle_end, uint32_t segments, glm::vec3 color)
Filled circular arc sector (pie slice) as a TRIANGLE_LIST fan.
std::vector< Kakshya::Vertex > filled_rounded_rect(AABB2D region, float corner_radius, uint32_t corner_segments, glm::vec3 color)
Filled rounded rectangle as a TRIANGLE_LIST mesh.
std::vector< Kakshya::LineVertex > polyline_colored(std::span< const glm::vec2 > pts, std::span< const glm::vec3 > colors, float thickness)
Polyline with per-vertex colors as a LINE_LIST.
std::vector< glm::vec2 > arc_path(glm::vec2 center, float radius_x, float radius_y, float angle_start, float angle_end, uint32_t segments)
Sample a circular arc as ordered NDC positions.
float height() const noexcept
float width() const noexcept
Axis-aligned bounding rectangle in a 2D coordinate space.