Blender V5.0
overlay_shape.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "GPU_batch_utils.hh"
10#include "draw_cache.hh"
11
12#include "overlay_private.hh"
13
14namespace blender::draw::overlay {
15
16static constexpr int diamond_nsegments = 4;
17static constexpr int inner_nsegments = 8;
18static constexpr int outer_nsegments = 10;
19static constexpr int circle_nsegments = 32;
20
21static constexpr float bone_box_verts[8][3] = {
22 {1.0f, 0.0f, 1.0f},
23 {1.0f, 0.0f, -1.0f},
24 {-1.0f, 0.0f, -1.0f},
25 {-1.0f, 0.0f, 1.0f},
26 {1.0f, 1.0f, 1.0f},
27 {1.0f, 1.0f, -1.0f},
28 {-1.0f, 1.0f, -1.0f},
29 {-1.0f, 1.0f, 1.0f},
30};
31
32static constexpr std::array<uint, 24> bone_box_wire_lines = {
33 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7,
34};
35
36static const std::array<uint3, 12> bone_box_solid_tris{
37 uint3{0, 2, 1}, /* bottom */
38 {0, 3, 2},
39
40 {0, 1, 5}, /* sides */
41 {0, 5, 4},
42
43 {1, 2, 6},
44 {1, 6, 5},
45
46 {2, 3, 7},
47 {2, 7, 6},
48
49 {3, 0, 4},
50 {3, 4, 7},
51
52 {4, 5, 6}, /* top */
53 {4, 6, 7},
54};
55
60static const std::array<uint4, 12> bone_box_wire_lines_adjacency = {
61 uint4{4, 2, 0, 11},
62 {0, 1, 2, 8},
63 {2, 4, 1, 14},
64 {1, 0, 4, 20}, /* bottom */
65 {0, 8, 11, 14},
66 {2, 14, 8, 20},
67 {1, 20, 14, 11},
68 {4, 11, 20, 8}, /* top */
69 {20, 0, 11, 2},
70 {11, 2, 8, 1},
71 {8, 1, 14, 4},
72 {14, 4, 20, 0}, /* sides */
73};
74
75/* aligned with bone_box_solid_tris */
76static const std::array<float3, 12> bone_box_solid_normals = {
77 float3{0.0f, -1.0f, 0.0f},
78 {0.0f, -1.0f, 0.0f},
79
80 {1.0f, 0.0f, 0.0f},
81 {1.0f, 0.0f, 0.0f},
82
83 {0.0f, 0.0f, -1.0f},
84 {0.0f, 0.0f, -1.0f},
85
86 {-1.0f, 0.0f, 0.0f},
87 {-1.0f, 0.0f, 0.0f},
88
89 {0.0f, 0.0f, 1.0f},
90 {0.0f, 0.0f, 1.0f},
91
92 {0.0f, 1.0f, 0.0f},
93 {0.0f, 1.0f, 0.0f},
94};
95
96static const std::array<float3, 6> bone_octahedral_verts{
97 float3{0.0f, 0.0f, 0.0f},
98 {0.1f, 0.1f, 0.1f},
99 {0.1f, 0.1f, -0.1f},
100 {-0.1f, 0.1f, -0.1f},
101 {-0.1f, 0.1f, 0.1f},
102 {0.0f, 1.0f, 0.0f},
103};
104
111static const std::array<float3, 6> bone_octahedral_smooth_normals{
112 float3{0.0f, -1.0f, 0.0f},
113 {float(M_SQRT1_2), 0.0f, float(M_SQRT1_2)},
114 {float(M_SQRT1_2), 0.0f, -float(M_SQRT1_2)},
115 {-float(M_SQRT1_2), 0.0f, -float(M_SQRT1_2)},
116 {-float(M_SQRT1_2), 0.0f, float(M_SQRT1_2)},
117 {0.0f, 1.0f, 0.0f},
118};
119
120static const std::array<uint2, 12> bone_octahedral_wire_lines = {
121 uint2{0, 1},
122 {1, 5},
123 {5, 3},
124 {3, 0},
125 {0, 4},
126 {4, 5},
127 {5, 2},
128 {2, 0},
129 {1, 2},
130 {2, 3},
131 {3, 4},
132 {4, 1},
133};
134
135static const std::array<uint3, 8> bone_octahedral_solid_tris = {
136 uint3{2, 1, 0}, /* bottom */
137 {3, 2, 0},
138 {4, 3, 0},
139 {1, 4, 0},
140
141 {5, 1, 2}, /* top */
142 {5, 2, 3},
143 {5, 3, 4},
144 {5, 4, 1},
145};
146
159static const std::array<uint4, 12> bone_octahedral_wire_lines_adjacency = {
160 uint4{0, 1, 2, 6},
161 {0, 12, 1, 6},
162 {0, 3, 12, 6},
163 {0, 2, 3, 6},
164 {1, 6, 2, 3},
165 {1, 12, 6, 3},
166 {1, 0, 12, 3},
167 {1, 2, 0, 3},
168 {2, 0, 1, 12},
169 {2, 3, 0, 12},
170 {2, 6, 3, 12},
171 {2, 1, 6, 12},
172};
173
174/* aligned with bone_octahedral_solid_tris */
175static const float bone_octahedral_solid_normals[8][3] = {
176 {M_SQRT1_2, -M_SQRT1_2, 0.00000000f},
177 {-0.00000000f, -M_SQRT1_2, -M_SQRT1_2},
178 {-M_SQRT1_2, -M_SQRT1_2, 0.00000000f},
179 {0.00000000f, -M_SQRT1_2, M_SQRT1_2},
180 {0.99388373f, 0.11043154f, -0.00000000f},
181 {0.00000000f, 0.11043154f, -0.99388373f},
182 {-0.99388373f, 0.11043154f, 0.00000000f},
183 {0.00000000f, 0.11043154f, 0.99388373f},
184};
185
187 Vector<Vertex> &dest, Span<float2> verts, float z, VertexClass flag, bool dashed = false)
188{
189 const int step = dashed ? 2 : 1;
190 for (const int i : IndexRange(verts.size() / step)) {
191 for (const int j : IndexRange(2)) {
192 const float2 &cv = verts[(i * step + j) % verts.size()];
193 dest.append({{cv[0], cv[1], z}, flag});
194 }
195 }
196}
197
198static float light_distance_z_get(char axis, const bool start)
199{
200 switch (axis) {
201 case 'x': /* - X */
202 return start ? 0.4f : 0.3f;
203 case 'X': /* + X */
204 return start ? 0.6f : 0.7f;
205 case 'y': /* - Y */
206 return start ? 1.4f : 1.3f;
207 case 'Y': /* + Y */
208 return start ? 1.6f : 1.7f;
209 case 'z': /* - Z */
210 return start ? 2.4f : 2.3f;
211 case 'Z': /* + Z */
212 return start ? 2.6f : 2.7f;
213 }
214 return 0.0;
215}
216
217/* A single ring of vertices. */
218static Vector<float2> ring_vertices(const float radius,
219 const int segments,
220 const bool half = false)
221{
223 const float full = (half ? 1.0f : 2.0f) * math::numbers::pi;
224 for (const int angle_i : IndexRange(segments + (half ? 1 : 0))) {
225 const float angle = (full * angle_i) / segments;
226 verts.append(radius * float2(math::cos(angle), math::sin(angle)));
227 }
228 return verts;
229}
230
231/* Returns lines segment geometry forming 3 circles, one on each axis. */
232static Vector<Vertex> sphere_axes_circles(const float radius,
233 const VertexClass vclass,
234 const int segments)
235{
236 Vector<float2> ring = ring_vertices(radius, segments);
237
239 for (int axis : IndexRange(3)) {
240 for (int i : IndexRange(segments)) {
241 for (int j : IndexRange(2)) {
242 float2 cv = ring[(i + j) % segments];
243 if (axis == 0) {
244 verts.append({{cv[0], cv[1], 0.0f}, vclass});
245 }
246 else if (axis == 1) {
247 verts.append({{cv[0], 0.0f, cv[1]}, vclass});
248 }
249 else {
250 verts.append({{0.0f, cv[0], cv[1]}, vclass});
251 }
252 }
253 }
254 }
255 return verts;
256}
257
258static void light_append_direction_line(const char axis,
259 Span<float2> diamond,
261{
262 const float zsta = light_distance_z_get(axis, true);
263 const float zend = light_distance_z_get(axis, false);
264 verts.append({{0.0, 0.0, zsta}, VCLASS_LIGHT_DIST});
265 verts.append({{0.0, 0.0, zend}, VCLASS_LIGHT_DIST});
268}
269
275
276static VertShaded sphere_lat_lon_vert(const float2 &lat_pt, const float2 &lon_pt)
277{
278 const float x = lon_pt.y * lat_pt.x;
279 const float y = lon_pt.x;
280 const float z = lon_pt.y * lat_pt.y;
281 return VertShaded{{x, y, z}, VCLASS_EMPTY_SCALED, {x, y, z}};
282}
283
284static void append_sphere(Vector<VertShaded> &dest, const eDRWLevelOfDetail level_of_detail)
285{
286 /* Sphere shape resolution */
287 /* Low */
288 constexpr int drw_sphere_shape_latitude_low = 32;
289 constexpr int drw_sphere_shape_longitude_low = 24;
290 /* Medium */
291 constexpr int drw_sphere_shape_latitude_medium = 64;
292 constexpr int drw_sphere_shape_longitude_medium = 48;
293 /* High */
294 constexpr int drw_sphere_shape_latitude_high = 80;
295 constexpr int drw_sphere_shape_longitude_high = 60;
296
297 BLI_assert(level_of_detail >= DRW_LOD_LOW && level_of_detail < DRW_LOD_MAX);
298 const std::array<Vector<float2>, DRW_LOD_MAX> latitude_rings = {
299 ring_vertices(1.0f, drw_sphere_shape_latitude_low),
300 ring_vertices(1.0f, drw_sphere_shape_latitude_medium),
301 ring_vertices(1.0f, drw_sphere_shape_latitude_high)};
302 const std::array<Vector<float2>, DRW_LOD_MAX> longitude_half_rings = {
303 ring_vertices(1.0f, drw_sphere_shape_longitude_low, true),
304 ring_vertices(1.0f, drw_sphere_shape_longitude_medium, true),
305 ring_vertices(1.0f, drw_sphere_shape_longitude_high, true)};
306
307 const Vector<float2> &latitude_ring = latitude_rings[level_of_detail];
308 const Vector<float2> &longitude_half_ring = longitude_half_rings[level_of_detail];
309
310 for (const int i : latitude_ring.index_range()) {
311 const float2 lat_pt = latitude_ring[i];
312 const float2 next_lat_pt = latitude_ring[(i + 1) % latitude_ring.size()];
313 for (const int j : IndexRange(longitude_half_ring.size() - 1)) {
314 const float2 lon_pt = longitude_half_ring[j];
315 const float2 next_lon_pt = longitude_half_ring[j + 1];
316 if (j != 0) { /* Pole */
317 dest.append(sphere_lat_lon_vert(next_lat_pt, next_lon_pt));
318 dest.append(sphere_lat_lon_vert(next_lat_pt, lon_pt));
319 dest.append(sphere_lat_lon_vert(lat_pt, lon_pt));
320 }
321 if (j != longitude_half_ring.index_range().last(1)) { /* Pole */
322 dest.append(sphere_lat_lon_vert(lat_pt, next_lon_pt));
323 dest.append(sphere_lat_lon_vert(next_lat_pt, next_lon_pt));
324 dest.append(sphere_lat_lon_vert(lat_pt, lon_pt));
325 }
326 }
327 }
328}
329
331{
333
334 /* Armature Octahedron. */
335 {
337 for (int tri = 0; tri < 8; tri++) {
338 for (int v = 0; v < 3; v++) {
342 }
343 }
344 bone_octahedron = BatchPtr(
345 GPU_batch_create_ex(GPU_PRIM_TRIS, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
346 }
347 {
350
351 for (auto line : bone_octahedral_wire_lines_adjacency) {
352 GPU_indexbuf_add_line_adj_verts(&elb, line[0], line[1], line[2], line[3]);
353 }
355
356 /* NOTE: Reuses the same VBO as bone_octahedron. Thus has the same vertex format. */
359 }
360
361 /* Armature Sphere. */
362 {
363 constexpr int resolution = 64;
364 Vector<float2> ring = ring_vertices(0.05f, resolution);
365
367 for (int a : IndexRange(resolution + 1)) {
368 float2 cv = ring[a % resolution];
369 verts.append({{cv.x, cv.y, 0.0f}, VCLASS_EMPTY_SCALED});
370 }
371
373 GPU_PRIM_TRI_FAN, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
374 }
375 {
376 bone_sphere_wire = BatchPtr(
377 GPU_batch_create(GPU_PRIM_LINE_STRIP, bone_sphere.get()->verts[0], nullptr));
378 }
379
380 /* Armature Stick. */
381 {
383 /* Gather as a strip and add to main buffer as a list of triangles. */
384 Vector<VertexBone> vert_strip;
385 vert_strip.append({{0.0f, 1.0f, 0.0f}, StickBoneFlag(bone | POS_HEAD | COL_HEAD | COL_WIRE)});
386 vert_strip.append({{0.0f, 1.0f, 0.0f}, StickBoneFlag(bone | POS_TAIL | COL_TAIL | COL_WIRE)});
387 vert_strip.append({{0.0f, 0.0f, 0.0f}, StickBoneFlag(bone | POS_HEAD | COL_HEAD)});
388 vert_strip.append({{0.0f, 0.0f, 0.0f}, StickBoneFlag(bone | POS_TAIL | COL_TAIL)});
389 vert_strip.append({{0.0f, -1.0f, 0.0f}, StickBoneFlag(bone | POS_HEAD | COL_HEAD | COL_WIRE)});
390 vert_strip.append({{0.0f, -1.0f, 0.0f}, StickBoneFlag(bone | POS_TAIL | COL_TAIL | COL_WIRE)});
391
393 /* Bone rectangle */
394 for (int t : IndexRange(vert_strip.size() - 2)) {
395 /* NOTE: Don't care about winding.
396 * Theses triangles are facing the camera and should not be backface culled. */
397 verts.append(vert_strip[t]);
398 verts.append(vert_strip[t + 1]);
399 verts.append(vert_strip[t + 2]);
400 }
401
402 constexpr int resolution = 12;
403 Vector<float2> ring = ring_vertices(2.0f, resolution);
404 for (int a : IndexRange(resolution)) {
405 float2 cv1 = ring[a % resolution];
406 float2 cv2 = ring[(a + 1) % resolution];
407 /* Head point. */
408 verts.append({{0.0f, 0.0f, 0.0f}, StickBoneFlag(POS_HEAD | COL_HEAD)});
409 verts.append({{cv1.x, cv1.y, 0.0f}, StickBoneFlag(POS_HEAD | COL_HEAD | COL_WIRE)});
410 verts.append({{cv2.x, cv2.y, 0.0f}, StickBoneFlag(POS_HEAD | COL_HEAD | COL_WIRE)});
411 /* Tail point. */
412 verts.append({{0.0f, 0.0f, 0.0f}, StickBoneFlag(POS_TAIL | COL_TAIL)});
413 verts.append({{cv1.x, cv1.y, 0.0f}, StickBoneFlag(POS_TAIL | COL_TAIL | COL_WIRE)});
414 verts.append({{cv2.x, cv2.y, 0.0f}, StickBoneFlag(POS_TAIL | COL_TAIL | COL_WIRE)});
415 }
416
417 bone_stick = BatchPtr(
418 GPU_batch_create_ex(GPU_PRIM_TRIS, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
419 }
420
421 /* Armature BBones. */
422 {
424 for (int tri = 0; tri < 12; tri++) {
425 for (int v = 0; v < 3; v++) {
429 }
430 }
431 bone_box = BatchPtr(
432 GPU_batch_create_ex(GPU_PRIM_TRIS, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
433 }
434 {
437
438 for (auto line : bone_box_wire_lines_adjacency) {
439 GPU_indexbuf_add_line_adj_verts(&elb, line[0], line[1], line[2], line[3]);
440 }
442
443 /* NOTE: Reuses the same VBO as bone_box. Thus has the same vertex format. */
445 GPU_PRIM_LINES_ADJ, bone_box.get()->verts[0], ibo, GPU_BATCH_OWNS_INDEX));
446 }
447
448 /* Armature Envelope. */
449 {
450 constexpr int lon_res = 24;
451 constexpr int lat_res = 24;
452 constexpr float lon_inc = 2.0f * M_PI / lon_res;
453 constexpr float lat_inc = M_PI / lat_res;
454
455 auto lat_lon_to_co = [](const float lat, const float lon) {
456 return float3(sinf(lat) * cosf(lon), sinf(lat) * sinf(lon), cosf(lat));
457 };
458
460 float lon = 0.0f;
461 for (int i = 0; i < lon_res; i++, lon += lon_inc) {
462 float lat = 0.0f;
463 /* NOTE: the poles are duplicated on purpose, to restart the strip. */
464 for (int j = 0; j < lat_res; j++, lat += lat_inc) {
465 verts.append({lat_lon_to_co(lat, lon), VCLASS_NONE});
466 verts.append({lat_lon_to_co(lat, lon + lon_inc), VCLASS_NONE});
467 }
468 /* Closing the loop */
469 verts.append({lat_lon_to_co(M_PI, lon), VCLASS_NONE});
470 verts.append({lat_lon_to_co(M_PI, lon + lon_inc), VCLASS_NONE});
471 }
472
474 GPU_PRIM_TRI_STRIP, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
475 }
476 {
477 constexpr int circle_resolution = 64;
478 float2 v0, v1, v2;
479
480 auto circle_pt = [](const float angle) { return float2(sinf(angle), cosf(angle)); };
481
483 /* Output 3 verts for each position. See shader for explanation. */
484 v0 = circle_pt((2.0f * M_PI * -2) / float(circle_resolution));
485 v1 = circle_pt((2.0f * M_PI * -1) / float(circle_resolution));
486 for (int a = 0; a <= circle_resolution; a++, v0 = v1, v1 = v2) {
487 v2 = circle_pt((2.0f * M_PI * a) / float(circle_resolution));
488 verts.append({v0, v1, v2});
489 }
490
492 GPU_PRIM_LINE_STRIP, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
493 }
494
495 /* Degrees of freedom. */
496 {
497 constexpr int resolution = 16;
498
500 auto set_vert = [&](const float x, const float y, const int quarter) {
501 verts.append({{(quarter % 2 == 0) ? -x : x, (quarter < 2) ? -y : y, 0.0f}, VCLASS_NONE});
502 };
503
504 for (int quarter : IndexRange(4)) {
505 float prev_z = 0.0f;
506 for (int i : IndexRange(1, resolution - 1)) {
507 float z = sinf(M_PI_2 * i / float(resolution - 1));
508 float prev_x = 0.0f;
509 for (int j : IndexRange(1, resolution - i)) {
510 float x = sinf(M_PI_2 * j / float(resolution - 1));
511 if (j == resolution - i) {
512 /* Pole triangle. */
513 set_vert(prev_x, z, quarter);
514 set_vert(prev_x, prev_z, quarter);
515 set_vert(x, prev_z, quarter);
516 }
517 else {
518 /* Quad. */
519 set_vert(x, z, quarter);
520 set_vert(x, prev_z, quarter);
521 set_vert(prev_x, z, quarter);
522
523 set_vert(x, prev_z, quarter);
524 set_vert(prev_x, prev_z, quarter);
525 set_vert(prev_x, z, quarter);
526 }
527 prev_x = x;
528 }
529 prev_z = z;
530 }
531 }
532
533 bone_degrees_of_freedom = BatchPtr(
534 GPU_batch_create_ex(GPU_PRIM_TRIS, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
535 }
536 {
537 constexpr int resolution = 16 * 4;
538 Vector<float2> ring = ring_vertices(1.0f, resolution);
539
541 for (int a : IndexRange(resolution + 1)) {
542 float2 cv = ring[a % resolution];
543 verts.append({{cv.x, cv.y, 0.0f}, VCLASS_NONE});
544 }
545
547 GPU_PRIM_LINE_STRIP, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
548 }
549
550 /* quad_wire */
551 {
553 verts.append({{-1.0f, -1.0f, 0.0f}, VCLASS_EMPTY_SCALED});
554 verts.append({{-1.0f, +1.0f, 0.0f}, VCLASS_EMPTY_SCALED});
555 verts.append({{-1.0f, +1.0f, 0.0f}, VCLASS_EMPTY_SCALED});
556 verts.append({{+1.0f, +1.0f, 0.0f}, VCLASS_EMPTY_SCALED});
557 verts.append({{+1.0f, +1.0f, 0.0f}, VCLASS_EMPTY_SCALED});
558 verts.append({{+1.0f, -1.0f, 0.0f}, VCLASS_EMPTY_SCALED});
559 verts.append({{+1.0f, -1.0f, 0.0f}, VCLASS_EMPTY_SCALED});
560 verts.append({{-1.0f, -1.0f, 0.0f}, VCLASS_EMPTY_SCALED});
561
562 quad_wire = BatchPtr(
563 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
564 }
565 /* quad_solid */
566 {
567 const Array<float2> quad = {{-1.0f, 1.0f}, {1.0f, 1.0f}, {-1.0f, -1.0f}, {1.0f, -1.0f}};
569 for (const float2 &point : quad) {
570 verts.append({{point, 0.0f}, VCLASS_EMPTY_SCALED});
571 }
573 GPU_PRIM_TRI_STRIP, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
574 }
575 /* plain_axes */
576 {
578 verts.append({{0.0f, -1.0f, 0.0f}, VCLASS_EMPTY_SCALED});
579 verts.append({{0.0f, +1.0f, 0.0f}, VCLASS_EMPTY_SCALED});
580 verts.append({{-1.0f, 0.0f, 0.0f}, VCLASS_EMPTY_SCALED});
581 verts.append({{+1.0f, 0.0f, 0.0f}, VCLASS_EMPTY_SCALED});
582 verts.append({{0.0f, 0.0f, -1.0f}, VCLASS_EMPTY_SCALED});
583 verts.append({{0.0f, 0.0f, +1.0f}, VCLASS_EMPTY_SCALED});
584
585 plain_axes = BatchPtr(
586 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
587 }
588 /* single_arrow */
589 {
591 float p[3][3] = {{0}};
592 p[0][2] = 1.0f;
593 p[1][0] = 0.035f;
594 p[1][1] = 0.035f;
595 p[2][0] = -0.035f;
596 p[2][1] = 0.035f;
597 p[1][2] = p[2][2] = 0.75f;
598 for (int sides : IndexRange(4)) {
599 if (sides % 2 == 1) {
600 p[1][0] = -p[1][0];
601 p[2][1] = -p[2][1];
602 }
603 else {
604 p[1][1] = -p[1][1];
605 p[2][0] = -p[2][0];
606 }
607 for (int i = 0, a = 1; i < 2; i++, a++) {
608 verts.append({{p[i][0], p[i][1], p[i][2]}, VCLASS_EMPTY_SCALED});
609 verts.append({{p[a][0], p[a][1], p[a][2]}, VCLASS_EMPTY_SCALED});
610 }
611 }
612 verts.append({{0.0f, 0.0f, 0.0}, VCLASS_EMPTY_SCALED});
613 verts.append({{0.0f, 0.0f, 0.75f}, VCLASS_EMPTY_SCALED});
614
615 single_arrow = BatchPtr(
616 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
617 }
618 /* cube */
619 {
621 for (auto index : bone_box_wire_lines) {
622 float x = bone_box_verts[index][0];
623 float y = bone_box_verts[index][1] * 2.0 - 1.0f;
624 float z = bone_box_verts[index][2];
625 verts.append({{x, y, z}, VCLASS_EMPTY_SCALED});
626 }
627
628 cube = BatchPtr(
629 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
630 }
631 /* cube_solid */
632 {
633 cube_solid = BatchPtr(GPU_batch_unit_cube());
634 }
635 /* circle */
636 {
637 constexpr int resolution = 64;
638 Vector<float2> ring = ring_vertices(1.0f, resolution);
639
641 for (int a : IndexRange(resolution + 1)) {
642 float2 cv1 = ring[(a + 0) % resolution];
643 float2 cv2 = ring[(a + 1) % resolution];
644 verts.append({{cv1.x, 0.0f, cv1.y}, VCLASS_EMPTY_SCALED});
645 verts.append({{cv2.x, 0.0f, cv2.y}, VCLASS_EMPTY_SCALED});
646 }
647
648 circle = BatchPtr(
649 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
650 }
651 /* empty_sphere */
652 {
654
655 empty_sphere = BatchPtr(
656 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
657 }
658 /* empty_cone */
659 {
660 constexpr int resolution = 8;
661 Vector<float2> ring = ring_vertices(1.0f, resolution);
662
664 for (int i : IndexRange(resolution)) {
665 float2 cv = ring[i % resolution];
666 /* Cone sides. */
667 verts.append({{cv[0], 0.0f, cv[1]}, VCLASS_EMPTY_SCALED});
668 verts.append({{0.0f, 2.0f, 0.0f}, VCLASS_EMPTY_SCALED});
669 /* Base ring. */
670 for (int j : IndexRange(2)) {
671 float2 cv = ring[(i + j) % resolution];
672 verts.append({{cv[0], 0.0f, cv[1]}, VCLASS_EMPTY_SCALED});
673 }
674 }
675
676 empty_cone = BatchPtr(
677 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
678 }
679 /* cylinder */
680 {
681 constexpr int n_segments = 12;
682 const Vector<float2> ring = ring_vertices(1.0f, n_segments);
684 /* top ring */
686 /* bottom ring */
688 /* cylinder sides */
689 for (const float2 &point : ring) {
690 verts.append({{point.x, point.y, 1.0f}, VCLASS_EMPTY_SCALED});
691 verts.append({{point.x, point.y, -1.0f}, VCLASS_EMPTY_SCALED});
692 }
693 cylinder = BatchPtr(
694 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
695 }
696 /* capsule body */
697 {
698 const Vector<float2> diamond = ring_vertices(1.0f, 4);
700 for (const float2 &point : diamond) {
701 verts.append({{point.x, point.y, 1.0f}, VCLASS_NONE});
702 verts.append({{point.x, point.y, 0.0f}, VCLASS_NONE});
703 }
704 capsule_body = BatchPtr(
705 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
706 }
707 /* capsule cap */
708 {
709 constexpr int n_segments = 24;
710 const Vector<float2> ring = ring_vertices(1.0f, n_segments);
712 /* Base circle */
713 append_line_loop(verts, ring, 0.0f, VCLASS_NONE);
714 for (const int i : IndexRange(n_segments / 2)) {
715 const float2 &point = ring[i];
716 const float2 &next_point = ring[i + 1];
717 /* Y half circle */
718 verts.append({{point.x, 0.0f, point.y}, VCLASS_NONE});
719 verts.append({{next_point.x, 0.0f, next_point.y}, VCLASS_NONE});
720 /* X half circle */
721 verts.append({{0.0f, point.x, point.y}, VCLASS_NONE});
722 verts.append({{0.0f, next_point.x, next_point.y}, VCLASS_NONE});
723 }
724 capsule_cap = BatchPtr(
725 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
726 }
727 /* arrows */
728 {
729 float2 x_axis_name_scale = {0.0215f, 0.025f};
730 Vector<float2> x_axis_name = {
731 float2(0.9f, 1.0f) * x_axis_name_scale,
732 float2(-1.0f, -1.0f) * x_axis_name_scale,
733 float2(-0.9f, 1.0f) * x_axis_name_scale,
734 float2(1.0f, -1.0f) * x_axis_name_scale,
735 };
736
737 float2 y_axis_name_scale = {0.0175f, 0.025f};
738 Vector<float2> y_axis_name = {
739 float2(-1.0f, 1.0f) * y_axis_name_scale,
740 float2(0.0f, -0.1f) * y_axis_name_scale,
741 float2(1.0f, 1.0f) * y_axis_name_scale,
742 float2(0.0f, -0.1f) * y_axis_name_scale,
743 float2(0.0f, -0.1f) * y_axis_name_scale,
744 float2(0.0f, -1.0f) * y_axis_name_scale,
745 };
746
747 float2 z_axis_name_scale = {0.02f, 0.025f};
748 Vector<float2> z_axis_name = {
749 float2(-0.95f, 1.00f) * z_axis_name_scale,
750 float2(0.95f, 1.00f) * z_axis_name_scale,
751 float2(0.95f, 1.00f) * z_axis_name_scale,
752 float2(0.95f, 0.90f) * z_axis_name_scale,
753 float2(0.95f, 0.90f) * z_axis_name_scale,
754 float2(-1.00f, -0.90f) * z_axis_name_scale,
755 float2(-1.00f, -0.90f) * z_axis_name_scale,
756 float2(-1.00f, -1.00f) * z_axis_name_scale,
757 float2(-1.00f, -1.00f) * z_axis_name_scale,
758 float2(1.00f, -1.00f) * z_axis_name_scale,
759 };
760
761 float2 axis_marker_scale = {0.007f, 0.007f};
762 Vector<float2> axis_marker = {
763#if 0 /* square */
764 float2(-1.0f, 1.0f) * axis_marker_scale,
765 float2(1.0f, 1.0f) * axis_marker_scale,
766 float2(1.0f, 1.0f) * axis_marker_scale,
767 float2(1.0f, -1.0f) * axis_marker_scale,
768 float2(1.0f, -1.0f) * axis_marker_scale,
769 float2(-1.0f, -1.0f) * axis_marker_scale,
770 float2(-1.0f, -1.0f) * axis_marker_scale,
771 float2(-1.0f, 1.0f) * axis_marker_scale,
772#else /* diamond */
773 float2(-1.0f, 0.0f) * axis_marker_scale,
774 float2(0.0f, 1.0f) * axis_marker_scale,
775 float2(0.0f, 1.0f) * axis_marker_scale,
776 float2(1.0f, 0.0f) * axis_marker_scale,
777 float2(1.0f, 0.0f) * axis_marker_scale,
778 float2(0.0f, -1.0f) * axis_marker_scale,
779 float2(0.0f, -1.0f) * axis_marker_scale,
780 float2(-1.0f, 0.0f) * axis_marker_scale,
781#endif
782 };
783
785 for (int axis : IndexRange(3)) {
786 /* Vertex layout is XY screen position and axis in Z.
787 * Fractional part of Z is a positive offset at axis unit position. */
789 /* Center to axis line. */
790 /* NOTE: overlay_armature_shape_wire_vert.glsl expects the axis verts at the origin to be the
791 * only ones with this coordinates (it derives the VCLASS from it). */
792 float pos_on_axis = float(axis) + 1e-8f;
793 verts.append({{0.0f, 0.0f, 0.0f}, VCLASS_NONE});
794 verts.append({{0.0f, 0.0f, pos_on_axis}, flag});
795 /* Axis end marker. */
796 constexpr int marker_fill_layer = 6;
797 for (int j = 1; j < marker_fill_layer + 1; j++) {
798 for (float2 axis_marker_vert : axis_marker) {
799 verts.append({{axis_marker_vert * ((4.0f * j) / marker_fill_layer), pos_on_axis}, flag});
800 }
801 }
802 /* Axis name. */
803 const Vector<float2> *axis_names[3] = {&x_axis_name, &y_axis_name, &z_axis_name};
804 for (float2 axis_name_vert : *(axis_names[axis])) {
806 verts.append({{axis_name_vert * 4.0f, pos_on_axis + 0.25f}, flag});
807 }
808 }
809 arrows = BatchPtr(
810 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
811 }
812 /* metaball_wire_circle */
813 {
814 constexpr int resolution = 64;
815 constexpr float radius = 1.0f;
816 Vector<float2> ring = ring_vertices(radius, resolution);
817
819 for (int i : IndexRange(resolution + 1)) {
820 float2 cv = ring[i % resolution];
821 verts.append({{cv[0], cv[1], 0.0f}, VCLASS_SCREENALIGNED});
822 }
824 GPU_PRIM_LINE_STRIP, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
825 };
826 /* speaker */
827 {
828 constexpr int segments = 16;
829 constexpr float bottom_r = 0.5f;
830 constexpr float bottom_z = -0.125f;
831 constexpr float step_z = 0.25f;
832 const Vector<float2> diamond = ring_vertices(bottom_r, 4);
833 Vector<float2> ring = ring_vertices(bottom_r, segments);
835
836 append_line_loop(verts, ring, bottom_z, VCLASS_NONE);
837 for (float2 &point : ring) {
838 point *= 0.5f;
839 }
840 for (const int j : IndexRange(1, 2)) {
841 const float z = step_z * j + bottom_z;
843 }
844
845 for (const float2 &point : diamond) {
846 Vertex vertex{float3(point, bottom_z)};
847 verts.append(vertex);
848 vertex.pos = float3(point * 0.5f, bottom_z + step_z);
849 verts.append(vertex);
850 verts.append(vertex);
851 vertex.pos.z += step_z;
852 verts.append(vertex);
853 }
854 speaker = BatchPtr(
855 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
856 }
857 /* camera distances */
858 {
859 const Vector<float2> diamond = ring_vertices(1.5f, 5);
860 const Vector<float2> cross = {{1.0f, 0.0f}, {-1.0f, 0.0f}, {0.0f, 1.0f}, {0.0f, -1.0f}};
861
863 verts.append({{0.0f, 0.0f, 0.0f}, VCLASS_CAMERA_DIST});
864 verts.append({{0.0f, 0.0f, 1.0f}, VCLASS_CAMERA_DIST});
865
868
869 /* Focus cross */
870 for (const float2 &point : cross) {
871 verts.append({{point.x, point.y, 2.0f}, VCLASS_CAMERA_DIST});
872 }
873 camera_distances = BatchPtr(
874 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
875 }
876 /* camera frame */
877 {
878 const Vector<float2> rect{{-1.0f, -1.0f}, {-1.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, -1.0f}};
880 /* Frame */
882 /* Wires to origin. */
883 for (const float2 &point : rect) {
884 verts.append({{point.x, point.y, 1.0f}, VCLASS_CAMERA_FRAME});
885 verts.append({{point.x, point.y, 0.0f}, VCLASS_CAMERA_FRAME});
886 }
887 camera_frame = BatchPtr(
888 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
889 }
890 /* camera tria */
891 {
892 const Vector<float2> triangle = {{-1.0f, 1.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}};
894 /* Wire */
896 camera_tria_wire = BatchPtr(
897 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
898
899 verts.clear();
900 /* Triangle */
901 for (const float2 &point : triangle) {
902 verts.append({{point.x, point.y, 1.0f}, VCLASS_CAMERA_FRAME});
903 }
904 camera_tria = BatchPtr(
905 GPU_batch_create_ex(GPU_PRIM_TRIS, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
906 }
907 /* camera volume */
908 {
910 for (const uint3 &tri : bone_box_solid_tris) {
911 for (const int i : IndexRange(uint3::type_length)) {
912 const int v = tri[i];
913 const float x = bone_box_verts[v][2];
914 const float y = bone_box_verts[v][0];
915 const float z = bone_box_verts[v][1];
917 }
918 }
919 camera_volume = BatchPtr(
920 GPU_batch_create_ex(GPU_PRIM_TRIS, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
921 }
922 /* camera volume wire */
923 {
925 for (int i : bone_box_wire_lines) {
926 const float x = bone_box_verts[i][2];
927 const float y = bone_box_verts[i][0];
928 const float z = bone_box_verts[i][1];
930 }
931 camera_volume_wire = BatchPtr(
932 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
933 }
934 /* spheres */
935 {
938 sphere_low_detail = BatchPtr(
939 GPU_batch_create_ex(GPU_PRIM_TRIS, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
940 }
941 /* ground line */
942 {
944
946 /* Ground Point */
947 append_line_loop(verts, ring, 0.0f, VCLASS_NONE);
948 /* Ground Line */
949 verts.append({{0.0, 0.0, 1.0}, VCLASS_NONE});
950 verts.append({{0.0, 0.0, 0.0}, VCLASS_NONE});
951
952 ground_line = BatchPtr(
953 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
954 }
955 /* image_quad */
956 {
957 const Array<float2> quad = {{0.0f, 1.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 0.0f}};
959 for (const float2 &point : quad) {
960 verts.append({{point, 0.75f}, VCLASS_NONE});
961 }
963 GPU_PRIM_TRI_STRIP, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
964 }
965 /* light spot volume */
966 {
968
969 /* Cone apex */
970 verts.append({{0.0f, 0.0f, 0.0f}, VCLASS_NONE});
971 /* Cone silhouette */
972 for (const int angle_i : IndexRange(circle_nsegments + 1)) {
973 const float angle = (2.0f * math::numbers::pi * angle_i) / circle_nsegments;
974 const float s = sinf(-angle);
975 const float c = cosf(-angle);
976 verts.append({{s, c, -1.0f}, VCLASS_LIGHT_SPOT_SHAPE});
977 }
979 GPU_PRIM_TRI_FAN, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
980 }
981 /* light icon outer lines */
982 {
983 constexpr float r = 9.0f;
984 const Vector<float2> ring = ring_vertices(r * 1.33f, outer_nsegments * 2);
985
987 append_line_loop(verts, ring, 0.0f, VCLASS_SCREENSPACE, true);
988 light_icon_outer_lines = BatchPtr(
989 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
990 }
991 /* light icon inner lines */
992 {
993 constexpr float r = 9.0f;
994 const Vector<float2> diamond = ring_vertices(r * 0.3f, diamond_nsegments);
995 const Vector<float2> ring = ring_vertices(r, inner_nsegments * 2);
996
999 append_line_loop(verts, ring, 0.0f, VCLASS_SCREENSPACE, true);
1000
1001 light_icon_inner_lines = BatchPtr(
1002 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
1003 }
1004 /* light icon sun rays */
1005 {
1006 constexpr int num_rays = 8;
1007 constexpr float r = 9.0f;
1008 const Vector<float2> ring = ring_vertices(r, num_rays);
1009 const std::array<float, 4> scales{1.6f, 1.9f, 2.2f, 2.5f};
1010
1012 for (const float2 &point : ring) {
1013 for (float scale : scales) {
1014 float2 scaled = point * scale;
1015 verts.append({{scaled.x, scaled.y, 0.0f}, VCLASS_SCREENSPACE});
1016 }
1017 }
1018 light_icon_sun_rays = BatchPtr(
1019 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
1020 }
1021 /* light point lines */
1022 {
1023 const Vector<float2> ring = ring_vertices(1.0f, circle_nsegments);
1024
1027 light_point_lines = BatchPtr(
1028 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
1029 }
1030 /* light sun lines */
1031 {
1033 /* Direction Line */
1034 verts.append({{0.0, 0.0, 0.0}, VCLASS_NONE});
1035 verts.append({{0.0, 0.0, -20.0}, VCLASS_NONE}); /* Good default. */
1036 light_sun_lines = BatchPtr(
1037 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
1038 }
1039 /* light spot lines */
1040 {
1041 const Vector<float2> ring = ring_vertices(1.0f, circle_nsegments);
1042
1044 /* Light area */
1046 /* Cone cap */
1049 /* Cone silhouette */
1050 for (const float2 &point : ring) {
1051 verts.append({{0.0f, 0.0f, 0.0f}, VCLASS_NONE});
1052 verts.append({{point.x, point.y, -1.0f}, VCLASS_LIGHT_SPOT_SHAPE | VCLASS_LIGHT_SPOT_CONE});
1053 }
1054
1056
1057 light_spot_lines = BatchPtr(
1058 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
1059 }
1060 /* light area disk lines */
1061 {
1062 const Vector<float2> ring = ring_vertices(0.5f, circle_nsegments);
1063
1065 /* Light area */
1067
1069
1070 light_area_disk_lines = BatchPtr(
1071 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
1072 }
1073 /* light area square lines */
1074 {
1075 const Array<float2> rect{{-0.5f, -0.5f}, {-0.5f, 0.5f}, {0.5f, 0.5f}, {0.5f, -0.5f}};
1076
1078 /* Light area */
1080
1082
1083 light_area_square_lines = BatchPtr(
1084 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
1085 }
1086 /* field_force */
1087 {
1088 constexpr int circle_resol = 32;
1090 constexpr std::array<float, 2> scales{2.0f, 0.75};
1091 Vector<float2> ring = ring_vertices(1.0f, circle_resol);
1092
1094
1095 append_line_loop(verts, ring, 0.0f, flag);
1096 for (const float scale : scales) {
1097 for (float2 &point : ring) {
1098 point *= scale;
1099 }
1100 append_line_loop(verts, ring, 0.0f, flag);
1101 }
1102
1103 field_force = BatchPtr(
1104 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
1105 }
1106 /* field_wind */
1107 {
1108 constexpr int circle_resol = 32;
1109 const Vector<float2> ring = ring_vertices(1.0f, circle_resol);
1110
1112
1113 for (const int i : IndexRange(4)) {
1114 const float z = 0.05f * float(i);
1116 }
1117
1118 field_wind = BatchPtr(
1119 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
1120 }
1121 /* field_vortex */
1122 {
1123 constexpr int spiral_resol = 32;
1124 const Vector<float2> ring = ring_vertices(1.0f, spiral_resol);
1125
1127
1128 for (const int i : IndexRange(ring.size() * 2 + 1)) {
1129 /* r: [-1, .., 0, .., 1] */
1130 const float r = (i - spiral_resol) / float(spiral_resol);
1131 /* index: [9, spiral_resol - 1, spiral_resol - 2, .., 2, 1, 0, 1, 2, .., spiral_resol - 1, 0]
1132 */
1133 const float2 point = ring[abs(spiral_resol - i) % spiral_resol] * r;
1134 verts.append({float3(point.y, point.x, 0.0f), VCLASS_EMPTY_SIZE});
1135 }
1137 GPU_PRIM_LINE_STRIP, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
1138 }
1139 /* field_curve */
1140 {
1141 constexpr int circle_resol = 32;
1142 const Vector<float2> ring = ring_vertices(1.0f, circle_resol);
1143
1145
1147
1148 field_curve = BatchPtr(
1149 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
1150 }
1151 /* field_sphere_limit */
1152 {
1153 constexpr int circle_resol = 32 * 2;
1154 const Vector<float2> ring = ring_vertices(1.0f, circle_resol);
1155
1157
1159
1160 field_sphere_limit = BatchPtr(
1161 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
1162 }
1163 /* field_tube_limit */
1164 {
1165 constexpr int circle_resol = 32;
1166 constexpr int side_stipple = 32;
1167 const Vector<float2> ring = ring_vertices(1.0f, circle_resol);
1168 const Vector<float2> diamond = ring_vertices(1.0f, 4);
1169
1171
1172 /* Caps */
1173 for (const int i : IndexRange(2)) {
1174 const float z = i * 2.0f - 1.0f;
1176 }
1177 /* Side Edges */
1178 for (const float2 &point : diamond) {
1179 for (const int i : IndexRange(side_stipple)) {
1180 const float z = (i / float(side_stipple)) * 2.0f - 1.0f;
1181 verts.append({float3(point.y, point.x, z), VCLASS_EMPTY_SIZE});
1182 }
1183 }
1184
1185 field_tube_limit = BatchPtr(
1186 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
1187 }
1188 /* field_cone_limit */
1189 {
1190 constexpr int circle_resol = 32;
1191 constexpr int side_stipple = 32;
1192 const Vector<float2> ring = ring_vertices(1.0f, circle_resol);
1193 const Vector<float2> diamond = ring_vertices(1.0f, 4);
1194
1196
1197 /* Caps */
1198 for (const int i : IndexRange(2)) {
1199 const float z = i * 2.0f - 1.0f;
1201 }
1202 /* Side Edges */
1203 for (const float2 &point : diamond) {
1204 for (const int i : IndexRange(side_stipple)) {
1205 const float z = (i / float(side_stipple)) * 2.0f - 1.0f;
1206 verts.append({float3(point.y * z, point.x * z, z), VCLASS_EMPTY_SIZE});
1207 }
1208 }
1209
1210 field_cone_limit = BatchPtr(
1211 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
1212 }
1213 /* lightprobe_cube */
1214 {
1215 constexpr float r = 14.0f;
1217 /* Icon */
1218 constexpr float sin_pi_3 = 0.86602540378f;
1219 constexpr float cos_pi_3 = 0.5f;
1220 const Array<float2, 6> points = {
1221 float2(0.0f, 1.0f) * r,
1222 float2(sin_pi_3, cos_pi_3) * r,
1223 float2(sin_pi_3, -cos_pi_3) * r,
1224 float2(0.0f, -1.0f) * r,
1225 float2(-sin_pi_3, -cos_pi_3) * r,
1226 float2(-sin_pi_3, cos_pi_3) * r,
1227 };
1228
1230
1231 append_line_loop(verts, points, 0.0f, flag);
1232 for (const int i : IndexRange(3)) {
1233 const float2 &point = points[i * 2 + 1];
1234 verts.append(Vertex{{point, 0.0f}, flag});
1235 verts.append(Vertex{{0.0f, 0.0f, 0.0f}, flag});
1236 }
1237
1238 /* Direction Lines */
1239 const Vector<float2> diamond = ring_vertices(1.2f, diamond_nsegments);
1240 const std::string axes = "zZyYxX";
1241 for (const char axis : axes) {
1242 light_append_direction_line(axis, diamond, verts);
1243 }
1244
1245 lightprobe_cube = BatchPtr(
1246 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
1247 }
1248 /* lightprobe_planar */
1249 {
1250 constexpr float r = 20.0f;
1251 /* Icon */
1252 constexpr float sin_pi_3 = 0.86602540378f;
1253 const Array<float2, 4> points = {
1254 float2(0.0f, 0.5f) * r,
1255 float2(sin_pi_3, 0.0f) * r,
1256 float2(0.0f, -0.5f) * r,
1257 float2(-sin_pi_3, 0.0f) * r,
1258 };
1259
1261
1263 lightprobe_planar = BatchPtr(
1264 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
1265 }
1266 /* lightprobe_grid */
1267 {
1268 constexpr float r = 14.0f;
1270 /* Icon */
1271 constexpr float sin_pi_3 = 0.86602540378f;
1272 constexpr float cos_pi_3 = 0.5f;
1273 const Array<float2, 6> points = {float2(0.0f, 1.0f) * r,
1274 float2(sin_pi_3, cos_pi_3) * r,
1275 float2(sin_pi_3, -cos_pi_3) * r,
1276 float2(0.0f, -1.0f) * r,
1277 float2(-sin_pi_3, -cos_pi_3) * r,
1278 float2(-sin_pi_3, cos_pi_3) * r};
1280
1281 append_line_loop(verts, points, 0.0f, flag);
1282 /* Internal wires. */
1283 for (const int i : IndexRange(6)) {
1284 const float2 tr = points[(i / 2) * 2 + 1] * -0.5f;
1285 const float2 t1 = points[i] + tr;
1286 const float2 t2 = points[(i + 1) % 6] + tr;
1287 verts.append({{t1, 0.0f}, flag});
1288 verts.append({{t2, 0.0f}, flag});
1289 }
1290 for (const int i : IndexRange(3)) {
1291 const float2 &point = points[i * 2 + 1];
1292 verts.append(Vertex{{point, 0.0f}, flag});
1293 verts.append(Vertex{{0.0f, 0.0f, 0.0f}, flag});
1294 }
1295 /* Direction Lines */
1296 const Vector<float2> diamond = ring_vertices(1.2f, diamond_nsegments);
1297 const std::string axes = "zZyYxX";
1298 for (const char axis : axes) {
1299 light_append_direction_line(axis, diamond, verts);
1300 }
1301
1302 lightprobe_grid = BatchPtr(
1303 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
1304 }
1305 /* grid */
1306 {
1307 constexpr int resolution = 8;
1308 std::array<float, resolution + 1> steps;
1309 /* [-1, 1] divided into "resolution" steps. */
1310 for (const int i : IndexRange(resolution + 1)) {
1311 steps[i] = -1.0f + float(i * 2) / resolution;
1312 }
1313
1315 verts.reserve(resolution * resolution * 6);
1316 for (const int x : IndexRange(resolution)) {
1317 for (const int y : IndexRange(resolution)) {
1318 verts.append(Vertex{{steps[x], steps[y], 0.0f}});
1319 verts.append(Vertex{{steps[x + 1], steps[y], 0.0f}});
1320 verts.append(Vertex{{steps[x], steps[y + 1], 0.0f}});
1321
1322 verts.append(Vertex{{steps[x], steps[y + 1], 0.0f}});
1323 verts.append(Vertex{{steps[x + 1], steps[y], 0.0f}});
1324 verts.append(Vertex{{steps[x + 1], steps[y + 1], 0.0f}});
1325 }
1326 }
1327 grid = BatchPtr(
1328 GPU_batch_create_ex(GPU_PRIM_TRIS, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
1329 }
1330 /* cursor circle */
1331 {
1332 const int segments = 12;
1333 const float radius = 0.5f;
1334 const float color_primary[3] = {1.0f, 0.0f, 0.0f};
1335 const float color_secondary[3] = {1.0f, 1.0f, 1.0f};
1336
1338
1339 for (int i = 0; i < segments + 1; i++) {
1340 float angle = float(2 * M_PI) * (float(i) / float(segments));
1341 verts.append({radius * float3(cosf(angle), sinf(angle), 0.0f),
1342 (i % 2 == 0) ? color_secondary : color_primary});
1343 }
1344
1346 GPU_PRIM_LINE_STRIP, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
1347 }
1348 /* cursor lines */
1349 {
1350 const float outer_limit = 1.0f;
1351 const float color_limit = 0.85f;
1352 const float inner_limit = 0.25f;
1353 const std::array<int, 3> axis_theme = {TH_AXIS_X, TH_AXIS_Y, TH_AXIS_Z};
1354
1355 float crosshair_color[3];
1356
1358
1359 for (int i = 0; i < 3; i++) {
1360 float3 axis(0.0f);
1361 axis[i] = 1.0f;
1362 /* Draw the positive axes. */
1363 UI_GetThemeColor3fv(axis_theme[i], crosshair_color);
1364 verts.append({outer_limit * axis, crosshair_color});
1365 verts.append({color_limit * axis, crosshair_color});
1366
1367 /* Inner crosshair. */
1368 UI_GetThemeColor3fv(TH_VIEW_OVERLAY, crosshair_color);
1369 verts.append({color_limit * axis, crosshair_color});
1370 verts.append({inner_limit * axis, crosshair_color});
1371
1372 /* Draw the negative axis a little darker and desaturated. */
1373 axis[i] = -1.0f;
1374 UI_GetThemeColorBlendShade3fv(axis_theme[i], TH_WHITE, .25f, -60, crosshair_color);
1375 verts.append({outer_limit * axis, crosshair_color});
1376 verts.append({color_limit * axis, crosshair_color});
1377
1378 /* Inner crosshair. */
1379 UI_GetThemeColor3fv(TH_VIEW_OVERLAY, crosshair_color);
1380 verts.append({color_limit * axis, crosshair_color});
1381 verts.append({inner_limit * axis, crosshair_color});
1382 }
1383
1384 cursor_lines = BatchPtr(
1385 GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
1386 }
1387}
1388
1389} // namespace blender::draw::overlay
#define BLI_assert(a)
Definition BLI_assert.h:46
#define M_PI_2
#define M_SQRT1_2
#define M_PI
#define UNUSED_VARS(...)
#define GPU_batch_create(primitive_type, vertex_buf, index_buf)
Definition GPU_batch.hh:141
blender::gpu::Batch * GPU_batch_create_ex(GPUPrimType primitive_type, blender::gpu::VertBuf *vertex_buf, blender::gpu::IndexBuf *index_buf, GPUBatchFlag owns_flag)
Definition gpu_batch.cc:51
@ GPU_BATCH_OWNS_INDEX
Definition GPU_batch.hh:46
@ GPU_BATCH_OWNS_VBO
Definition GPU_batch.hh:42
blender::gpu::Batch * GPU_batch_unit_cube() ATTR_WARN_UNUSED_RESULT
void GPU_indexbuf_init(GPUIndexBufBuilder *, GPUPrimType, uint prim_len, uint vertex_len)
blender::gpu::IndexBuf * GPU_indexbuf_build(GPUIndexBufBuilder *)
void GPU_indexbuf_add_line_adj_verts(GPUIndexBufBuilder *, uint v1, uint v2, uint v3, uint v4)
@ GPU_PRIM_TRI_FAN
@ GPU_PRIM_LINES
@ GPU_PRIM_LINES_ADJ
@ GPU_PRIM_LINE_STRIP
@ GPU_PRIM_TRI_STRIP
@ GPU_PRIM_TRIS
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:117
void UI_GetThemeColor3fv(int colorid, float col[3])
@ TH_WHITE
@ TH_AXIS_Y
@ TH_AXIS_X
@ TH_AXIS_Z
@ TH_VIEW_OVERLAY
void UI_GetThemeColorBlendShade3fv(int colorid1, int colorid2, float fac, int offset, float col[3])
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
btMatrix3x3 scaled(const btVector3 &s) const
Create a scaled copy of the matrix.
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
constexpr int64_t last(const int64_t n=0) const
int64_t size() const
void append(const T &value)
IndexRange index_range() const
Definition half.h:41
nullptr float
#define VCLASS_LIGHT_AREA_SHAPE
Definition draw_cache.cc:45
#define VCLASS_CAMERA_DIST
Definition draw_cache.cc:52
#define VCLASS_EMPTY_AXES_NAME
Definition draw_cache.cc:60
#define VCLASS_LIGHT_SPOT_BLEND
Definition draw_cache.cc:47
#define VCLASS_EMPTY_AXES
Definition draw_cache.cc:59
#define VCLASS_EMPTY_SCALED
Definition draw_cache.cc:58
#define VCLASS_LIGHT_DIST
Definition draw_cache.cc:49
#define VCLASS_LIGHT_SPOT_SHAPE
Definition draw_cache.cc:46
#define VCLASS_CAMERA_FRAME
Definition draw_cache.cc:51
#define VCLASS_CAMERA_VOLUME
Definition draw_cache.cc:53
#define VCLASS_LIGHT_SPOT_CONE
Definition draw_cache.cc:48
#define VCLASS_SCREENALIGNED
Definition draw_cache.cc:56
#define VCLASS_SCREENSPACE
Definition draw_cache.cc:55
#define VCLASS_EMPTY_SIZE
Definition draw_cache.cc:62
static float verts[][3]
blender::gpu::Batch * quad
#define abs
static const std::array< uint3, 12 > bone_box_solid_tris
static const std::array< float3, 12 > bone_box_solid_normals
static constexpr int circle_nsegments
static Vector< float2 > ring_vertices(const float radius, const int segments, const bool half=false)
static const float bone_octahedral_solid_normals[8][3]
static const std::array< float3, 6 > bone_octahedral_verts
static float light_distance_z_get(char axis, const bool start)
static constexpr int inner_nsegments
static constexpr float bone_box_verts[8][3]
static constexpr int diamond_nsegments
static const std::array< uint3, 8 > bone_octahedral_solid_tris
static const std::array< float3, 6 > bone_octahedral_smooth_normals
static const std::array< uint2, 12 > bone_octahedral_wire_lines
static void light_append_direction_line(const char axis, Span< float2 > diamond, Vector< Vertex > &verts)
static void append_sphere(Vector< VertShaded > &dest, const eDRWLevelOfDetail level_of_detail)
static constexpr std::array< uint, 24 > bone_box_wire_lines
static VertShaded sphere_lat_lon_vert(const float2 &lat_pt, const float2 &lon_pt)
static const std::array< uint4, 12 > bone_box_wire_lines_adjacency
static Vector< Vertex > sphere_axes_circles(const float radius, const VertexClass vclass, const int segments)
static void append_line_loop(Vector< Vertex > &dest, Span< float2 > verts, float z, VertexClass flag, bool dashed=false)
static constexpr int outer_nsegments
static const std::array< uint4, 12 > bone_octahedral_wire_lines_adjacency
T cos(const AngleRadianBase< T > &a)
MatBase< T, NumCol, NumRow > scale(const MatBase< T, NumCol, NumRow > &mat, const VectorT &scale)
T step(const T &edge, const T &value)
AxisSigned cross(const AxisSigned a, const AxisSigned b)
T sin(const AngleRadianBase< T > &a)
VecBase< uint32_t, 2 > uint2
VecBase< uint32_t, 4 > uint4
VecBase< uint32_t, 3 > uint3
VecBase< float, 2 > float2
VecBase< float, 3 > float3
#define sinf
#define cosf
i
Definition text_draw.cc:230
uint8_t flag
Definition wm_window.cc:145