Cleanup: warnings (clang)
[blender.git] / source / blender / draw / intern / draw_cache.c
1 /*
2  * Copyright 2016, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Blender Institute
19  *
20  */
21
22 /** \file draw_cache.c
23  *  \ingroup draw
24  */
25
26
27 #include "DNA_scene_types.h"
28 #include "DNA_mesh_types.h"
29 #include "DNA_meta_types.h"
30 #include "DNA_curve_types.h"
31 #include "DNA_object_types.h"
32 #include "DNA_particle_types.h"
33 #include "DNA_modifier_types.h"
34 #include "DNA_lattice_types.h"
35
36 #include "UI_resources.h"
37
38 #include "BLI_utildefines.h"
39 #include "BLI_math.h"
40 #include "BLI_listbase.h"
41
42 #include "BKE_object.h"
43 #include "BKE_object_deform.h"
44
45 #include "GPU_batch.h"
46 #include "GPU_batch_presets.h"
47 #include "GPU_batch_utils.h"
48
49 #include "MEM_guardedalloc.h"
50
51 #include "draw_cache.h"
52 #include "draw_cache_impl.h"
53 #include "draw_manager.h"
54
55 /* Batch's only (free'd as an array) */
56 static struct DRWShapeCache {
57         GPUBatch *drw_single_vertice;
58         GPUBatch *drw_cursor;
59         GPUBatch *drw_cursor_only_circle;
60         GPUBatch *drw_fullscreen_quad;
61         GPUBatch *drw_fullscreen_quad_texcoord;
62         GPUBatch *drw_quad;
63         GPUBatch *drw_grid;
64         GPUBatch *drw_sphere;
65         GPUBatch *drw_screenspace_circle;
66         GPUBatch *drw_plain_axes;
67         GPUBatch *drw_single_arrow;
68         GPUBatch *drw_cube;
69         GPUBatch *drw_circle;
70         GPUBatch *drw_square;
71         GPUBatch *drw_line;
72         GPUBatch *drw_line_endpoints;
73         GPUBatch *drw_empty_cube;
74         GPUBatch *drw_empty_sphere;
75         GPUBatch *drw_empty_cylinder;
76         GPUBatch *drw_empty_capsule_body;
77         GPUBatch *drw_empty_capsule_cap;
78         GPUBatch *drw_empty_cone;
79         GPUBatch *drw_arrows;
80         GPUBatch *drw_axis_names;
81         GPUBatch *drw_image_plane;
82         GPUBatch *drw_image_plane_wire;
83         GPUBatch *drw_field_wind;
84         GPUBatch *drw_field_force;
85         GPUBatch *drw_field_vortex;
86         GPUBatch *drw_field_tube_limit;
87         GPUBatch *drw_field_cone_limit;
88         GPUBatch *drw_lamp;
89         GPUBatch *drw_lamp_shadows;
90         GPUBatch *drw_lamp_sunrays;
91         GPUBatch *drw_lamp_area_square;
92         GPUBatch *drw_lamp_area_disk;
93         GPUBatch *drw_lamp_hemi;
94         GPUBatch *drw_lamp_spot;
95         GPUBatch *drw_lamp_spot_volume;
96         GPUBatch *drw_lamp_spot_square;
97         GPUBatch *drw_lamp_spot_square_volume;
98         GPUBatch *drw_speaker;
99         GPUBatch *drw_lightprobe_cube;
100         GPUBatch *drw_lightprobe_planar;
101         GPUBatch *drw_lightprobe_grid;
102         GPUBatch *drw_bone_octahedral;
103         GPUBatch *drw_bone_octahedral_wire;
104         GPUBatch *drw_bone_box;
105         GPUBatch *drw_bone_box_wire;
106         GPUBatch *drw_bone_wire_wire;
107         GPUBatch *drw_bone_envelope;
108         GPUBatch *drw_bone_envelope_outline;
109         GPUBatch *drw_bone_point;
110         GPUBatch *drw_bone_point_wire;
111         GPUBatch *drw_bone_stick;
112         GPUBatch *drw_bone_arrows;
113         GPUBatch *drw_bone_dof_sphere;
114         GPUBatch *drw_bone_dof_lines;
115         GPUBatch *drw_camera;
116         GPUBatch *drw_camera_frame;
117         GPUBatch *drw_camera_tria;
118         GPUBatch *drw_camera_focus;
119         GPUBatch *drw_particle_cross;
120         GPUBatch *drw_particle_circle;
121         GPUBatch *drw_particle_axis;
122         GPUBatch *drw_gpencil_axes;
123 } SHC = {NULL};
124
125 void DRW_shape_cache_free(void)
126 {
127         uint i = sizeof(SHC) / sizeof(GPUBatch *);
128         GPUBatch **batch = (GPUBatch **)&SHC;
129         while (i--) {
130                 GPU_BATCH_DISCARD_SAFE(*batch);
131                 batch++;
132         }
133 }
134
135 void DRW_shape_cache_reset(void)
136 {
137         uint i = sizeof(SHC) / sizeof(GPUBatch *);
138         GPUBatch **batch = (GPUBatch **)&SHC;
139         while (i--) {
140                 if (*batch) {
141                         GPU_batch_vao_cache_clear(*batch);
142                 }
143                 batch++;
144         }
145 }
146
147 /* -------------------------------------------------------------------- */
148
149 /** \name Helper functions
150  * \{ */
151
152 static void UNUSED_FUNCTION(add_fancy_edge)(
153         GPUVertBuf *vbo, uint pos_id, uint n1_id, uint n2_id,
154         uint *v_idx, const float co1[3], const float co2[3],
155         const float n1[3], const float n2[3])
156 {
157         GPU_vertbuf_attr_set(vbo, n1_id, *v_idx, n1);
158         GPU_vertbuf_attr_set(vbo, n2_id, *v_idx, n2);
159         GPU_vertbuf_attr_set(vbo, pos_id, (*v_idx)++, co1);
160
161         GPU_vertbuf_attr_set(vbo, n1_id, *v_idx, n1);
162         GPU_vertbuf_attr_set(vbo, n2_id, *v_idx, n2);
163         GPU_vertbuf_attr_set(vbo, pos_id, (*v_idx)++, co2);
164 }
165
166 #if 0 /* UNUSED */
167 static void add_lat_lon_vert(
168         GPUVertBuf *vbo, uint pos_id, uint nor_id,
169         uint *v_idx, const float rad, const float lat, const float lon)
170 {
171         float pos[3], nor[3];
172         nor[0] = sinf(lat) * cosf(lon);
173         nor[1] = cosf(lat);
174         nor[2] = sinf(lat) * sinf(lon);
175         mul_v3_v3fl(pos, nor, rad);
176
177         GPU_vertbuf_attr_set(vbo, nor_id, *v_idx, nor);
178         GPU_vertbuf_attr_set(vbo, pos_id, (*v_idx)++, pos);
179 }
180
181 static GPUVertBuf *fill_arrows_vbo(const float scale)
182 {
183         /* Position Only 3D format */
184         static GPUVertFormat format = { 0 };
185         static struct { uint pos; } attr_id;
186         if (format.attr_len == 0) {
187                 attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
188         }
189
190         /* Line */
191         GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
192         GPU_vertbuf_data_alloc(vbo, 6 * 3);
193
194         float v1[3] = {0.0, 0.0, 0.0};
195         float v2[3] = {0.0, 0.0, 0.0};
196         float vtmp1[3], vtmp2[3];
197
198         for (int axis = 0; axis < 3; axis++) {
199                 const int arrow_axis = (axis == 0) ? 1 : 0;
200
201                 v2[axis] = 1.0f;
202                 mul_v3_v3fl(vtmp1, v1, scale);
203                 mul_v3_v3fl(vtmp2, v2, scale);
204                 GPU_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 0, vtmp1);
205                 GPU_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 1, vtmp2);
206
207                 v1[axis] = 0.85f;
208                 v1[arrow_axis] = -0.08f;
209                 mul_v3_v3fl(vtmp1, v1, scale);
210                 mul_v3_v3fl(vtmp2, v2, scale);
211                 GPU_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 2, vtmp1);
212                 GPU_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 3, vtmp2);
213
214                 v1[arrow_axis] = 0.08f;
215                 mul_v3_v3fl(vtmp1, v1, scale);
216                 mul_v3_v3fl(vtmp2, v2, scale);
217                 GPU_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 4, vtmp1);
218                 GPU_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 5, vtmp2);
219
220                 /* reset v1 & v2 to zero */
221                 v1[arrow_axis] = v1[axis] = v2[axis] = 0.0f;
222         }
223
224         return vbo;
225 }
226 #endif  /* UNUSED */
227
228 static GPUVertBuf *sphere_wire_vbo(const float rad)
229 {
230 #define NSEGMENTS 32
231         /* Position Only 3D format */
232         static GPUVertFormat format = { 0 };
233         static struct { uint pos; } attr_id;
234         if (format.attr_len == 0) {
235                 attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
236         }
237
238         GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
239         GPU_vertbuf_data_alloc(vbo, NSEGMENTS * 2 * 3);
240
241         /* a single ring of vertices */
242         float p[NSEGMENTS][2];
243         for (int i = 0; i < NSEGMENTS; ++i) {
244                 float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS);
245                 p[i][0] = rad * cosf(angle);
246                 p[i][1] = rad * sinf(angle);
247         }
248
249         for (int axis = 0; axis < 3; ++axis) {
250                 for (int i = 0; i < NSEGMENTS; ++i) {
251                         for (int j = 0; j < 2; ++j) {
252                                 float cv[2], v[3];
253
254                                 cv[0] = p[(i + j) % NSEGMENTS][0];
255                                 cv[1] = p[(i + j) % NSEGMENTS][1];
256
257                                 if (axis == 0) {
258                                         ARRAY_SET_ITEMS(v, cv[0], cv[1], 0.0f);
259                                 }
260                                 else if (axis == 1) {
261                                         ARRAY_SET_ITEMS(v, cv[0], 0.0f, cv[1]);
262                                 }
263                                 else {
264                                         ARRAY_SET_ITEMS(v, 0.0f, cv[0], cv[1]);
265                                 }
266                                 GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 2 + j + (NSEGMENTS * 2 * axis), v);
267                         }
268                 }
269         }
270
271         return vbo;
272 #undef NSEGMENTS
273 }
274
275 /* Quads */
276 /* Use this one for rendering fullscreen passes. For 3D objects use DRW_cache_quad_get(). */
277 GPUBatch *DRW_cache_fullscreen_quad_get(void)
278 {
279         if (!SHC.drw_fullscreen_quad) {
280                 /* Use a triangle instead of a real quad */
281                 /* https://www.slideshare.net/DevCentralAMD/vertex-shader-tricks-bill-bilodeau - slide 14 */
282                 float pos[3][2] = {{-1.0f, -1.0f}, { 3.0f, -1.0f}, {-1.0f,  3.0f}};
283                 float uvs[3][2] = {{ 0.0f,  0.0f}, { 2.0f,  0.0f}, { 0.0f,  2.0f}};
284
285                 /* Position Only 2D format */
286                 static GPUVertFormat format = { 0 };
287                 static struct { uint pos, uvs; } attr_id;
288                 if (format.attr_len == 0) {
289                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
290                         attr_id.uvs = GPU_vertformat_attr_add(&format, "uvs", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
291                         GPU_vertformat_alias_add(&format, "texCoord");
292                 }
293
294                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
295                 GPU_vertbuf_data_alloc(vbo, 3);
296
297                 for (int i = 0; i < 3; ++i) {
298                         GPU_vertbuf_attr_set(vbo, attr_id.pos, i, pos[i]);
299                         GPU_vertbuf_attr_set(vbo, attr_id.uvs, i, uvs[i]);
300                 }
301
302                 SHC.drw_fullscreen_quad = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
303         }
304         return SHC.drw_fullscreen_quad;
305 }
306
307 /* Just a regular quad with 4 vertices. */
308 GPUBatch *DRW_cache_quad_get(void)
309 {
310         if (!SHC.drw_quad) {
311                 float pos[4][2] = {{-1.0f, -1.0f}, { 1.0f, -1.0f}, {1.0f,  1.0f}, {-1.0f,  1.0f}};
312                 float uvs[4][2] = {{ 0.0f,  0.0f}, { 1.0f,  0.0f}, {1.0f,  1.0f}, { 0.0f,  1.0f}};
313
314                 /* Position Only 2D format */
315                 static GPUVertFormat format = { 0 };
316                 static struct { uint pos, uvs; } attr_id;
317                 if (format.attr_len == 0) {
318                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
319                         attr_id.uvs = GPU_vertformat_attr_add(&format, "uvs", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
320                 }
321
322                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
323                 GPU_vertbuf_data_alloc(vbo, 4);
324
325                 for (int i = 0; i < 4; ++i) {
326                         GPU_vertbuf_attr_set(vbo, attr_id.pos, i, pos[i]);
327                         GPU_vertbuf_attr_set(vbo, attr_id.uvs, i, uvs[i]);
328                 }
329
330                 SHC.drw_quad = GPU_batch_create_ex(GPU_PRIM_TRI_FAN, vbo, NULL, GPU_BATCH_OWNS_VBO);
331         }
332         return SHC.drw_quad;
333 }
334
335 /* Grid */
336 GPUBatch *DRW_cache_grid_get(void)
337 {
338         if (!SHC.drw_grid) {
339                 /* Position Only 2D format */
340                 static GPUVertFormat format = { 0 };
341                 static struct { uint pos; } attr_id;
342                 if (format.attr_len == 0) {
343                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
344                 }
345
346                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
347                 GPU_vertbuf_data_alloc(vbo, 8 * 8 * 2 * 3);
348
349                 uint v_idx = 0;
350                 for (int i = 0; i < 8; ++i) {
351                         for (int j = 0; j < 8; ++j) {
352                                 float pos0[2] = {(float)i / 8.0f, (float)j / 8.0f};
353                                 float pos1[2] = {(float)(i + 1) / 8.0f, (float)j / 8.0f};
354                                 float pos2[2] = {(float)i / 8.0f, (float)(j + 1) / 8.0f};
355                                 float pos3[2] = {(float)(i + 1) / 8.0f, (float)(j + 1) / 8.0f};
356
357                                 madd_v2_v2v2fl(pos0, (float[2]){-1.0f, -1.0f}, pos0, 2.0f);
358                                 madd_v2_v2v2fl(pos1, (float[2]){-1.0f, -1.0f}, pos1, 2.0f);
359                                 madd_v2_v2v2fl(pos2, (float[2]){-1.0f, -1.0f}, pos2, 2.0f);
360                                 madd_v2_v2v2fl(pos3, (float[2]){-1.0f, -1.0f}, pos3, 2.0f);
361
362                                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, pos0);
363                                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, pos1);
364                                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, pos2);
365
366                                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, pos2);
367                                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, pos1);
368                                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, pos3);
369                         }
370                 }
371
372                 SHC.drw_grid = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
373         }
374         return SHC.drw_grid;
375 }
376
377 /* Sphere */
378 GPUBatch *DRW_cache_sphere_get(void)
379 {
380         if (!SHC.drw_sphere) {
381                 SHC.drw_sphere = gpu_batch_sphere(32, 24);
382         }
383         return SHC.drw_sphere;
384 }
385
386 /** \} */
387
388 /* -------------------------------------------------------------------- */
389
390 /** \name Common
391  * \{ */
392
393 GPUBatch *DRW_cache_cube_get(void)
394 {
395         if (!SHC.drw_cube) {
396                 const GLfloat verts[8][3] = {
397                         {-1.0f, -1.0f, -1.0f},
398                         {-1.0f, -1.0f,  1.0f},
399                         {-1.0f,  1.0f, -1.0f},
400                         {-1.0f,  1.0f,  1.0f},
401                         { 1.0f, -1.0f, -1.0f},
402                         { 1.0f, -1.0f,  1.0f},
403                         { 1.0f,  1.0f, -1.0f},
404                         { 1.0f,  1.0f,  1.0f}
405                 };
406
407                 const uint indices[36] = {
408                         0, 1, 2,
409                         1, 3, 2,
410                         0, 4, 1,
411                         4, 5, 1,
412                         6, 5, 4,
413                         6, 7, 5,
414                         2, 7, 6,
415                         2, 3, 7,
416                         3, 1, 7,
417                         1, 5, 7,
418                         0, 2, 4,
419                         2, 6, 4,
420                 };
421
422                 /* Position Only 3D format */
423                 static GPUVertFormat format = { 0 };
424                 static struct { uint pos; } attr_id;
425                 if (format.attr_len == 0) {
426                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
427                 }
428
429                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
430                 GPU_vertbuf_data_alloc(vbo, 36);
431
432                 for (int i = 0; i < 36; ++i) {
433                         GPU_vertbuf_attr_set(vbo, attr_id.pos, i, verts[indices[i]]);
434                 }
435
436                 SHC.drw_cube = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
437         }
438         return SHC.drw_cube;
439 }
440
441 GPUBatch *DRW_cache_empty_cube_get(void)
442 {
443         if (!SHC.drw_empty_cube) {
444                 const GLfloat verts[8][3] = {
445                         {-1.0f, -1.0f, -1.0f},
446                         {-1.0f, -1.0f,  1.0f},
447                         {-1.0f,  1.0f, -1.0f},
448                         {-1.0f,  1.0f,  1.0f},
449                         { 1.0f, -1.0f, -1.0f},
450                         { 1.0f, -1.0f,  1.0f},
451                         { 1.0f,  1.0f, -1.0f},
452                         { 1.0f,  1.0f,  1.0f}
453                 };
454
455                 const GLubyte indices[24] = {0, 1, 1, 3, 3, 2, 2, 0, 0, 4, 4, 5, 5, 7, 7, 6, 6, 4, 1, 5, 3, 7, 2, 6};
456
457                 /* Position Only 3D format */
458                 static GPUVertFormat format = { 0 };
459                 static struct { uint pos; } attr_id;
460                 if (format.attr_len == 0) {
461                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
462                 }
463
464                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
465                 GPU_vertbuf_data_alloc(vbo, 24);
466
467                 for (int i = 0; i < 24; ++i) {
468                         GPU_vertbuf_attr_set(vbo, attr_id.pos, i, verts[indices[i]]);
469                 }
470
471                 SHC.drw_empty_cube = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
472         }
473         return SHC.drw_empty_cube;
474 }
475
476 GPUBatch *DRW_cache_circle_get(void)
477 {
478 #define CIRCLE_RESOL 64
479         if (!SHC.drw_circle) {
480                 float v[3] = {0.0f, 0.0f, 0.0f};
481
482                 /* Position Only 3D format */
483                 static GPUVertFormat format = { 0 };
484                 static struct { uint pos; } attr_id;
485                 if (format.attr_len == 0) {
486                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
487                 }
488
489                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
490                 GPU_vertbuf_data_alloc(vbo, CIRCLE_RESOL);
491
492                 for (int a = 0; a < CIRCLE_RESOL; a++) {
493                         v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
494                         v[2] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
495                         v[1] = 0.0f;
496                         GPU_vertbuf_attr_set(vbo, attr_id.pos, a, v);
497                 }
498
499                 SHC.drw_circle = GPU_batch_create_ex(GPU_PRIM_LINE_LOOP, vbo, NULL, GPU_BATCH_OWNS_VBO);
500         }
501         return SHC.drw_circle;
502 #undef CIRCLE_RESOL
503 }
504
505 GPUBatch *DRW_cache_square_get(void)
506 {
507         if (!SHC.drw_square) {
508                 float p[4][3] = {{ 1.0f, 0.0f,  1.0f},
509                                  { 1.0f, 0.0f, -1.0f},
510                                  {-1.0f, 0.0f, -1.0f},
511                                  {-1.0f, 0.0f,  1.0f}};
512
513                 /* Position Only 3D format */
514                 static GPUVertFormat format = { 0 };
515                 static struct { uint pos; } attr_id;
516                 if (format.attr_len == 0) {
517                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
518                 }
519
520                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
521                 GPU_vertbuf_data_alloc(vbo, 8);
522
523                 for (int i = 0; i < 4; i++) {
524                         GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 2,     p[i % 4]);
525                         GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 2 + 1, p[(i + 1) % 4]);
526                 }
527
528                 SHC.drw_square = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
529         }
530         return SHC.drw_square;
531 }
532
533 GPUBatch *DRW_cache_single_line_get(void)
534 {
535         /* Z axis line */
536         if (!SHC.drw_line) {
537                 float v1[3] = {0.0f, 0.0f, 0.0f};
538                 float v2[3] = {0.0f, 0.0f, 1.0f};
539
540                 /* Position Only 3D format */
541                 static GPUVertFormat format = { 0 };
542                 static struct { uint pos; } attr_id;
543                 if (format.attr_len == 0) {
544                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
545                 }
546
547                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
548                 GPU_vertbuf_data_alloc(vbo, 2);
549
550                 GPU_vertbuf_attr_set(vbo, attr_id.pos, 0, v1);
551                 GPU_vertbuf_attr_set(vbo, attr_id.pos, 1, v2);
552
553                 SHC.drw_line = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
554         }
555         return SHC.drw_line;
556 }
557
558 GPUBatch *DRW_cache_single_line_endpoints_get(void)
559 {
560         /* Z axis line */
561         if (!SHC.drw_line_endpoints) {
562                 float v1[3] = {0.0f, 0.0f, 0.0f};
563                 float v2[3] = {0.0f, 0.0f, 1.0f};
564
565                 /* Position Only 3D format */
566                 static GPUVertFormat format = { 0 };
567                 static struct { uint pos; } attr_id;
568                 if (format.attr_len == 0) {
569                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
570                 }
571
572                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
573                 GPU_vertbuf_data_alloc(vbo, 2);
574
575                 GPU_vertbuf_attr_set(vbo, attr_id.pos, 0, v1);
576                 GPU_vertbuf_attr_set(vbo, attr_id.pos, 1, v2);
577
578                 SHC.drw_line_endpoints = GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO);
579         }
580         return SHC.drw_line_endpoints;
581 }
582
583 GPUBatch *DRW_cache_screenspace_circle_get(void)
584 {
585 #define CIRCLE_RESOL 32
586         if (!SHC.drw_screenspace_circle) {
587                 float v[3] = {0.0f, 0.0f, 0.0f};
588
589                 /* Position Only 3D format */
590                 static GPUVertFormat format = { 0 };
591                 static struct { uint pos; } attr_id;
592                 if (format.attr_len == 0) {
593                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
594                 }
595
596                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
597                 GPU_vertbuf_data_alloc(vbo, CIRCLE_RESOL + 1);
598
599                 for (int a = 0; a <= CIRCLE_RESOL; a++) {
600                         v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
601                         v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
602                         GPU_vertbuf_attr_set(vbo, attr_id.pos, a, v);
603                 }
604
605                 SHC.drw_screenspace_circle = GPU_batch_create_ex(GPU_PRIM_LINE_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
606         }
607         return SHC.drw_screenspace_circle;
608 #undef CIRCLE_RESOL
609 }
610
611 /* Grease Pencil object */
612 GPUBatch *DRW_cache_gpencil_axes_get(void)
613 {
614         if (!SHC.drw_gpencil_axes) {
615                 int axis;
616                 float v1[3] = { 0.0f, 0.0f, 0.0f };
617                 float v2[3] = { 0.0f, 0.0f, 0.0f };
618
619                 /* cube data */
620                 const GLfloat verts[8][3] = {
621                         { -0.25f, -0.25f, -0.25f },
622                         { -0.25f, -0.25f,  0.25f },
623                         { -0.25f,  0.25f, -0.25f },
624                         { -0.25f,  0.25f,  0.25f },
625                         { 0.25f, -0.25f, -0.25f },
626                         { 0.25f, -0.25f,  0.25f },
627                         { 0.25f,  0.25f, -0.25f },
628                         { 0.25f,  0.25f,  0.25f }
629                 };
630
631                 const GLubyte indices[24] = { 0, 1, 1, 3, 3, 2, 2, 0, 0, 4, 4, 5, 5, 7, 7, 6, 6, 4, 1, 5, 3, 7, 2, 6 };
632
633                 /* Position Only 3D format */
634                 static GPUVertFormat format = { 0 };
635                 static uint pos_id;
636                 if (format.attr_len == 0) {
637                         pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
638                 }
639
640                 GPUVertBuf *vbo =  GPU_vertbuf_create_with_format(&format);
641
642                 /* alloc 30 elements for cube and 3 axis */
643                 GPU_vertbuf_data_alloc(vbo, ARRAY_SIZE(indices) + 6);
644
645                 /* draw axis */
646                 for (axis = 0; axis < 3; axis++) {
647                         v1[axis] = 1.0f;
648                         v2[axis] = -1.0f;
649
650                         GPU_vertbuf_attr_set(vbo, pos_id, axis * 2, v1);
651                         GPU_vertbuf_attr_set(vbo, pos_id, axis * 2 + 1, v2);
652
653                         /* reset v1 & v2 to zero for next axis */
654                         v1[axis] = v2[axis] = 0.0f;
655                 }
656
657                 /* draw cube */
658                 for (int i = 0; i < 24; ++i) {
659                         GPU_vertbuf_attr_set(vbo, pos_id, i + 6, verts[indices[i]]);
660                 }
661
662                 SHC.drw_gpencil_axes = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
663         }
664         return SHC.drw_gpencil_axes;
665 }
666
667
668 /* -------------------------------------------------------------------- */
669
670 /** \name Common Object API
671 * \{ */
672
673 GPUBatch *DRW_cache_object_all_edges_get(Object *ob)
674 {
675         switch (ob->type) {
676                 case OB_MESH:
677                         return DRW_cache_mesh_all_edges_get(ob);
678
679                 /* TODO, should match 'DRW_cache_object_surface_get' */
680                 default:
681                         return NULL;
682         }
683 }
684
685 GPUBatch *DRW_cache_object_edge_detection_get(Object *ob, bool *r_is_manifold)
686 {
687         switch (ob->type) {
688                 case OB_MESH:
689                         return DRW_cache_mesh_edge_detection_get(ob, r_is_manifold);
690
691                 /* TODO, should match 'DRW_cache_object_surface_get' */
692                 default:
693                         return NULL;
694         }
695 }
696
697 GPUBatch *DRW_cache_object_face_wireframe_get(Object *ob)
698 {
699         switch (ob->type) {
700                 case OB_MESH:
701                         return DRW_cache_mesh_face_wireframe_get(ob);
702                 case OB_CURVE:
703                         return DRW_cache_curve_face_wireframe_get(ob);
704                 case OB_SURF:
705                         return DRW_cache_surf_face_wireframe_get(ob);
706                 case OB_FONT:
707                         return DRW_cache_text_face_wireframe_get(ob);
708                 case OB_MBALL:
709                         return DRW_cache_mball_face_wireframe_get(ob);
710                 default:
711                         return NULL;
712         }
713 }
714
715 GPUBatch *DRW_cache_object_loose_edges_get(struct Object *ob)
716 {
717         switch (ob->type) {
718                 case OB_MESH:
719                         return DRW_cache_mesh_loose_edges_get(ob);
720                 case OB_CURVE:
721                         return DRW_cache_curve_loose_edges_get(ob);
722                 case OB_SURF:
723                         return DRW_cache_surf_loose_edges_get(ob);
724                 case OB_FONT:
725                         return DRW_cache_text_loose_edges_get(ob);
726                 case OB_MBALL:
727                         /* Cannot have any loose edge */
728                 default:
729                         return NULL;
730         }
731 }
732
733 GPUBatch *DRW_cache_object_surface_get(Object *ob)
734 {
735         switch (ob->type) {
736                 case OB_MESH:
737                         return DRW_cache_mesh_surface_get(ob);
738                 case OB_CURVE:
739                         return DRW_cache_curve_surface_get(ob);
740                 case OB_SURF:
741                         return DRW_cache_surf_surface_get(ob);
742                 case OB_FONT:
743                         return DRW_cache_text_surface_get(ob);
744                 case OB_MBALL:
745                         return DRW_cache_mball_surface_get(ob);
746                 default:
747                         return NULL;
748         }
749 }
750
751 GPUBatch **DRW_cache_object_surface_material_get(
752         struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len,
753         char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count)
754 {
755         if (auto_layer_names != NULL) {
756                 *auto_layer_names = NULL;
757                 *auto_layer_is_srgb = NULL;
758                 *auto_layer_count = 0;
759         }
760
761         switch (ob->type) {
762                 case OB_MESH:
763                         return DRW_cache_mesh_surface_shaded_get(ob, gpumat_array, gpumat_array_len,
764                                                                  auto_layer_names, auto_layer_is_srgb, auto_layer_count);
765                 case OB_CURVE:
766                         return DRW_cache_curve_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
767                 case OB_SURF:
768                         return DRW_cache_surf_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
769                 case OB_FONT:
770                         return DRW_cache_text_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
771                 case OB_MBALL:
772                         return DRW_cache_mball_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
773                 default:
774                         return NULL;
775         }
776 }
777
778 /** \} */
779
780
781 /* -------------------------------------------------------------------- */
782
783 /** \name Empties
784  * \{ */
785
786 GPUBatch *DRW_cache_plain_axes_get(void)
787 {
788         if (!SHC.drw_plain_axes) {
789                 int axis;
790                 float v1[3] = {0.0f, 0.0f, 0.0f};
791                 float v2[3] = {0.0f, 0.0f, 0.0f};
792
793                 /* Position Only 3D format */
794                 static GPUVertFormat format = { 0 };
795                 static struct { uint pos; } attr_id;
796                 if (format.attr_len == 0) {
797                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
798                 }
799
800                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
801                 GPU_vertbuf_data_alloc(vbo, 6);
802
803                 for (axis = 0; axis < 3; axis++) {
804                         v1[axis] = 1.0f;
805                         v2[axis] = -1.0f;
806
807                         GPU_vertbuf_attr_set(vbo, attr_id.pos, axis * 2, v1);
808                         GPU_vertbuf_attr_set(vbo, attr_id.pos, axis * 2 + 1, v2);
809
810                         /* reset v1 & v2 to zero for next axis */
811                         v1[axis] = v2[axis] = 0.0f;
812                 }
813
814                 SHC.drw_plain_axes = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
815         }
816         return SHC.drw_plain_axes;
817 }
818
819 GPUBatch *DRW_cache_single_arrow_get(void)
820 {
821         if (!SHC.drw_single_arrow) {
822                 float v1[3] = {0.0f, 0.0f, 1.0f}, v2[3], v3[3];
823
824                 /* Position Only 3D format */
825                 static GPUVertFormat format = { 0 };
826                 static struct { uint pos; } attr_id;
827                 if (format.attr_len == 0) {
828                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
829                 }
830
831                 /* Square Pyramid */
832                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
833                 GPU_vertbuf_data_alloc(vbo, 12);
834
835                 v2[0] = 0.035f; v2[1] = 0.035f;
836                 v3[0] = -0.035f; v3[1] = 0.035f;
837                 v2[2] = v3[2] = 0.75f;
838
839                 for (int sides = 0; sides < 4; sides++) {
840                         if (sides % 2 == 1) {
841                                 v2[0] = -v2[0];
842                                 v3[1] = -v3[1];
843                         }
844                         else {
845                                 v2[1] = -v2[1];
846                                 v3[0] = -v3[0];
847                         }
848
849                         GPU_vertbuf_attr_set(vbo, attr_id.pos, sides * 3 + 0, v1);
850                         GPU_vertbuf_attr_set(vbo, attr_id.pos, sides * 3 + 1, v2);
851                         GPU_vertbuf_attr_set(vbo, attr_id.pos, sides * 3 + 2, v3);
852                 }
853
854                 SHC.drw_single_arrow = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
855         }
856         return SHC.drw_single_arrow;
857 }
858
859 GPUBatch *DRW_cache_empty_sphere_get(void)
860 {
861         if (!SHC.drw_empty_sphere) {
862                 GPUVertBuf *vbo = sphere_wire_vbo(1.0f);
863                 SHC.drw_empty_sphere = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
864         }
865         return SHC.drw_empty_sphere;
866 }
867
868 GPUBatch *DRW_cache_empty_cone_get(void)
869 {
870 #define NSEGMENTS 8
871         if (!SHC.drw_empty_cone) {
872                 /* a single ring of vertices */
873                 float p[NSEGMENTS][2];
874                 for (int i = 0; i < NSEGMENTS; ++i) {
875                         float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS);
876                         p[i][0] = cosf(angle);
877                         p[i][1] = sinf(angle);
878                 }
879
880                 /* Position Only 3D format */
881                 static GPUVertFormat format = { 0 };
882                 static struct { uint pos; } attr_id;
883                 if (format.attr_len == 0) {
884                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
885                 }
886
887                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
888                 GPU_vertbuf_data_alloc(vbo, NSEGMENTS * 4);
889
890                 for (int i = 0; i < NSEGMENTS; ++i) {
891                         float cv[2], v[3];
892                         cv[0] = p[(i) % NSEGMENTS][0];
893                         cv[1] = p[(i) % NSEGMENTS][1];
894
895                         /* cone sides */
896                         ARRAY_SET_ITEMS(v, cv[0], 0.0f, cv[1]);
897                         GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 4, v);
898                         ARRAY_SET_ITEMS(v, 0.0f, 2.0f, 0.0f);
899                         GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 1, v);
900
901                         /* end ring */
902                         ARRAY_SET_ITEMS(v, cv[0], 0.0f, cv[1]);
903                         GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 2, v);
904                         cv[0] = p[(i + 1) % NSEGMENTS][0];
905                         cv[1] = p[(i + 1) % NSEGMENTS][1];
906                         ARRAY_SET_ITEMS(v, cv[0], 0.0f, cv[1]);
907                         GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 3, v);
908                 }
909
910                 SHC.drw_empty_cone = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
911         }
912         return SHC.drw_empty_cone;
913 #undef NSEGMENTS
914 }
915
916 GPUBatch *DRW_cache_empty_cylinder_get(void)
917 {
918 #define NSEGMENTS 12
919         if (!SHC.drw_empty_cylinder) {
920                 /* a single ring of vertices */
921                 float p[NSEGMENTS][2];
922                 for (int i = 0; i < NSEGMENTS; ++i) {
923                         float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS);
924                         p[i][0] = cosf(angle);
925                         p[i][1] = sinf(angle);
926                 }
927
928                 /* Position Only 3D format */
929                 static GPUVertFormat format = { 0 };
930                 static struct { uint pos; } attr_id;
931                 if (format.attr_len == 0) {
932                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
933                 }
934
935                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
936                 GPU_vertbuf_data_alloc(vbo, NSEGMENTS * 6);
937
938                 for (int i = 0; i < NSEGMENTS; ++i) {
939                         float cv[2], pv[2], v[3];
940                         cv[0] = p[(i) % NSEGMENTS][0];
941                         cv[1] = p[(i) % NSEGMENTS][1];
942                         pv[0] = p[(i + 1) % NSEGMENTS][0];
943                         pv[1] = p[(i + 1) % NSEGMENTS][1];
944
945                         /* cylinder sides */
946                         copy_v3_fl3(v, cv[0], cv[1], -1.0f);
947                         GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 6, v);
948                         copy_v3_fl3(v, cv[0], cv[1],  1.0f);
949                         GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 6 + 1, v);
950
951                         /* top ring */
952                         copy_v3_fl3(v, cv[0], cv[1],  1.0f);
953                         GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 6 + 2, v);
954                         copy_v3_fl3(v, pv[0], pv[1],  1.0f);
955                         GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 6 + 3, v);
956
957                         /* bottom ring */
958                         copy_v3_fl3(v, cv[0], cv[1], -1.0f);
959                         GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 6 + 4, v);
960                         copy_v3_fl3(v, pv[0], pv[1], -1.0f);
961                         GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 6 + 5, v);
962                 }
963
964                 SHC.drw_empty_cylinder = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
965         }
966         return SHC.drw_empty_cylinder;
967 #undef NSEGMENTS
968 }
969
970 GPUBatch *DRW_cache_empty_capsule_body_get(void)
971 {
972         if (!SHC.drw_empty_capsule_body) {
973                 const float pos[8][3] = {
974                         { 1.0f,  0.0f, 1.0f},
975                         { 1.0f,  0.0f, 0.0f},
976                         { 0.0f,  1.0f, 1.0f},
977                         { 0.0f,  1.0f, 0.0f},
978                         {-1.0f,  0.0f, 1.0f},
979                         {-1.0f,  0.0f, 0.0f},
980                         { 0.0f, -1.0f, 1.0f},
981                         { 0.0f, -1.0f, 0.0f}
982                 };
983
984                 /* Position Only 3D format */
985                 static GPUVertFormat format = { 0 };
986                 static struct { uint pos; } attr_id;
987                 if (format.attr_len == 0) {
988                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
989                 }
990
991                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
992                 GPU_vertbuf_data_alloc(vbo, 8);
993                 GPU_vertbuf_attr_fill(vbo, attr_id.pos, pos);
994
995                 SHC.drw_empty_capsule_body = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
996         }
997         return SHC.drw_empty_capsule_body;
998 }
999
1000 GPUBatch *DRW_cache_empty_capsule_cap_get(void)
1001 {
1002 #define NSEGMENTS 24 /* Must be multiple of 2. */
1003         if (!SHC.drw_empty_capsule_cap) {
1004                 /* a single ring of vertices */
1005                 float p[NSEGMENTS][2];
1006                 for (int i = 0; i < NSEGMENTS; ++i) {
1007                         float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS);
1008                         p[i][0] = cosf(angle);
1009                         p[i][1] = sinf(angle);
1010                 }
1011
1012                 /* Position Only 3D format */
1013                 static GPUVertFormat format = { 0 };
1014                 static struct { uint pos; } attr_id;
1015                 if (format.attr_len == 0) {
1016                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
1017                 }
1018
1019                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
1020                 GPU_vertbuf_data_alloc(vbo, (NSEGMENTS * 2) * 2);
1021
1022                 /* Base circle */
1023                 int vidx = 0;
1024                 for (int i = 0; i < NSEGMENTS; ++i) {
1025                         float v[3] = {0.0f, 0.0f, 0.0f};
1026                         copy_v2_v2(v, p[(i) % NSEGMENTS]);
1027                         GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
1028                         copy_v2_v2(v, p[(i + 1) % NSEGMENTS]);
1029                         GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
1030                 }
1031
1032                 for (int i = 0; i < NSEGMENTS / 2; ++i) {
1033                         float v[3] = {0.0f, 0.0f, 0.0f};
1034                         int ci = i % NSEGMENTS;
1035                         int pi = (i + 1) % NSEGMENTS;
1036                         /* Y half circle */
1037                         copy_v3_fl3(v, p[ci][0], 0.0f, p[ci][1]);
1038                         GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
1039                         copy_v3_fl3(v, p[pi][0], 0.0f, p[pi][1]);
1040                         GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
1041                         /* X half circle */
1042                         copy_v3_fl3(v, 0.0f, p[ci][0], p[ci][1]);
1043                         GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
1044                         copy_v3_fl3(v, 0.0f, p[pi][0], p[pi][1]);
1045                         GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
1046                 }
1047
1048                 SHC.drw_empty_capsule_cap = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
1049         }
1050         return SHC.drw_empty_capsule_cap;
1051 #undef NSEGMENTS
1052 }
1053
1054 GPUBatch *DRW_cache_image_plane_get(void)
1055 {
1056         if (!SHC.drw_image_plane) {
1057                 const float quad[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
1058                 static GPUVertFormat format = { 0 };
1059                 static struct { uint pos, texCoords; } attr_id;
1060                 if (format.attr_len == 0) {
1061                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
1062                         attr_id.texCoords = GPU_vertformat_attr_add(&format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
1063                 }
1064                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
1065                 GPU_vertbuf_data_alloc(vbo, 4);
1066                 for (uint j = 0; j < 4; j++) {
1067                         GPU_vertbuf_attr_set(vbo, attr_id.pos, j, quad[j]);
1068                         GPU_vertbuf_attr_set(vbo, attr_id.texCoords, j, quad[j]);
1069                 }
1070                 SHC.drw_image_plane = GPU_batch_create_ex(GPU_PRIM_TRI_FAN, vbo, NULL, GPU_BATCH_OWNS_VBO);
1071         }
1072         return SHC.drw_image_plane;
1073 }
1074
1075 GPUBatch *DRW_cache_image_plane_wire_get(void)
1076 {
1077         if (!SHC.drw_image_plane_wire) {
1078                 const float quad[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
1079                 static GPUVertFormat format = { 0 };
1080                 static struct { uint pos; } attr_id;
1081                 if (format.attr_len == 0) {
1082                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
1083                 }
1084                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
1085                 GPU_vertbuf_data_alloc(vbo, 4);
1086                 for (uint j = 0; j < 4; j++) {
1087                         GPU_vertbuf_attr_set(vbo, attr_id.pos, j, quad[j]);
1088                 }
1089                 SHC.drw_image_plane_wire = GPU_batch_create_ex(GPU_PRIM_LINE_LOOP, vbo, NULL, GPU_BATCH_OWNS_VBO);
1090         }
1091         return SHC.drw_image_plane_wire;
1092 }
1093
1094 /* Force Field */
1095 GPUBatch *DRW_cache_field_wind_get(void)
1096 {
1097 #define CIRCLE_RESOL 32
1098         if (!SHC.drw_field_wind) {
1099                 float v[3] = {0.0f, 0.0f, 0.0f};
1100
1101                 /* Position Only 3D format */
1102                 static GPUVertFormat format = { 0 };
1103                 static struct { uint pos; } attr_id;
1104                 if (format.attr_len == 0) {
1105                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
1106                 }
1107
1108                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
1109                 GPU_vertbuf_data_alloc(vbo, CIRCLE_RESOL * 2 * 4);
1110
1111                 for (int i = 0; i < 4; i++) {
1112                         float z = 0.05f * (float)i;
1113                         for (int a = 0; a < CIRCLE_RESOL; a++) {
1114                                 v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
1115                                 v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
1116                                 v[2] = z;
1117                                 GPU_vertbuf_attr_set(vbo, attr_id.pos, i * CIRCLE_RESOL * 2 + a * 2, v);
1118
1119                                 v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
1120                                 v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
1121                                 v[2] = z;
1122                                 GPU_vertbuf_attr_set(vbo, attr_id.pos, i * CIRCLE_RESOL * 2 + a * 2 + 1, v);
1123                         }
1124                 }
1125
1126                 SHC.drw_field_wind = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
1127         }
1128         return SHC.drw_field_wind;
1129 #undef CIRCLE_RESOL
1130 }
1131
1132 GPUBatch *DRW_cache_field_force_get(void)
1133 {
1134 #define CIRCLE_RESOL 32
1135         if (!SHC.drw_field_force) {
1136                 float v[3] = {0.0f, 0.0f, 0.0f};
1137
1138                 /* Position Only 3D format */
1139                 static GPUVertFormat format = { 0 };
1140                 static struct { uint pos; } attr_id;
1141                 if (format.attr_len == 0) {
1142                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
1143                 }
1144
1145                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
1146                 GPU_vertbuf_data_alloc(vbo, CIRCLE_RESOL * 2 * 3);
1147
1148                 for (int i = 0; i < 3; i++) {
1149                         float radius = 1.0f + 0.5f * (float)i;
1150                         for (int a = 0; a < CIRCLE_RESOL; a++) {
1151                                 v[0] = radius * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
1152                                 v[1] = radius * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
1153                                 v[2] = 0.0f;
1154                                 GPU_vertbuf_attr_set(vbo, attr_id.pos, i * CIRCLE_RESOL * 2 + a * 2, v);
1155
1156                                 v[0] = radius * sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
1157                                 v[1] = radius * cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
1158                                 v[2] = 0.0f;
1159                                 GPU_vertbuf_attr_set(vbo, attr_id.pos, i * CIRCLE_RESOL * 2 + a * 2 + 1, v);
1160                         }
1161                 }
1162
1163                 SHC.drw_field_force = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
1164         }
1165         return SHC.drw_field_force;
1166 #undef CIRCLE_RESOL
1167 }
1168
1169 GPUBatch *DRW_cache_field_vortex_get(void)
1170 {
1171 #define SPIRAL_RESOL 32
1172         if (!SHC.drw_field_vortex) {
1173                 float v[3] = {0.0f, 0.0f, 0.0f};
1174                 uint v_idx = 0;
1175
1176                 /* Position Only 3D format */
1177                 static GPUVertFormat format = { 0 };
1178                 static struct { uint pos; } attr_id;
1179                 if (format.attr_len == 0) {
1180                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
1181                 }
1182
1183                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
1184                 GPU_vertbuf_data_alloc(vbo, SPIRAL_RESOL * 2 + 1);
1185
1186                 for (int a = SPIRAL_RESOL; a > -1; a--) {
1187                         v[0] = sinf((2.0f * M_PI * a) / ((float)SPIRAL_RESOL)) * (a / (float)SPIRAL_RESOL);
1188                         v[1] = cosf((2.0f * M_PI * a) / ((float)SPIRAL_RESOL)) * (a / (float)SPIRAL_RESOL);
1189
1190                         GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
1191                 }
1192
1193                 for (int a = 1; a <= SPIRAL_RESOL; a++) {
1194                         v[0] = -sinf((2.0f * M_PI * a) / ((float)SPIRAL_RESOL)) * (a / (float)SPIRAL_RESOL);
1195                         v[1] = -cosf((2.0f * M_PI * a) / ((float)SPIRAL_RESOL)) * (a / (float)SPIRAL_RESOL);
1196
1197                         GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
1198                 }
1199
1200                 SHC.drw_field_vortex = GPU_batch_create_ex(GPU_PRIM_LINE_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
1201         }
1202         return SHC.drw_field_vortex;
1203 #undef SPIRAL_RESOL
1204 }
1205
1206 GPUBatch *DRW_cache_field_tube_limit_get(void)
1207 {
1208 #define CIRCLE_RESOL 32
1209         if (!SHC.drw_field_tube_limit) {
1210                 float v[3] = {0.0f, 0.0f, 0.0f};
1211                 uint v_idx = 0;
1212
1213                 /* Position Only 3D format */
1214                 static GPUVertFormat format = { 0 };
1215                 static struct { uint pos; } attr_id;
1216                 if (format.attr_len == 0) {
1217                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
1218                 }
1219
1220                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
1221                 GPU_vertbuf_data_alloc(vbo, CIRCLE_RESOL * 2 * 2 + 8);
1222
1223                 /* Caps */
1224                 for (int i = 0; i < 2; i++) {
1225                         float z = (float)i * 2.0f - 1.0f;
1226                         for (int a = 0; a < CIRCLE_RESOL; a++) {
1227                                 v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
1228                                 v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
1229                                 v[2] = z;
1230                                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
1231
1232                                 v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
1233                                 v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
1234                                 v[2] = z;
1235                                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
1236                         }
1237                 }
1238                 /* Side Edges */
1239                 for (int a = 0; a < 4; a++) {
1240                         for (int i = 0; i < 2; i++) {
1241                                 float z = (float)i * 2.0f - 1.0f;
1242                                 v[0] = sinf((2.0f * M_PI * a) / 4.0f);
1243                                 v[1] = cosf((2.0f * M_PI * a) / 4.0f);
1244                                 v[2] = z;
1245                                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
1246                         }
1247                 }
1248
1249                 SHC.drw_field_tube_limit = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
1250         }
1251         return SHC.drw_field_tube_limit;
1252 #undef CIRCLE_RESOL
1253 }
1254
1255 GPUBatch *DRW_cache_field_cone_limit_get(void)
1256 {
1257 #define CIRCLE_RESOL 32
1258         if (!SHC.drw_field_cone_limit) {
1259                 float v[3] = {0.0f, 0.0f, 0.0f};
1260                 uint v_idx = 0;
1261
1262                 /* Position Only 3D format */
1263                 static GPUVertFormat format = { 0 };
1264                 static struct { uint pos; } attr_id;
1265                 if (format.attr_len == 0) {
1266                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
1267                 }
1268
1269                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
1270                 GPU_vertbuf_data_alloc(vbo, CIRCLE_RESOL * 2 * 2 + 8);
1271
1272                 /* Caps */
1273                 for (int i = 0; i < 2; i++) {
1274                         float z = (float)i * 2.0f - 1.0f;
1275                         for (int a = 0; a < CIRCLE_RESOL; a++) {
1276                                 v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
1277                                 v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
1278                                 v[2] = z;
1279                                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
1280
1281                                 v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
1282                                 v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
1283                                 v[2] = z;
1284                                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
1285                         }
1286                 }
1287                 /* Side Edges */
1288                 for (int a = 0; a < 4; a++) {
1289                         for (int i = 0; i < 2; i++) {
1290                                 float z = (float)i * 2.0f - 1.0f;
1291                                 v[0] = z * sinf((2.0f * M_PI * a) / 4.0f);
1292                                 v[1] = z * cosf((2.0f * M_PI * a) / 4.0f);
1293                                 v[2] = z;
1294                                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
1295                         }
1296                 }
1297
1298                 SHC.drw_field_cone_limit = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
1299         }
1300         return SHC.drw_field_cone_limit;
1301 #undef CIRCLE_RESOL
1302 }
1303
1304 /** \} */
1305
1306 /* -------------------------------------------------------------------- */
1307
1308 /** \name Lamps
1309  * \{ */
1310
1311 GPUBatch *DRW_cache_lamp_get(void)
1312 {
1313 #define NSEGMENTS 8
1314         if (!SHC.drw_lamp) {
1315                 float v[2];
1316
1317                 /* Position Only 3D format */
1318                 static GPUVertFormat format = { 0 };
1319                 static struct { uint pos; } attr_id;
1320                 if (format.attr_len == 0) {
1321                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
1322                 }
1323
1324                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
1325                 GPU_vertbuf_data_alloc(vbo, NSEGMENTS * 2);
1326
1327                 for (int a = 0; a < NSEGMENTS * 2; a += 2) {
1328                         v[0] = sinf((2.0f * M_PI * a) / ((float)NSEGMENTS * 2));
1329                         v[1] = cosf((2.0f * M_PI * a) / ((float)NSEGMENTS * 2));
1330                         GPU_vertbuf_attr_set(vbo, attr_id.pos, a, v);
1331
1332                         v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS * 2));
1333                         v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS * 2));
1334                         GPU_vertbuf_attr_set(vbo, attr_id.pos, a + 1, v);
1335                 }
1336
1337                 SHC.drw_lamp = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
1338         }
1339         return SHC.drw_lamp;
1340 #undef NSEGMENTS
1341 }
1342
1343 GPUBatch *DRW_cache_lamp_shadows_get(void)
1344 {
1345 #define NSEGMENTS 10
1346         if (!SHC.drw_lamp_shadows) {
1347                 float v[2];
1348
1349                 /* Position Only 3D format */
1350                 static GPUVertFormat format = { 0 };
1351                 static struct { uint pos; } attr_id;
1352                 if (format.attr_len == 0) {
1353                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
1354                 }
1355
1356                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
1357                 GPU_vertbuf_data_alloc(vbo, NSEGMENTS * 2);
1358
1359                 for (int a = 0; a < NSEGMENTS * 2; a += 2) {
1360                         v[0] = sinf((2.0f * M_PI * a) / ((float)NSEGMENTS * 2));
1361                         v[1] = cosf((2.0f * M_PI * a) / ((float)NSEGMENTS * 2));
1362                         GPU_vertbuf_attr_set(vbo, attr_id.pos, a, v);
1363
1364                         v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS * 2));
1365                         v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS * 2));
1366                         GPU_vertbuf_attr_set(vbo, attr_id.pos, a + 1, v);
1367                 }
1368
1369                 SHC.drw_lamp_shadows = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
1370         }
1371         return SHC.drw_lamp_shadows;
1372 #undef NSEGMENTS
1373 }
1374
1375 GPUBatch *DRW_cache_lamp_sunrays_get(void)
1376 {
1377         if (!SHC.drw_lamp_sunrays) {
1378                 float v[2], v1[2], v2[2];
1379
1380                 /* Position Only 2D format */
1381                 static GPUVertFormat format = { 0 };
1382                 static struct { uint pos; } attr_id;
1383                 if (format.attr_len == 0) {
1384                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
1385                 }
1386
1387                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
1388                 GPU_vertbuf_data_alloc(vbo, 32);
1389
1390                 for (int a = 0; a < 8; a++) {
1391                         v[0] = sinf((2.0f * M_PI * a) / 8.0f);
1392                         v[1] = cosf((2.0f * M_PI * a) / 8.0f);
1393
1394                         mul_v2_v2fl(v1, v, 1.6f);
1395                         mul_v2_v2fl(v2, v, 1.9f);
1396                         GPU_vertbuf_attr_set(vbo, attr_id.pos, a * 4, v1);
1397                         GPU_vertbuf_attr_set(vbo, attr_id.pos, a * 4 + 1, v2);
1398
1399                         mul_v2_v2fl(v1, v, 2.2f);
1400                         mul_v2_v2fl(v2, v, 2.5f);
1401                         GPU_vertbuf_attr_set(vbo, attr_id.pos, a * 4 + 2, v1);
1402                         GPU_vertbuf_attr_set(vbo, attr_id.pos, a * 4 + 3, v2);
1403                 }
1404
1405                 SHC.drw_lamp_sunrays = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
1406         }
1407         return SHC.drw_lamp_sunrays;
1408 }
1409
1410 GPUBatch *DRW_cache_lamp_area_square_get(void)
1411 {
1412         if (!SHC.drw_lamp_area_square) {
1413                 float v1[3] = {0.0f, 0.0f, 0.0f};
1414
1415                 /* Position Only 3D format */
1416                 static GPUVertFormat format = { 0 };
1417                 static struct { uint pos; } attr_id;
1418                 if (format.attr_len == 0) {
1419                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
1420                 }
1421
1422                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
1423                 GPU_vertbuf_data_alloc(vbo, 8);
1424
1425                 v1[0] = v1[1] = 0.5f;
1426                 GPU_vertbuf_attr_set(vbo, attr_id.pos, 0, v1);
1427                 v1[0] = -0.5f;
1428                 GPU_vertbuf_attr_set(vbo, attr_id.pos, 1, v1);
1429                 GPU_vertbuf_attr_set(vbo, attr_id.pos, 2, v1);
1430                 v1[1] = -0.5f;
1431                 GPU_vertbuf_attr_set(vbo, attr_id.pos, 3, v1);
1432                 GPU_vertbuf_attr_set(vbo, attr_id.pos, 4, v1);
1433                 v1[0] = 0.5f;
1434                 GPU_vertbuf_attr_set(vbo, attr_id.pos, 5, v1);
1435                 GPU_vertbuf_attr_set(vbo, attr_id.pos, 6, v1);
1436                 v1[1] = 0.5f;
1437                 GPU_vertbuf_attr_set(vbo, attr_id.pos, 7, v1);
1438
1439                 SHC.drw_lamp_area_square = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
1440         }
1441         return SHC.drw_lamp_area_square;
1442 }
1443
1444 GPUBatch *DRW_cache_lamp_area_disk_get(void)
1445 {
1446 #define NSEGMENTS 32
1447         if (!SHC.drw_lamp_area_disk) {
1448                 /* Position Only 3D format */
1449                 static GPUVertFormat format = { 0 };
1450                 static struct { uint pos; } attr_id;
1451                 if (format.attr_len == 0) {
1452                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
1453                 }
1454
1455                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
1456                 GPU_vertbuf_data_alloc(vbo, 2 * NSEGMENTS);
1457
1458                 float v[3] = {0.0f, 0.5f, 0.0f};
1459                 GPU_vertbuf_attr_set(vbo, attr_id.pos, 0, v);
1460                 for (int a = 1; a < NSEGMENTS; a++) {
1461                         v[0] = 0.5f * sinf(2.0f * (float)M_PI * a / NSEGMENTS);
1462                         v[1] = 0.5f * cosf(2.0f * (float)M_PI * a / NSEGMENTS);
1463                         GPU_vertbuf_attr_set(vbo, attr_id.pos, 2 * a - 1, v);
1464                         GPU_vertbuf_attr_set(vbo, attr_id.pos, 2 * a, v);
1465                 }
1466                 copy_v3_fl3(v, 0.0f, 0.5f, 0.0f);
1467                 GPU_vertbuf_attr_set(vbo, attr_id.pos, (2 * NSEGMENTS) - 1, v);
1468
1469                 SHC.drw_lamp_area_disk = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
1470         }
1471         return SHC.drw_lamp_area_disk;
1472 #undef NSEGMENTS
1473 }
1474
1475 GPUBatch *DRW_cache_lamp_hemi_get(void)
1476 {
1477 #define CIRCLE_RESOL 32
1478         if (!SHC.drw_lamp_hemi) {
1479                 float v[3];
1480                 int vidx = 0;
1481
1482                 /* Position Only 3D format */
1483                 static GPUVertFormat format = { 0 };
1484                 static struct { uint pos; } attr_id;
1485                 if (format.attr_len == 0) {
1486                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
1487                 }
1488
1489                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
1490                 GPU_vertbuf_data_alloc(vbo, CIRCLE_RESOL * 2 * 2 - 6 * 2 * 2);
1491
1492                 /* XZ plane */
1493                 for (int a = 3; a < CIRCLE_RESOL / 2 - 3; a++) {
1494                         v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL) - M_PI / 2);
1495                         v[2] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL) - M_PI / 2) - 1.0f;
1496                         v[1] = 0.0f;
1497                         GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
1498
1499                         v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL) - M_PI / 2);
1500                         v[2] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL) - M_PI / 2) - 1.0f;
1501                         v[1] = 0.0f;
1502                         GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
1503                 }
1504
1505                 /* XY plane */
1506                 for (int a = 3; a < CIRCLE_RESOL / 2 - 3; a++) {
1507                         v[2] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)) - 1.0f;
1508                         v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
1509                         v[0] = 0.0f;
1510                         GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
1511
1512                         v[2] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL)) - 1.0f;
1513                         v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
1514                         v[0] = 0.0f;
1515                         GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
1516                 }
1517
1518                 /* YZ plane full circle */
1519                 /* lease v[2] as it is */
1520                 const float rad = cosf((2.0f * M_PI * 3) / ((float)CIRCLE_RESOL));
1521                 for (int a = 0; a < CIRCLE_RESOL; a++) {
1522                         v[1] = rad * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
1523                         v[0] = rad * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
1524                         GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
1525
1526                         v[1] = rad * sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
1527                         v[0] = rad * cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
1528                         GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
1529                 }
1530
1531
1532                 SHC.drw_lamp_hemi = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
1533         }
1534         return SHC.drw_lamp_hemi;
1535 #undef CIRCLE_RESOL
1536 }
1537
1538
1539 GPUBatch *DRW_cache_lamp_spot_get(void)
1540 {
1541 #define NSEGMENTS 32
1542         if (!SHC.drw_lamp_spot) {
1543                 /* a single ring of vertices */
1544                 float p[NSEGMENTS][2];
1545                 float n[NSEGMENTS][3];
1546                 float neg[NSEGMENTS][3];
1547                 float half_angle = 2 * M_PI / ((float)NSEGMENTS * 2);
1548                 for (int i = 0; i < NSEGMENTS; ++i) {
1549                         float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS);
1550                         p[i][0] = cosf(angle);
1551                         p[i][1] = sinf(angle);
1552
1553                         n[i][0] = cosf(angle - half_angle);
1554                         n[i][1] = sinf(angle - half_angle);
1555                         n[i][2] = cosf(M_PI / 16.0f); /* slope of the cone */
1556                         normalize_v3(n[i]); /* necessary ? */
1557                         negate_v3_v3(neg[i], n[i]);
1558                 }
1559
1560                 static GPUVertFormat format = { 0 };
1561                 static struct { uint pos, n1, n2; } attr_id;
1562                 if (format.attr_len == 0) {
1563                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
1564                         attr_id.n1 = GPU_vertformat_attr_add(&format, "N1", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
1565                         attr_id.n2 = GPU_vertformat_attr_add(&format, "N2", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
1566                 }
1567
1568                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
1569                 GPU_vertbuf_data_alloc(vbo, NSEGMENTS * 4);
1570
1571                 for (int i = 0; i < NSEGMENTS; ++i) {
1572                         float cv[2], v[3];
1573                         cv[0] = p[i % NSEGMENTS][0];
1574                         cv[1] = p[i % NSEGMENTS][1];
1575
1576                         /* cone sides */
1577                         ARRAY_SET_ITEMS(v, cv[0], cv[1], -1.0f);
1578                         GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 4, v);
1579                         ARRAY_SET_ITEMS(v, 0.0f, 0.0f, 0.0f);
1580                         GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 1, v);
1581
1582                         GPU_vertbuf_attr_set(vbo, attr_id.n1, i * 4,     n[(i) % NSEGMENTS]);
1583                         GPU_vertbuf_attr_set(vbo, attr_id.n1, i * 4 + 1, n[(i) % NSEGMENTS]);
1584                         GPU_vertbuf_attr_set(vbo, attr_id.n2, i * 4,     n[(i + 1) % NSEGMENTS]);
1585                         GPU_vertbuf_attr_set(vbo, attr_id.n2, i * 4 + 1, n[(i + 1) % NSEGMENTS]);
1586
1587                         /* end ring */
1588                         ARRAY_SET_ITEMS(v, cv[0], cv[1], -1.0f);
1589                         GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 2, v);
1590                         cv[0] = p[(i + 1) % NSEGMENTS][0];
1591                         cv[1] = p[(i + 1) % NSEGMENTS][1];
1592                         ARRAY_SET_ITEMS(v, cv[0], cv[1], -1.0f);
1593                         GPU_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 3, v);
1594
1595                         GPU_vertbuf_attr_set(vbo, attr_id.n1, i * 4 + 2, n[(i) % NSEGMENTS]);
1596                         GPU_vertbuf_attr_set(vbo, attr_id.n1, i * 4 + 3, n[(i) % NSEGMENTS]);
1597                         GPU_vertbuf_attr_set(vbo, attr_id.n2, i * 4 + 2, neg[(i) % NSEGMENTS]);
1598                         GPU_vertbuf_attr_set(vbo, attr_id.n2, i * 4 + 3, neg[(i) % NSEGMENTS]);
1599                 }
1600
1601                 SHC.drw_lamp_spot = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
1602         }
1603         return SHC.drw_lamp_spot;
1604 #undef NSEGMENTS
1605 }
1606
1607 GPUBatch *DRW_cache_lamp_spot_volume_get(void)
1608 {
1609 #define NSEGMENTS 32
1610         if (!SHC.drw_lamp_spot_volume) {
1611                 /* a single ring of vertices */
1612                 float p[NSEGMENTS][2];
1613                 for (int i = 0; i < NSEGMENTS; ++i) {
1614                         float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS);
1615                         p[i][0] = cosf(angle);
1616                         p[i][1] = sinf(angle);
1617                 }
1618
1619                 static GPUVertFormat format = { 0 };
1620                 static struct { uint pos; } attr_id;
1621                 if (format.attr_len == 0) {
1622                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
1623                 }
1624
1625                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
1626                 GPU_vertbuf_data_alloc(vbo, NSEGMENTS * 3);
1627
1628                 uint v_idx = 0;
1629                 for (int i = 0; i < NSEGMENTS; ++i) {
1630                         float cv[2], v[3];
1631
1632                         ARRAY_SET_ITEMS(v, 0.0f, 0.0f, 0.0f);
1633                         GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
1634
1635                         cv[0] = p[i % NSEGMENTS][0];
1636                         cv[1] = p[i % NSEGMENTS][1];
1637                         ARRAY_SET_ITEMS(v, cv[0], cv[1], -1.0f);
1638                         GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
1639
1640                         cv[0] = p[(i + 1) % NSEGMENTS][0];
1641                         cv[1] = p[(i + 1) % NSEGMENTS][1];
1642                         ARRAY_SET_ITEMS(v, cv[0], cv[1], -1.0f);
1643                         GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
1644                 }
1645
1646                 SHC.drw_lamp_spot_volume = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
1647         }
1648         return SHC.drw_lamp_spot_volume;
1649 #undef NSEGMENTS
1650 }
1651
1652 GPUBatch *DRW_cache_lamp_spot_square_get(void)
1653 {
1654         if (!SHC.drw_lamp_spot_square) {
1655                 float p[5][3] = {{ 0.0f,  0.0f,  0.0f},
1656                                  { 1.0f,  1.0f, -1.0f},
1657                                  { 1.0f, -1.0f, -1.0f},
1658                                  {-1.0f, -1.0f, -1.0f},
1659                                  {-1.0f,  1.0f, -1.0f}};
1660
1661                 uint v_idx = 0;
1662
1663                 /* Position Only 3D format */
1664                 static GPUVertFormat format = { 0 };
1665                 static struct { uint pos; } attr_id;
1666                 if (format.attr_len == 0) {
1667                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
1668                 }
1669
1670                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
1671                 GPU_vertbuf_data_alloc(vbo, 16);
1672
1673                 /* piramid sides */
1674                 for (int i = 1; i <= 4; ++i) {
1675                         GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, p[0]);
1676                         GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, p[i]);
1677
1678                         GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, p[(i % 4) + 1]);
1679                         GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, p[((i + 1) % 4) + 1]);
1680                 }
1681
1682                 SHC.drw_lamp_spot_square = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
1683         }
1684         return SHC.drw_lamp_spot_square;
1685 }
1686
1687 GPUBatch *DRW_cache_lamp_spot_square_volume_get(void)
1688 {
1689         if (!SHC.drw_lamp_spot_square_volume) {
1690                 float p[5][3] = {{ 0.0f,  0.0f,  0.0f},
1691                                  { 1.0f,  1.0f, -1.0f},
1692                                  { 1.0f, -1.0f, -1.0f},
1693                                  {-1.0f, -1.0f, -1.0f},
1694                                  {-1.0f,  1.0f, -1.0f}};
1695
1696                 uint v_idx = 0;
1697
1698                 /* Position Only 3D format */
1699                 static GPUVertFormat format = { 0 };
1700                 static struct { uint pos; } attr_id;
1701                 if (format.attr_len == 0) {
1702                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
1703                 }
1704
1705                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
1706                 GPU_vertbuf_data_alloc(vbo, 12);
1707
1708                 /* piramid sides */
1709                 for (int i = 1; i <= 4; ++i) {
1710                         GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, p[0]);
1711                         GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, p[((i + 1) % 4) + 1]);
1712                         GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, p[(i % 4) + 1]);
1713                 }
1714
1715                 SHC.drw_lamp_spot_square_volume = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
1716         }
1717         return SHC.drw_lamp_spot_square_volume;
1718 }
1719
1720 /** \} */
1721
1722 /* -------------------------------------------------------------------- */
1723
1724 /** \name Speaker
1725  * \{ */
1726
1727 GPUBatch *DRW_cache_speaker_get(void)
1728 {
1729         if (!SHC.drw_speaker) {
1730                 float v[3];
1731                 const int segments = 16;
1732                 int vidx = 0;
1733
1734                 /* Position Only 3D format */
1735                 static GPUVertFormat format = { 0 };
1736                 static struct { uint pos; } attr_id;
1737                 if (format.attr_len == 0) {
1738                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
1739                 }
1740
1741                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
1742                 GPU_vertbuf_data_alloc(vbo, 3 * segments * 2 + 4 * 4);
1743
1744                 for (int j = 0; j < 3; j++) {
1745                         float z = 0.25f * j - 0.125f;
1746                         float r = (j == 0 ? 0.5f : 0.25f);
1747
1748                         copy_v3_fl3(v, r, 0.0f, z);
1749                         GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
1750                         for (int i = 1; i < segments; i++) {
1751                                 float x = cosf(2.f * (float)M_PI * i / segments) * r;
1752                                 float y = sinf(2.f * (float)M_PI * i / segments) * r;
1753                                 copy_v3_fl3(v, x, y, z);
1754                                 GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
1755                                 GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
1756                         }
1757                         copy_v3_fl3(v, r, 0.0f, z);
1758                         GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
1759                 }
1760
1761                 for (int j = 0; j < 4; j++) {
1762                         float x = (((j + 1) % 2) * (j - 1)) * 0.5f;
1763                         float y = ((j % 2) * (j - 2)) * 0.5f;
1764                         for (int i = 0; i < 3; i++) {
1765                                 if (i == 1) {
1766                                         x *= 0.5f;
1767                                         y *= 0.5f;
1768                                 }
1769
1770                                 float z = 0.25f * i - 0.125f;
1771                                 copy_v3_fl3(v, x, y, z);
1772                                 GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
1773                                 if (i == 1) {
1774                                         GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
1775                                 }
1776                         }
1777                 }
1778
1779                 SHC.drw_speaker = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
1780         }
1781         return SHC.drw_speaker;
1782 }
1783
1784 /** \} */
1785
1786 /* -------------------------------------------------------------------- */
1787
1788 /** \name Probe
1789  * \{ */
1790
1791 GPUBatch *DRW_cache_lightprobe_cube_get(void)
1792 {
1793         if (!SHC.drw_lightprobe_cube) {
1794                 int v_idx = 0;
1795                 const float sin_pi_3 = 0.86602540378f;
1796                 const float cos_pi_3 = 0.5f;
1797                 float v[7][3] = {
1798                         {0.0f, 1.0f, 0.0f},
1799                         {sin_pi_3, cos_pi_3, 0.0f},
1800                         {sin_pi_3, -cos_pi_3, 0.0f},
1801                         {0.0f, -1.0f, 0.0f},
1802                         {-sin_pi_3, -cos_pi_3, 0.0f},
1803                         {-sin_pi_3, cos_pi_3, 0.0f},
1804                         {0.0f, 0.0f, 0.0f},
1805                 };
1806
1807                 /* Position Only 3D format */
1808                 static GPUVertFormat format = { 0 };
1809                 static struct { uint pos; } attr_id;
1810                 if (format.attr_len == 0) {
1811                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
1812                 }
1813
1814                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
1815                 GPU_vertbuf_data_alloc(vbo, (6 + 3) * 2);
1816
1817                 for (int i = 0; i < 6; ++i) {
1818                         GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[i]);
1819                         GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[(i + 1) % 6]);
1820                 }
1821
1822                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[1]);
1823                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]);
1824
1825                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[5]);
1826                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]);
1827
1828                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[3]);
1829                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]);
1830
1831                 SHC.drw_lightprobe_cube = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
1832         }
1833         return SHC.drw_lightprobe_cube;
1834 }
1835
1836 GPUBatch *DRW_cache_lightprobe_grid_get(void)
1837 {
1838         if (!SHC.drw_lightprobe_grid) {
1839                 int v_idx = 0;
1840                 const float sin_pi_3 = 0.86602540378f;
1841                 const float cos_pi_3 = 0.5f;
1842                 const float v[7][3] = {
1843                         {0.0f, 1.0f, 0.0f},
1844                         {sin_pi_3, cos_pi_3, 0.0f},
1845                         {sin_pi_3, -cos_pi_3, 0.0f},
1846                         {0.0f, -1.0f, 0.0f},
1847                         {-sin_pi_3, -cos_pi_3, 0.0f},
1848                         {-sin_pi_3, cos_pi_3, 0.0f},
1849                         {0.0f, 0.0f, 0.0f},
1850                 };
1851
1852                 /* Position Only 3D format */
1853                 static GPUVertFormat format = { 0 };
1854                 static struct { uint pos; } attr_id;
1855                 if (format.attr_len == 0) {
1856                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
1857                 }
1858
1859                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
1860                 GPU_vertbuf_data_alloc(vbo, (6 * 2 + 3) * 2);
1861
1862                 for (int i = 0; i < 6; ++i) {
1863                         float tmp_v1[3], tmp_v2[3], tmp_tr[3];
1864                         copy_v3_v3(tmp_v1, v[i]);
1865                         copy_v3_v3(tmp_v2, v[(i + 1) % 6]);
1866                         GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, tmp_v1);
1867                         GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, tmp_v2);
1868
1869                         /* Internal wires. */
1870                         for (int j = 1; j < 2; ++j) {
1871                                 mul_v3_v3fl(tmp_tr, v[(i / 2) * 2 + 1], -0.5f * j);
1872                                 add_v3_v3v3(tmp_v1, v[i], tmp_tr);
1873                                 add_v3_v3v3(tmp_v2, v[(i + 1) % 6], tmp_tr);
1874                                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, tmp_v1);
1875                                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, tmp_v2);
1876                         }
1877                 }
1878
1879                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[1]);
1880                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]);
1881
1882                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[5]);
1883                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]);
1884
1885                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[3]);
1886                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]);
1887
1888                 SHC.drw_lightprobe_grid = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
1889         }
1890         return SHC.drw_lightprobe_grid;
1891 }
1892
1893 GPUBatch *DRW_cache_lightprobe_planar_get(void)
1894 {
1895         if (!SHC.drw_lightprobe_planar) {
1896                 int v_idx = 0;
1897                 const float sin_pi_3 = 0.86602540378f;
1898                 float v[4][3] = {
1899                         {0.0f, 0.5f, 0.0f},
1900                         {sin_pi_3, 0.0f, 0.0f},
1901                         {0.0f, -0.5f, 0.0f},
1902                         {-sin_pi_3, 0.0f, 0.0f},
1903                 };
1904
1905                 /* Position Only 3D format */
1906                 static GPUVertFormat format = { 0 };
1907                 static struct { uint pos; } attr_id;
1908                 if (format.attr_len == 0) {
1909                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
1910                 }
1911
1912                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
1913                 GPU_vertbuf_data_alloc(vbo, 4 * 2);
1914
1915                 for (int i = 0; i < 4; ++i) {
1916                         GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[i]);
1917                         GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[(i + 1) % 4]);
1918                 }
1919
1920                 SHC.drw_lightprobe_planar = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
1921         }
1922         return SHC.drw_lightprobe_planar;
1923 }
1924
1925 /** \} */
1926
1927 /* -------------------------------------------------------------------- */
1928
1929 /** \name Armature Bones
1930  * \{ */
1931
1932 static const float bone_octahedral_verts[6][3] = {
1933         { 0.0f, 0.0f,  0.0f},
1934         { 0.1f, 0.1f,  0.1f},
1935         { 0.1f, 0.1f, -0.1f},
1936         {-0.1f, 0.1f, -0.1f},
1937         {-0.1f, 0.1f,  0.1f},
1938         { 0.0f, 1.0f,  0.0f}
1939 };
1940
1941 static const float bone_octahedral_smooth_normals[6][3] = {
1942         { 0.0f, -1.0f,  0.0f},
1943 #if 0 /* creates problems for outlines when scaled */
1944         { 0.943608f * M_SQRT1_2, -0.331048f,  0.943608f * M_SQRT1_2},
1945         { 0.943608f * M_SQRT1_2, -0.331048f, -0.943608f * M_SQRT1_2},
1946         {-0.943608f * M_SQRT1_2, -0.331048f, -0.943608f * M_SQRT1_2},
1947         {-0.943608f * M_SQRT1_2, -0.331048f,  0.943608f * M_SQRT1_2},
1948 #else
1949         { M_SQRT1_2, 0.0f,  M_SQRT1_2},
1950         { M_SQRT1_2, 0.0f, -M_SQRT1_2},
1951         {-M_SQRT1_2, 0.0f, -M_SQRT1_2},
1952         {-M_SQRT1_2, 0.0f,  M_SQRT1_2},
1953 #endif
1954         { 0.0f,  1.0f,  0.0f}
1955 };
1956
1957 #if 0  /* UNUSED */
1958
1959 static const uint bone_octahedral_wire[24] = {
1960         0, 1,  1, 5,  5, 3,  3, 0,
1961         0, 4,  4, 5,  5, 2,  2, 0,
1962         1, 2,  2, 3,  3, 4,  4, 1,
1963 };
1964
1965 /* aligned with bone_octahedral_wire
1966  * Contains adjacent normal index */
1967 static const uint bone_octahedral_wire_adjacent_face[24] = {
1968         0, 3,  4, 7,  5, 6,  1, 2,
1969         2, 3,  6, 7,  4, 5,  0, 1,
1970         0, 4,  1, 5,  2, 6,  3, 7,
1971 };
1972 #endif
1973
1974 static const uint bone_octahedral_solid_tris[8][3] = {
1975         {2, 1, 0}, /* bottom */
1976         {3, 2, 0},
1977         {4, 3, 0},
1978         {1, 4, 0},
1979
1980         {5, 1, 2}, /* top */
1981         {5, 2, 3},
1982         {5, 3, 4},
1983         {5, 4, 1}
1984 };
1985
1986 /**
1987  * Store indices of generated verts from bone_octahedral_solid_tris to define adjacency infos.
1988  * Example: triangle {2, 1, 0} is adjacent to {3, 2, 0}, {1, 4, 0} and {5, 1, 2}.
1989  * {2, 1, 0} becomes {0, 1, 2}
1990  * {3, 2, 0} becomes {3, 4, 5}
1991  * {1, 4, 0} becomes {9, 10, 11}
1992  * {5, 1, 2} becomes {12, 13, 14}
1993  * According to opengl specification it becomes (starting from
1994  * the first vertex of the first face aka. vertex 2):
1995  * {0, 12, 1, 10, 2, 3}
1996  **/
1997 static const uint bone_octahedral_wire_lines_adjacency[12][4] = {
1998         { 0, 1, 2,  6}, { 0, 12, 1,  6}, { 0, 3, 12,  6}, { 0, 2, 3,  6},
1999         { 1, 6, 2,  3}, { 1, 12, 6,  3}, { 1, 0, 12,  3}, { 1, 2, 0,  3},
2000         { 2, 0, 1, 12}, { 2,  3, 0, 12}, { 2, 6,  3, 12}, { 2, 1, 6, 12},
2001 };
2002
2003 #if 0 /* UNUSED */
2004 static const uint bone_octahedral_solid_tris_adjacency[8][6] = {
2005         { 0, 12,  1, 10,  2,  3},
2006         { 3, 15,  4,  1,  5,  6},
2007         { 6, 18,  7,  4,  8,  9},
2008         { 9, 21, 10,  7, 11,  0},
2009
2010         {12, 22, 13,  2, 14, 17},
2011         {15, 13, 16,  5, 17, 20},
2012         {18, 16, 19,  8, 20, 23},
2013         {21, 19, 22, 11, 23, 14},
2014 };
2015 #endif
2016
2017 /* aligned with bone_octahedral_solid_tris */
2018 static const float bone_octahedral_solid_normals[8][3] = {
2019         { M_SQRT1_2,   -M_SQRT1_2,    0.00000000f},
2020         {-0.00000000f, -M_SQRT1_2,   -M_SQRT1_2},
2021         {-M_SQRT1_2,   -M_SQRT1_2,    0.00000000f},
2022         { 0.00000000f, -M_SQRT1_2,    M_SQRT1_2},
2023         { 0.99388373f,  0.11043154f, -0.00000000f},
2024         { 0.00000000f,  0.11043154f, -0.99388373f},
2025         {-0.99388373f,  0.11043154f,  0.00000000f},
2026         { 0.00000000f,  0.11043154f,  0.99388373f}
2027 };
2028
2029 GPUBatch *DRW_cache_bone_octahedral_get(void)
2030 {
2031         if (!SHC.drw_bone_octahedral) {
2032                 uint v_idx = 0;
2033
2034                 static GPUVertFormat format = { 0 };
2035                 static struct { uint pos, nor, snor; } attr_id;
2036                 if (format.attr_len == 0) {
2037                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
2038                         attr_id.nor = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
2039                         attr_id.snor = GPU_vertformat_attr_add(&format, "snor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
2040                 }
2041
2042                 /* Vertices */
2043                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
2044                 GPU_vertbuf_data_alloc(vbo, 24);
2045
2046                 for (int i = 0; i < 8; i++) {
2047                         for (int j = 0; j < 3; ++j) {
2048                                 GPU_vertbuf_attr_set(vbo, attr_id.nor, v_idx, bone_octahedral_solid_normals[i]);
2049                                 GPU_vertbuf_attr_set(vbo, attr_id.snor, v_idx, bone_octahedral_smooth_normals[bone_octahedral_solid_tris[i][j]]);
2050                                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][j]]);
2051                         }
2052                 }
2053
2054                 SHC.drw_bone_octahedral = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL,
2055                                                               GPU_BATCH_OWNS_VBO);
2056         }
2057         return SHC.drw_bone_octahedral;
2058 }
2059
2060 GPUBatch *DRW_cache_bone_octahedral_wire_get(void)
2061 {
2062         if (!SHC.drw_bone_octahedral_wire) {
2063                 GPUIndexBufBuilder elb;
2064                 GPU_indexbuf_init(&elb, GPU_PRIM_LINES_ADJ, 12, 24);
2065
2066                 for (int i = 0; i < 12; i++) {
2067                         GPU_indexbuf_add_line_adj_verts(&elb,
2068                                                         bone_octahedral_wire_lines_adjacency[i][0],
2069                                                         bone_octahedral_wire_lines_adjacency[i][1],
2070                                                         bone_octahedral_wire_lines_adjacency[i][2],
2071                                                         bone_octahedral_wire_lines_adjacency[i][3]);
2072                 }
2073
2074                 /* HACK Reuse vertex buffer. */
2075                 GPUBatch *pos_nor_batch = DRW_cache_bone_octahedral_get();
2076
2077                 SHC.drw_bone_octahedral_wire = GPU_batch_create_ex(GPU_PRIM_LINES_ADJ, pos_nor_batch->verts[0], GPU_indexbuf_build(&elb),
2078                                                                    GPU_BATCH_OWNS_INDEX);
2079         }
2080         return SHC.drw_bone_octahedral_wire;
2081 }
2082
2083 /* XXX TODO move that 1 unit cube to more common/generic place? */
2084 static const float bone_box_verts[8][3] = {
2085         { 1.0f, 0.0f,  1.0f},
2086         { 1.0f, 0.0f, -1.0f},
2087         {-1.0f, 0.0f, -1.0f},
2088         {-1.0f, 0.0f,  1.0f},
2089         { 1.0f, 1.0f,  1.0f},
2090         { 1.0f, 1.0f, -1.0f},
2091         {-1.0f, 1.0f, -1.0f},
2092         {-1.0f, 1.0f,  1.0f}
2093 };
2094
2095 static const float bone_box_smooth_normals[8][3] = {
2096         { M_SQRT3, -M_SQRT3,  M_SQRT3},
2097         { M_SQRT3, -M_SQRT3, -M_SQRT3},
2098         {-M_SQRT3, -M_SQRT3, -M_SQRT3},
2099         {-M_SQRT3, -M_SQRT3,  M_SQRT3},
2100         { M_SQRT3,  M_SQRT3,  M_SQRT3},
2101         { M_SQRT3,  M_SQRT3, -M_SQRT3},
2102         {-M_SQRT3,  M_SQRT3, -M_SQRT3},
2103         {-M_SQRT3,  M_SQRT3,  M_SQRT3},
2104 };
2105
2106 #if 0 /* UNUSED */
2107 static const uint bone_box_wire[24] = {
2108         0, 1,  1, 2,  2, 3,  3, 0,
2109         4, 5,  5, 6,  6, 7,  7, 4,
2110         0, 4,  1, 5,  2, 6,  3, 7,
2111 };
2112
2113 /* aligned with bone_octahedral_wire
2114  * Contains adjacent normal index */
2115 static const uint bone_box_wire_adjacent_face[24] = {
2116         0,  2,   0,  4,   1,  6,   1,  8,
2117         3, 10,   5, 10,   7, 11,   9, 11,
2118         3,  8,   2,  5,   4,  7,   6,  9,
2119 };
2120 #endif
2121
2122 static const uint bone_box_solid_tris[12][3] = {
2123         {0, 2, 1}, /* bottom */
2124         {0, 3, 2},
2125
2126         {0, 1, 5}, /* sides */
2127         {0, 5, 4},
2128
2129         {1, 2, 6},
2130         {1, 6, 5},
2131
2132         {2, 3, 7},
2133         {2, 7, 6},
2134
2135         {3, 0, 4},
2136         {3, 4, 7},
2137
2138         {4, 5, 6}, /* top */
2139         {4, 6, 7},
2140 };
2141
2142 /**
2143  * Store indices of generated verts from bone_box_solid_tris to define adjacency infos.
2144  * See bone_octahedral_solid_tris for more infos.
2145  **/
2146 static const uint bone_box_wire_lines_adjacency[12][4] = {
2147         { 4,  2,  0, 11}, { 0,  1, 2,  8}, { 2, 4,  1,  14}, {  1,  0,  4, 20}, /* bottom */
2148         { 0,  8, 11, 14}, { 2, 14, 8, 20}, { 1, 20, 14, 11}, {  4, 11, 20,  8}, /* top */
2149         { 20, 0, 11,  2}, { 11, 2, 8,  1}, { 8, 1,  14,  4}, { 14,  4, 20,  0}, /* sides */
2150 };
2151
2152 #if 0 /* UNUSED */
2153 static const uint bone_box_solid_tris_adjacency[12][6] = {
2154         { 0,  5,  1, 14,  2,  8},
2155         { 3, 26,  4, 20,  5,  1},
2156
2157         { 6,  2,  7, 16,  8, 11},
2158         { 9,  7, 10, 32, 11, 24},
2159
2160         {12,  0, 13, 22, 14, 17},
2161         {15, 13, 16, 30, 17,  6},
2162
2163         {18,  3, 19, 28, 20, 23},
2164         {21, 19, 22, 33, 23, 12},
2165
2166         {24,  4, 25, 10, 26, 29},
2167         {27, 25, 28, 34, 29, 18},
2168
2169         {30,  9, 31, 15, 32, 35},
2170         {33, 31, 34, 21, 35, 27},
2171 };
2172 #endif
2173
2174 /* aligned with bone_box_solid_tris */
2175 static const float bone_box_solid_normals[12][3] = {
2176         { 0.0f, -1.0f,  0.0f},
2177         { 0.0f, -1.0f,  0.0f},
2178
2179         { 1.0f,  0.0f,  0.0f},
2180         { 1.0f,  0.0f,  0.0f},
2181
2182         { 0.0f,  0.0f, -1.0f},
2183         { 0.0f,  0.0f, -1.0f},
2184
2185         {-1.0f,  0.0f,  0.0f},
2186         {-1.0f,  0.0f,  0.0f},
2187
2188         { 0.0f,  0.0f,  1.0f},
2189         { 0.0f,  0.0f,  1.0f},
2190
2191         { 0.0f,  1.0f,  0.0f},
2192         { 0.0f,  1.0f,  0.0f},
2193 };
2194
2195 GPUBatch *DRW_cache_bone_box_get(void)
2196 {
2197         if (!SHC.drw_bone_box) {
2198                 uint v_idx = 0;
2199
2200                 static GPUVertFormat format = { 0 };
2201                 static struct { uint pos, nor, snor; } attr_id;
2202                 if (format.attr_len == 0) {
2203                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
2204                         attr_id.nor = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
2205                         attr_id.snor = GPU_vertformat_attr_add(&format, "snor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
2206                 }
2207
2208                 /* Vertices */
2209                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
2210                 GPU_vertbuf_data_alloc(vbo, 36);
2211
2212                 for (int i = 0; i < 12; i++) {
2213                         for (int j = 0; j < 3; j++) {
2214                                 GPU_vertbuf_attr_set(vbo, attr_id.nor, v_idx, bone_box_solid_normals[i]);
2215                                 GPU_vertbuf_attr_set(vbo, attr_id.snor, v_idx, bone_box_smooth_normals[bone_box_solid_tris[i][j]]);
2216                                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, bone_box_verts[bone_box_solid_tris[i][j]]);
2217                         }
2218                 }
2219
2220                 SHC.drw_bone_box = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL,
2221                                                        GPU_BATCH_OWNS_VBO);
2222         }
2223         return SHC.drw_bone_box;
2224 }
2225
2226 GPUBatch *DRW_cache_bone_box_wire_get(void)
2227 {
2228         if (!SHC.drw_bone_box_wire) {
2229                 GPUIndexBufBuilder elb;
2230                 GPU_indexbuf_init(&elb, GPU_PRIM_LINES_ADJ, 12, 36);
2231
2232                 for (int i = 0; i < 12; i++) {
2233                         GPU_indexbuf_add_line_adj_verts(&elb,
2234                                                         bone_box_wire_lines_adjacency[i][0],
2235                                                         bone_box_wire_lines_adjacency[i][1],
2236                                                         bone_box_wire_lines_adjacency[i][2],
2237                                                         bone_box_wire_lines_adjacency[i][3]);
2238                 }
2239
2240                 /* HACK Reuse vertex buffer. */
2241                 GPUBatch *pos_nor_batch = DRW_cache_bone_box_get();
2242
2243                 SHC.drw_bone_box_wire = GPU_batch_create_ex(GPU_PRIM_LINES_ADJ, pos_nor_batch->verts[0], GPU_indexbuf_build(&elb),
2244                                                                    GPU_BATCH_OWNS_INDEX);
2245         }
2246         return SHC.drw_bone_box_wire;
2247 }
2248
2249 /* Helpers for envelope bone's solid sphere-with-hidden-equatorial-cylinder.
2250  * Note that here we only encode head/tail in forth component of the vector. */
2251 static void benv_lat_lon_to_co(const float lat, const float lon, float r_nor[3])
2252 {
2253         r_nor[0] = sinf(lat) * cosf(lon);
2254         r_nor[1] = sinf(lat) * sinf(lon);
2255         r_nor[2] = cosf(lat);
2256 }
2257
2258 GPUBatch *DRW_cache_bone_envelope_solid_get(void)
2259 {
2260         if (!SHC.drw_bone_envelope) {
2261                 const int lon_res = 24;
2262                 const int lat_res = 24;
2263                 const float lon_inc = 2.0f * M_PI / lon_res;
2264                 const float lat_inc = M_PI / lat_res;
2265                 uint v_idx = 0;
2266
2267                 static GPUVertFormat format = { 0 };
2268                 static struct { uint pos; } attr_id;
2269                 if (format.attr_len == 0) {
2270                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
2271                 }
2272
2273                 /* Vertices */
2274                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
2275                 GPU_vertbuf_data_alloc(vbo, ((lat_res + 1) * 2) * lon_res * 1);
2276
2277                 float lon = 0.0f;
2278                 for (int i = 0; i < lon_res; i++, lon += lon_inc) {
2279                         float lat = 0.0f;
2280                         float co1[3], co2[3];
2281
2282                         /* Note: the poles are duplicated on purpose, to restart the strip. */
2283
2284                         /* 1st sphere */
2285                         for (int j = 0; j < lat_res; j++, lat += lat_inc) {
2286                                 benv_lat_lon_to_co(lat, lon,           co1);
2287                                 benv_lat_lon_to_co(lat, lon + lon_inc, co2);
2288
2289                                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co1);
2290                                 GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co2);
2291                         }
2292
2293                         /* Closing the loop */
2294                         benv_lat_lon_to_co(M_PI, lon,           co1);
2295                         benv_lat_lon_to_co(M_PI, lon + lon_inc, co2);
2296
2297                         GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co1);
2298                         GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co2);
2299                 }
2300
2301                 SHC.drw_bone_envelope = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
2302         }
2303         return SHC.drw_bone_envelope;
2304 }
2305
2306 GPUBatch *DRW_cache_bone_envelope_outline_get(void)
2307 {
2308         if (!SHC.drw_bone_envelope_outline) {
2309 #  define CIRCLE_RESOL 64
2310                 float v0[2], v1[2], v2[2];
2311                 const float radius = 1.0f;
2312
2313                 /* Position Only 2D format */
2314                 static GPUVertFormat format = { 0 };
2315                 static struct { uint pos0, pos1, pos2; } attr_id;
2316                 if (format.attr_len == 0) {
2317                         attr_id.pos0 = GPU_vertformat_attr_add(&format, "pos0", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
2318                         attr_id.pos1 = GPU_vertformat_attr_add(&format, "pos1", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
2319                         attr_id.pos2 = GPU_vertformat_attr_add(&format, "pos2", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
2320                 }
2321
2322                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
2323                 GPU_vertbuf_data_alloc(vbo, (CIRCLE_RESOL + 1) * 2);
2324
2325                 v0[0] = radius * sinf((2.0f * M_PI * -2) / ((float)CIRCLE_RESOL));
2326                 v0[1] = radius * cosf((2.0f * M_PI * -2) / ((float)CIRCLE_RESOL));
2327                 v1[0] = radius * sinf((2.0f * M_PI * -1) / ((float)CIRCLE_RESOL));
2328                 v1[1] = radius * cosf((2.0f * M_PI * -1) / ((float)CIRCLE_RESOL));
2329
2330                 /* Output 4 verts for each position. See shader for explanation. */
2331                 uint v = 0;
2332                 for (int a = 0; a < CIRCLE_RESOL; a++) {
2333                         v2[0] = radius * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
2334                         v2[1] = radius * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
2335                         GPU_vertbuf_attr_set(vbo, attr_id.pos0, v,   v0);
2336                         GPU_vertbuf_attr_set(vbo, attr_id.pos1, v,   v1);
2337                         GPU_vertbuf_attr_set(vbo, attr_id.pos2, v++, v2);
2338                         GPU_vertbuf_attr_set(vbo, attr_id.pos0, v,   v0);
2339                         GPU_vertbuf_attr_set(vbo, attr_id.pos1, v,   v1);
2340                         GPU_vertbuf_attr_set(vbo, attr_id.pos2, v++, v2);
2341                         copy_v2_v2(v0, v1);
2342                         copy_v2_v2(v1, v2);
2343                 }
2344                 v2[0] = 0.0f;
2345                 v2[1] = radius;
2346                 GPU_vertbuf_attr_set(vbo, attr_id.pos0, v,   v0);
2347                 GPU_vertbuf_attr_set(vbo, attr_id.pos1, v,   v1);
2348                 GPU_vertbuf_attr_set(vbo, attr_id.pos2, v++, v2);
2349                 GPU_vertbuf_attr_set(vbo, attr_id.pos0, v,   v0);
2350                 GPU_vertbuf_attr_set(vbo, attr_id.pos1, v,   v1);
2351                 GPU_vertbuf_attr_set(vbo, attr_id.pos2, v++, v2);
2352
2353                 SHC.drw_bone_envelope_outline = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
2354 #  undef CIRCLE_RESOL
2355         }
2356         return SHC.drw_bone_envelope_outline;
2357 }
2358
2359 GPUBatch *DRW_cache_bone_point_get(void)
2360 {
2361         if (!SHC.drw_bone_point) {
2362 #if 0 /* old style geometry sphere */
2363                 const int lon_res = 16;
2364                 const int lat_res = 8;
2365                 const float rad = 0.05f;
2366                 const float lon_inc = 2 * M_PI / lon_res;
2367                 const float lat_inc = M_PI / lat_res;
2368                 uint v_idx = 0;
2369
2370                 static GPUVertFormat format = { 0 };
2371                 static struct { uint pos, nor; } attr_id;
2372                 if (format.attr_len == 0) {
2373                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
2374                         attr_id.nor = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
2375                 }
2376
2377                 /* Vertices */
2378                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
2379                 GPU_vertbuf_data_alloc(vbo, (lat_res - 1) * lon_res * 6);
2380
2381                 float lon = 0.0f;
2382                 for (int i = 0; i < lon_res; i++, lon += lon_inc) {
2383                         float lat = 0.0f;
2384                         for (int j = 0; j < lat_res; j++, lat += lat_inc) {
2385                                 if (j != lat_res - 1) { /* Pole */
2386                                         add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat + lat_inc, lon + lon_inc);
2387                                         add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat + lat_inc, lon);
2388                                         add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat,           lon);
2389                                 }
2390
2391                                 if (j != 0) { /* Pole */
2392                                         add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat,           lon + lon_inc);
2393                                         add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat + lat_inc, lon + lon_inc);
2394                                         add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat,           lon);
2395                                 }
2396                         }
2397                 }
2398
2399                 SHC.drw_bone_point = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
2400 #else
2401 #  define CIRCLE_RESOL 64
2402                 float v[2];
2403                 const float radius = 0.05f;
2404
2405                 /* Position Only 2D format */
2406                 static GPUVertFormat format = { 0 };
2407                 static struct { uint pos; } attr_id;
2408                 if (format.attr_len == 0) {
2409                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
2410                 }
2411
2412                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
2413                 GPU_vertbuf_data_alloc(vbo, CIRCLE_RESOL);
2414
2415                 for (int a = 0; a < CIRCLE_RESOL; a++) {
2416                         v[0] = radius * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
2417                         v[1] = radius * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
2418                         GPU_vertbuf_attr_set(vbo, attr_id.pos, a, v);
2419                 }
2420
2421                 SHC.drw_bone_point = GPU_batch_create_ex(GPU_PRIM_TRI_FAN, vbo, NULL, GPU_BATCH_OWNS_VBO);
2422 #  undef CIRCLE_RESOL
2423 #endif
2424         }
2425         return SHC.drw_bone_point;
2426 }
2427
2428 GPUBatch *DRW_cache_bone_point_wire_outline_get(void)
2429 {
2430         if (!SHC.drw_bone_point_wire) {
2431 #if 0 /* old style geometry sphere */
2432                 GPUVertBuf *vbo = sphere_wire_vbo(0.05f);
2433                 SHC.drw_bone_point_wire = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
2434 #else
2435 #  define CIRCLE_RESOL 64
2436                 float v0[2], v1[2];
2437                 const float radius = 0.05f;
2438
2439                 /* Position Only 2D format */
2440                 static GPUVertFormat format = { 0 };
2441                 static struct { uint pos0, pos1; } attr_id;
2442                 if (format.attr_len == 0) {
2443                         attr_id.pos0 = GPU_vertformat_attr_add(&format, "pos0", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
2444                         attr_id.pos1 = GPU_vertformat_attr_add(&format, "pos1", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
2445                 }
2446
2447                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
2448                 GPU_vertbuf_data_alloc(vbo, (CIRCLE_RESOL + 1) * 2);
2449
2450                 v0[0] = radius * sinf((2.0f * M_PI * -1) / ((float)CIRCLE_RESOL));
2451                 v0[1] = radius * cosf((2.0f * M_PI * -1) / ((float)CIRCLE_RESOL));
2452
2453                 uint v = 0;
2454                 for (int a = 0; a < CIRCLE_RESOL; a++) {
2455                         v1[0] = radius * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
2456                         v1[1] = radius * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
2457                         GPU_vertbuf_attr_set(vbo, attr_id.pos0, v,   v0);
2458                         GPU_vertbuf_attr_set(vbo, attr_id.pos1, v++, v1);
2459                         GPU_vertbuf_attr_set(vbo, attr_id.pos0, v,   v0);
2460                         GPU_vertbuf_attr_set(vbo, attr_id.pos1, v++, v1);
2461                         copy_v2_v2(v0, v1);
2462                 }
2463                 v1[0] = 0.0f;
2464                 v1[1] = radius;
2465                 GPU_vertbuf_attr_set(vbo, attr_id.pos0, v,   v0);
2466                 GPU_vertbuf_attr_set(vbo, attr_id.pos1, v++, v1);
2467                 GPU_vertbuf_attr_set(vbo, attr_id.pos0, v,   v0);
2468                 GPU_vertbuf_attr_set(vbo, attr_id.pos1, v++, v1);
2469
2470                 SHC.drw_bone_point_wire = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
2471 #  undef CIRCLE_RESOL
2472 #endif
2473         }
2474         return SHC.drw_bone_point_wire;
2475 }
2476
2477 /* keep in sync with armature_stick_vert.glsl */
2478 #define COL_WIRE (1 << 0)
2479 #define COL_HEAD (1 << 1)
2480 #define COL_TAIL (1 << 2)
2481 #define COL_BONE (1 << 3)
2482
2483 #define POS_HEAD (1 << 4)
2484 #define POS_TAIL (1 << 5)
2485 #define POS_BONE (1 << 6)
2486
2487 GPUBatch *DRW_cache_bone_stick_get(void)
2488 {
2489         if (!SHC.drw_bone_stick) {
2490 #define CIRCLE_RESOL 12
2491                 uint v = 0;
2492                 uint flag;
2493                 const float radius = 2.0f; /* head/tail radius */
2494                 float pos[2];
2495
2496                 /* Position Only 2D format */
2497                 static GPUVertFormat format = { 0 };
2498                 static struct { uint pos, flag; } attr_id;
2499                 if (format.attr_len == 0) {
2500                         attr_id.pos  = GPU_vertformat_attr_add(&format, "pos",  GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
2501                         attr_id.flag = GPU_vertformat_attr_add(&format, "flag", GPU_COMP_U32, 1, GPU_FETCH_INT);
2502                 }
2503
2504                 const uint vcount = (CIRCLE_RESOL + 1) * 2 + 6;
2505
2506                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
2507                 GPU_vertbuf_data_alloc(vbo, vcount);
2508
2509                 GPUIndexBufBuilder elb;
2510                 GPU_indexbuf_init_ex(&elb, GPU_PRIM_TRI_FAN, (CIRCLE_RESOL + 2) * 2 + 6 + 2, vcount, true);
2511
2512                 /* head/tail points */
2513                 for (int i = 0; i < 2; ++i) {
2514                         /* center vertex */
2515                         copy_v2_fl(pos, 0.0f);
2516                         flag  = (i == 0) ? POS_HEAD : POS_TAIL;
2517                         flag |= (i == 0) ? COL_HEAD : COL_TAIL;
2518                         GPU_vertbuf_attr_set(vbo, attr_id.pos,  v, pos);
2519                         GPU_vertbuf_attr_set(vbo, attr_id.flag, v, &flag);
2520                         GPU_indexbuf_add_generic_vert(&elb, v++);
2521                         /* circle vertices */
2522                         flag |= COL_WIRE;
2523                         for (int a = 0; a < CIRCLE_RESOL; a++) {
2524                                 pos[0] = radius * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
2525                                 pos[1] = radius * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
2526                                 GPU_vertbuf_attr_set(vbo, attr_id.pos,  v, pos);
2527                                 GPU_vertbuf_attr_set(vbo, attr_id.flag, v, &flag);
2528                                 GPU_indexbuf_add_generic_vert(&elb, v++);
2529                         }
2530                         /* Close the circle */
2531                         GPU_indexbuf_add_generic_vert(&elb, v - CIRCLE_RESOL);
2532
2533                         GPU_indexbuf_add_primitive_restart(&elb);
2534                 }
2535
2536                 /* Bone rectangle */
2537                 pos[0] = 0.0f;
2538                 for (int i = 0; i < 6; ++i) {
2539                         pos[1] = (i == 0 || i == 3) ? 0.0f : ((i < 3) ? 1.0f : -1.0f);
2540                         flag   = ((i <  2 || i >  4) ? POS_HEAD : POS_TAIL) |
2541                                  ((i == 0 || i == 3) ? 0 : COL_WIRE) | COL_BONE | POS_BONE;
2542                         GPU_vertbuf_attr_set(vbo, attr_id.pos,  v, pos);
2543                         GPU_vertbuf_attr_set(vbo, attr_id.flag, v, &flag);
2544                         GPU_indexbuf_add_generic_vert(&elb, v++);
2545                 }
2546
2547                 SHC.drw_bone_stick = GPU_batch_create_ex(GPU_PRIM_TRI_FAN, vbo, GPU_indexbuf_build(&elb),
2548                                                          GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX);
2549 #undef CIRCLE_RESOL
2550         }
2551         return SHC.drw_bone_stick;
2552 }
2553
2554 static void set_bone_axis_vert(
2555         GPUVertBuf *vbo, uint axis, uint pos, uint col,
2556         uint *v, const float *a, const float *p, const float *c)
2557 {
2558         GPU_vertbuf_attr_set(vbo, axis, *v, a);
2559         GPU_vertbuf_attr_set(vbo, pos,  *v, p);
2560         GPU_vertbuf_attr_set(vbo, col,  *v, c);
2561         *v += 1;
2562 }
2563
2564 #define S_X 0.0215f
2565 #define S_Y 0.025f
2566 static float x_axis_name[4][2] = {
2567         { 0.9f * S_X,  1.0f * S_Y}, {-1.0f * S_X, -1.0f * S_Y},
2568         {-0.9f * S_X,  1.0f * S_Y}, { 1.0f * S_X, -1.0f * S_Y}
2569 };
2570 #define X_LEN (sizeof(x_axis_name) / (sizeof(float) * 2))
2571 #undef S_X
2572 #undef S_Y
2573
2574 #define S_X 0.0175f
2575 #define S_Y 0.025f
2576 static float y_axis_name[6][2] = {
2577         {-1.0f * S_X,  1.0f * S_Y}, { 0.0f * S_X, -0.1f * S_Y},
2578         { 1.0f * S_X,  1.0f * S_Y}, { 0.0f * S_X, -0.1f * S_Y},
2579         { 0.0f * S_X, -0.1f * S_Y}, { 0.0f * S_X, -1.0f * S_Y}
2580 };
2581 #define Y_LEN (sizeof(y_axis_name) / (sizeof(float) * 2))
2582 #undef S_X
2583 #undef S_Y
2584
2585 #define S_X 0.02f
2586 #define S_Y 0.025f
2587 static float z_axis_name[10][2] = {
2588         {-0.95f * S_X,  1.00f * S_Y}, { 0.95f * S_X,  1.00f * S_Y},
2589         { 0.95f * S_X,  1.00f * S_Y}, { 0.95f * S_X,  0.90f * S_Y},
2590         { 0.95f * S_X,  0.90f * S_Y}, {-1.00f * S_X, -0.90f * S_Y},
2591         {-1.00f * S_X, -0.90f * S_Y}, {-1.00f * S_X, -1.00f * S_Y},
2592         {-1.00f * S_X, -1.00f * S_Y}, { 1.00f * S_X, -1.00f * S_Y}
2593 };
2594 #define Z_LEN (sizeof(z_axis_name) / (sizeof(float) * 2))
2595 #undef S_X
2596 #undef S_Y
2597
2598 #define S_X 0.007f
2599 #define S_Y 0.007f
2600 static float axis_marker[8][2] = {
2601 #if 0 /* square */
2602         {-1.0f * S_X,  1.0f * S_Y}, { 1.0f * S_X,  1.0f * S_Y},
2603         { 1.0f * S_X,  1.0f * S_Y}, { 1.0f * S_X, -1.0f * S_Y},
2604         { 1.0f * S_X, -1.0f * S_Y}, {-1.0f * S_X, -1.0f * S_Y},
2605         {-1.0f * S_X, -1.0f * S_Y}, {-1.0f * S_X,  1.0f * S_Y}
2606 #else /* diamond */
2607         {-S_X,  0.f}, { 0.f,  S_Y},
2608         { 0.f,  S_Y}, { S_X,  0.f},
2609         { S_X,  0.f}, { 0.f, -S_Y},
2610         { 0.f, -S_Y}, {-S_X,  0.f}
2611 #endif
2612 };
2613 #define MARKER_LEN (sizeof(axis_marker) / (sizeof(float) * 2))
2614 #define MARKER_FILL_LAYER 6
2615 #undef S_X
2616 #undef S_Y
2617
2618 #define S_X 0.0007f
2619 #define S_Y 0.0007f
2620 #define O_X  0.001f
2621 #define O_Y -0.001f
2622 static float axis_name_shadow[8][2] = {
2623         {-S_X + O_X,  S_Y + O_Y}, { S_X + O_X,  S_Y + O_Y},
2624         { S_X + O_X,  S_Y + O_Y}, { S_X + O_X, -S_Y + O_Y},
2625         { S_X + O_X, -S_Y + O_Y}, {-S_X + O_X, -S_Y + O_Y},
2626         {-S_X + O_X, -S_Y + O_Y}, {-S_X + O_X,  S_Y + O_Y}
2627 };
2628 // #define SHADOW_RES (sizeof(axis_name_shadow) / (sizeof(float) * 2))
2629 #define SHADOW_RES 0
2630 #undef O_X
2631 #undef O_Y
2632 #undef S_X
2633 #undef S_Y
2634
2635 GPUBatch *DRW_cache_bone_arrows_get(void)
2636 {
2637         if (!SHC.drw_bone_arrows) {
2638                 /* Position Only 3D format */
2639                 static GPUVertFormat format = { 0 };
2640                 static struct { uint axis, pos, col; } attr_id;
2641                 if (format.attr_len == 0) {
2642                         attr_id.axis = GPU_vertformat_attr_add(&format, "axis", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
2643                         attr_id.pos = GPU_vertformat_attr_add(&format, "screenPos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
2644                         attr_id.col = GPU_vertformat_attr_add(&format, "colorAxis", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
2645                 }
2646
2647                 /* Line */
2648                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
2649                 GPU_vertbuf_data_alloc(vbo, (2 + MARKER_LEN * MARKER_FILL_LAYER) * 3 +
2650                                             (X_LEN + Y_LEN + Z_LEN) * (1 + SHADOW_RES));
2651
2652                 uint v = 0;
2653
2654                 for (int axis = 0; axis < 3; axis++) {
2655                         float pos[2] = {0.0f, 0.0f};
2656                         float c[3] = {0.0f, 0.0f, 0.0f};
2657                         float a = 0.0f;
2658                         /* center to axis line */
2659                         set_bone_axis_vert(vbo, attr_id.axis, attr_id.pos, attr_id.col, &v, &a, pos, c);
2660                         c[axis] = 0.5f;
2661                         a = axis + 0.25f;
2662                         set_bone_axis_vert(vbo, attr_id.axis, attr_id.pos, attr_id.col, &v, &a, pos, c);
2663
2664                         /* Axis end marker */
2665                         for (int j = 1; j < MARKER_FILL_LAYER + 1; ++j) {
2666                                 for (int i = 0; i < MARKER_LEN; ++i) {
2667                                         float tmp[2];
2668                                         mul_v2_v2fl(tmp, axis_marker[i], j / (float)MARKER_FILL_LAYER);
2669                                         set_bone_axis_vert(vbo, attr_id.axis, attr_id.pos, attr_id.col,
2670                                                            &v, &a, tmp, c);
2671                                 }
2672                         }
2673
2674                         a = axis + 0.31f;
2675                         /* Axis name */
2676                         int axis_v_len;
2677                         float (*axis_verts)[2];
2678                         if (axis == 0) {
2679                                 axis_verts = x_axis_name;
2680                                 axis_v_len = X_LEN;
2681                         }
2682                         else if (axis == 1) {
2683                                 axis_verts = y_axis_name;
2684                                 axis_v_len = Y_LEN;
2685                         }
2686                         else {
2687                                 axis_verts = z_axis_name;
2688                                 axis_v_len = Z_LEN;
2689                         }
2690
2691                         /* Axis name shadows */
2692                         copy_v3_fl(c, 0.0f);
2693                         c[axis] = 0.3f;
2694                         for (int j = 0; j < SHADOW_RES; ++j) {
2695                                 for (int i = 0; i < axis_v_len; ++i) {
2696                                         float tmp[2];
2697                                         add_v2_v2v2(tmp, axis_verts[i], axis_name_shadow[j]);
2698                                         set_bone_axis_vert(vbo, attr_id.axis, attr_id.pos, attr_id.col,
2699                                                            &v, &a, tmp, c);
2700                                 }
2701                         }
2702
2703                         /* Axis name */
2704                         copy_v3_fl(c, 0.1f);
2705                         c[axis] = 1.0f;
2706                         for (int i = 0; i < axis_v_len; ++i) {
2707                                 set_bone_axis_vert(vbo, attr_id.axis, attr_id.pos, attr_id.col,
2708                                                    &v, &a, axis_verts[i], c);
2709                         }
2710                 }
2711
2712                 SHC.drw_bone_arrows = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
2713         }
2714         return SHC.drw_bone_arrows;
2715 }
2716
2717 static const float staticSine[16] = {
2718         0.0f, 0.104528463268f, 0.207911690818f, 0.309016994375f,
2719         0.406736643076f, 0.5f, 0.587785252292f, 0.669130606359f,
2720         0.743144825477f, 0.809016994375f, 0.866025403784f,
2721         0.913545457643f, 0.951056516295f, 0.978147600734f,
2722         0.994521895368f, 1.0f
2723 };
2724
2725 #define set_vert(a, b, quarter) \
2726         copy_v2_fl2(pos, (quarter % 2 == 0) ? -(a) : (a), (quarter < 2) ? -(b) : (b)); \
2727         GPU_vertbuf_attr_set(vbo, attr_id.pos, v++, pos);
2728
2729 GPUBatch *DRW_cache_bone_dof_sphere_get(void)
2730 {
2731         if (!SHC.drw_bone_dof_sphere) {
2732                 int i, j, q, n = ARRAY_SIZE(staticSine);
2733                 float x, z, px, pz, pos[2];
2734
2735                 /* Position Only 3D format */
2736                 static GPUVertFormat format = { 0 };
2737                 static struct { uint pos; } attr_id;
2738                 if (format.attr_len == 0) {
2739                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
2740                 }
2741
2742                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
2743                 GPU_vertbuf_data_alloc(vbo, n * n * 6 * 4);
2744
2745                 uint v = 0;
2746                 for (q = 0; q < 4; ++q) {
2747                         pz = 0.0f;
2748                         for (i = 1; i < n; ++i) {
2749                                 z = staticSine[i];
2750                                 px = 0.0f;
2751                                 for (j = 1; j <= (n - i); ++j) {
2752                                         x = staticSine[j];
2753                                         if (j == n - i) {
2754                                                 set_vert(px, z, q);
2755                                                 set_vert(px, pz, q);
2756                                                 set_vert(x, pz, q);
2757                                         }
2758                                         else {
2759                                                 set_vert(x, z, q);
2760                                                 set_vert(x, pz, q);
2761                                                 set_vert(px, z, q);
2762
2763                                                 set_vert(x, pz, q);
2764                                                 set_vert(px, pz, q);
2765                                                 set_vert(px, z, q);
2766                                         }
2767                                         px = x;
2768                                 }
2769                                 pz = z;
2770                         }
2771                 }
2772                 /* TODO alloc right count from the begining. */
2773                 GPU_vertbuf_data_resize(vbo, v);
2774
2775                 SHC.drw_bone_dof_sphere = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
2776         }
2777         return SHC.drw_bone_dof_sphere;
2778 }
2779
2780 GPUBatch *DRW_cache_bone_dof_lines_get(void)
2781 {
2782         if (!SHC.drw_bone_dof_lines) {
2783                 int i, n = ARRAY_SIZE(staticSine);
2784                 float pos[2];
2785
2786                 /* Position Only 3D format */
2787                 static GPUVertFormat format = { 0 };
2788                 static struct { uint pos; } attr_id;
2789                 if (format.attr_len == 0) {
2790                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
2791                 }
2792
2793                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
2794                 GPU_vertbuf_data_alloc(vbo, n * 4);
2795
2796                 uint v = 0;
2797                 for (i = 0; i < n * 4; i++) {
2798                         float a = (1.0f - (i / (float)(n * 4))) * 2.0f * M_PI;
2799                         float x = cosf(a);
2800                         float y = sinf(a);
2801                         set_vert(x, y, 0);
2802                 }
2803
2804                 SHC.drw_bone_dof_lines = GPU_batch_create_ex(GPU_PRIM_LINE_LOOP, vbo, NULL, GPU_BATCH_OWNS_VBO);
2805         }
2806         return SHC.drw_bone_dof_lines;
2807 }
2808
2809 #undef set_vert
2810
2811 /** \} */
2812
2813 /* -------------------------------------------------------------------- */
2814
2815 /** \name Camera
2816  * \{ */
2817
2818 /**
2819  * We could make these more generic functions.
2820  * although filling 1d lines is not common.
2821  *
2822  * \note Use x coordinate to identify the vertex the vertex shader take care to place it appropriately.
2823  */
2824
2825 static const float camera_coords_frame_bounds[5] = {
2826         0.0f, /* center point */
2827         1.0f, /* + X + Y */
2828         2.0f, /* + X - Y */
2829         3.0f, /* - X - Y */
2830         4.0f, /* - X + Y */
2831 };
2832
2833 static const float camera_coords_frame_tri[3] = {
2834         5.0f, /* tria + X */
2835         6.0f, /* tria - X */
2836         7.0f, /* tria + Y */
2837 };
2838
2839 /** Draw a loop of lines. */
2840 static void camera_fill_lines_loop_fl_v1(
2841         GPUVertBufRaw *pos_step,
2842         const float *coords, const uint coords_len)
2843 {
2844         for (uint i = 0, i_prev = coords_len - 1; i < coords_len; i_prev = i++) {
2845                 *((float *)GPU_vertbuf_raw_step(pos_step)) = coords[i_prev];
2846                 *((float *)GPU_vertbuf_raw_step(pos_step)) = coords[i];
2847         }
2848 }
2849
2850 /** Fan lines out from the first vertex. */
2851 static void camera_fill_lines_fan_fl_v1(
2852         GPUVertBufRaw *pos_step,
2853         const float *coords, const uint coords_len)
2854 {
2855         for (uint i = 1; i < coords_len; i++) {
2856                 *((float *)GPU_vertbuf_raw_step(pos_step)) = coords[0];
2857                 *((float *)GPU_vertbuf_raw_step(pos_step)) = coords[i];
2858         }
2859 }
2860
2861 /** Simply fill the array. */
2862 static void camera_fill_array_fl_v1(
2863         GPUVertBufRaw *pos_step,
2864         const float *coords, const uint coords_len)
2865 {
2866         for (uint i = 0; i < coords_len; i++) {
2867                 *((float *)GPU_vertbuf_raw_step(pos_step)) = coords[i];
2868         }
2869 }
2870
2871
2872 GPUBatch *DRW_cache_camera_get(void)
2873 {
2874         if (!SHC.drw_camera) {
2875                 static GPUVertFormat format = { 0 };
2876                 static struct { uint pos; } attr_id;
2877                 if (format.attr_len == 0) {
2878                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
2879                 }
2880
2881                 /* Vertices */
2882                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
2883                 const int vbo_len_capacity = 22;
2884                 GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
2885                 GPUVertBufRaw pos_step;
2886                 GPU_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
2887
2888                 /* camera cone (from center to frame) */
2889                 camera_fill_lines_fan_fl_v1(&pos_step, camera_coords_frame_bounds, ARRAY_SIZE(camera_coords_frame_bounds));
2890
2891                 /* camera frame (skip center) */
2892                 camera_fill_lines_loop_fl_v1(&pos_step, &camera_coords_frame_bounds[1], ARRAY_SIZE(camera_coords_frame_bounds) - 1);
2893
2894                 /* camera triangle (above the frame) */
2895                 camera_fill_lines_loop_fl_v1(&pos_step, camera_coords_frame_tri, ARRAY_SIZE(camera_coords_frame_tri));
2896
2897                 BLI_assert(vbo_len_capacity == GPU_vertbuf_raw_used(&pos_step));
2898
2899                 SHC.drw_camera = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
2900         }
2901         return SHC.drw_camera;
2902 }
2903
2904 GPUBatch *DRW_cache_camera_frame_get(void)
2905 {
2906         if (!SHC.drw_camera_frame) {
2907
2908                 static GPUVertFormat format = { 0 };
2909                 static struct { uint pos; } attr_id;
2910                 if (format.attr_len == 0) {
2911                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
2912                 }
2913
2914                 /* Vertices */
2915                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
2916                 const int vbo_len_capacity = 8;
2917                 GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
2918                 GPUVertBufRaw pos_step;
2919                 GPU_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
2920
2921                 /* camera frame (skip center) */
2922                 camera_fill_lines_loop_fl_v1(&pos_step, &camera_coords_frame_bounds[1], ARRAY_SIZE(camera_coords_frame_bounds) - 1);
2923
2924                 BLI_assert(vbo_len_capacity == GPU_vertbuf_raw_used(&pos_step));
2925
2926                 SHC.drw_camera_frame = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
2927         }
2928         return SHC.drw_camera_frame;
2929 }
2930
2931 GPUBatch *DRW_cache_camera_tria_get(void)
2932 {
2933         if (!SHC.drw_camera_tria) {
2934                 static GPUVertFormat format = { 0 };
2935                 static struct { uint pos; } attr_id;
2936                 if (format.attr_len == 0) {
2937                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
2938                 }
2939
2940                 /* Vertices */
2941                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
2942                 const int vbo_len_capacity = 3;
2943                 GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
2944                 GPUVertBufRaw pos_step;
2945                 GPU_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
2946
2947                 /* camera triangle (above the frame) */
2948                 camera_fill_array_fl_v1(&pos_step, camera_coords_frame_tri, ARRAY_SIZE(camera_coords_frame_tri));
2949
2950                 BLI_assert(vbo_len_capacity == GPU_vertbuf_raw_used(&pos_step));
2951
2952                 SHC.drw_camera_tria = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
2953         }
2954         return SHC.drw_camera_tria;
2955 }
2956
2957 /** \} */
2958
2959 /* -------------------------------------------------------------------- */
2960
2961 /** \name Object Mode Helpers
2962  * \{ */
2963
2964 /* Object Center */
2965 GPUBatch *DRW_cache_single_vert_get(void)
2966 {
2967         if (!SHC.drw_single_vertice) {
2968                 float v1[3] = {0.0f, 0.0f, 0.0f};
2969
2970                 /* Position Only 3D format */
2971                 static GPUVertFormat format = { 0 };
2972                 static struct { uint pos; } attr_id;
2973                 if (format.attr_len == 0) {
2974                         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
2975                 }
2976
2977                 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
2978                 GPU_vertbuf_data_alloc(vbo, 1);
2979
2980                 GPU_vertbuf_attr_set(vbo, attr_id.pos, 0, v1);
2981
2982                 SHC.drw_single_vertice = GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO);
2983         }
2984         return SHC.drw_single_vertice;
2985 }
2986
2987 /** \} */
2988
2989 /* -------------------------------------------------------------------- */
2990
2991 /** \name Meshes
2992  * \{ */
2993
2994 GPUBatch *DRW_cache_mesh_all_verts_get(Object *ob)
2995 {
2996         BLI_assert(ob->type == OB_MESH);
2997         return DRW_mesh_batch_cache_get_all_verts(ob->data);
2998 }
2999
3000 GPUBatch *DRW_cache_mesh_all_edges_get(Object *ob)
3001 {
3002         BLI_assert(ob->type == OB_MESH);
3003         return DRW_mesh_batch_cache_get_all_edges(ob->data);
3004 }
3005
3006 GPUBatch *DRW_cache_mesh_loose_edges_get(Object *ob)
3007 {
3008         BLI_assert(ob->type == OB_MESH);
3009         return DRW_mesh_batch_cache_get_loose_edges(ob->data);
3010 }
3011
3012 GPUBatch *DRW_cache_mesh_edge_detection_get(Object *ob, bool *r_is_manifold)
3013 {
3014         BLI_assert(ob->type == OB_MESH);
3015         return DRW_mesh_batch_cache_get_edge_detection(ob->data, r_is_manifold);
3016 }
3017
3018 GPUBatch *DRW_cache_mesh_surface_get(Object *ob)
3019 {
3020         BLI_assert(ob->type == OB_MESH);
3021         return DRW_mesh_batch_cache_get_surface(ob->data);
3022 }
3023
3024 GPUBatch *DRW_cache_mesh_surface_edges_get(Object *ob)
3025 {
3026         BLI_assert(ob->type == OB_MESH);
3027         return DRW_mesh_batch_cache_get_surface_edges(ob->data);
3028 }
3029
3030 /* Return list of batches with length equal to max(1, totcol). */
3031 GPUBatch **DRW_cache_mesh_surface_shaded_get(
3032         Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len,
3033         char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count)
3034 {
3035         BLI_assert(ob->type == OB_MESH);
3036         return DRW_mesh_batch_cache_get_surface_shaded(ob->data, gpumat_array, gpumat_array_len,
3037                                                        auto_layer_names, auto_layer_is_srgb, auto_layer_count);
3038 }
3039
3040 /* Return list of batches with length equal to max(1, totcol). */
3041 GPUBatch **DRW_cache_mesh_surface_texpaint_get(Object *ob)
3042 {
3043         BLI_assert(ob->type == OB_MESH);
3044         return DRW_mesh_batch_cache_get_surface_texpaint(ob->data);
3045 }
3046
3047 GPUBatch *DRW_cache_mesh_surface_texpaint_single_get(Object *ob)
3048 {
3049         BLI_assert(ob->type == OB_MESH);
3050         return DRW_mesh_batch_cache_get_surface_texpaint_single(ob->data);
3051 }
3052
3053 GPUBatch *DRW_cache_mesh_surface_vertpaint_get(Object *ob)
3054 {
3055         BLI_assert(ob->type == OB_MESH);
3056         return DRW_mesh_batch_cache_get_surface_vertpaint(ob->data);
3057 }
3058
3059 GPUBatch *DRW_cache_mesh_surface_weights_get(Object *ob)
3060 {
3061         BLI_assert(ob->type == OB_MESH);
3062         return DRW_mesh_batch_cache_get_surface_weights(ob->data);
3063 }
3064
3065 GPUBatch *DRW_cache_mesh_face_wireframe_get(Object *ob)
3066 {
3067         BLI_assert(ob->type == OB_MESH);
3068         return DRW_mesh_batch_cache_get_wireframes_face(ob->data);
3069 }
3070
3071 void DRW_cache_mesh_sculpt_coords_ensure(Object *ob)
3072 {
3073         BLI_assert(ob->type == OB_MESH);
3074
3075         Mesh *me = ob->data;
3076         DRW_mesh_cache_sculpt_coords_ensure(me);
3077 }
3078
3079 /** \} */
3080
3081 /* -------------------------------------------------------------------- */
3082
3083 /** \name Curve
3084  * \{ */
3085
3086 GPUBatch *DRW_cache_curve_edge_wire_get(Object *ob)
3087 {
3088         BLI_assert(ob->type == OB_CURVE);
3089
3090         struct Curve *cu = ob->data;
3091         return DRW_curve_batch_cache_get_wire_edge(cu);
3092 }
3093
3094 GPUBatch *DRW_cache_curve_edge_normal_get(Object *ob)
3095 {
3096         BLI_assert(ob->type == OB_CURVE);
3097
3098         struct Curve *cu = ob->data;
3099         return DRW_curve_batch_cache_get_normal_edge(cu);
3100 }
3101
3102 GPUBatch *DRW_cache_curve_edge_overlay_get(Object *ob)
3103 {
3104         BLI_assert(ELEM(ob->type, OB_CURVE, OB_SURF));
3105
3106         struct Curve *cu = ob->data;
3107         return DRW_curve_batch_cache_get_edit_edges(cu);
3108 }
3109
3110 GPUBatch *DRW_cache_curve_vert_overlay_get(Object *ob, bool handles)
3111 {
3112         BLI_assert(ELEM(ob->type, OB_CURVE, OB_SURF));
3113
3114         struct Curve *cu = ob->data;
3115         return DRW_curve_batch_cache_get_edit_verts(cu, handles);
3116 }
3117
3118 GPUBatch *DRW_cache_curve_surface_get(Object *ob)
3119 {
3120         BLI_assert(ob->type == OB_CURVE);
3121
3122         struct Curve *cu = ob->data;
3123         struct Mesh *mesh_eval = ob->runtime.mesh_eval;
3124         if (mesh_eval != NULL) {
3125                 return DRW_mesh_batch_cache_get_surface(mesh_eval);
3126         }
3127         else {
3128                 return DRW_curve_batch_cache_get_triangles_with_normals(cu);
3129         }
3130 }
3131
3132 GPUBatch *DRW_cache_curve_loose_edges_get(Object *ob)
3133 {
3134         BLI_assert(ob->type == OB_CURVE);
3135
3136         struct Curve *cu = ob->data;
3137         struct Mesh *mesh_eval = ob->runtime.mesh_eval;
3138         if (mesh_eval != NULL) {
3139                 return DRW_mesh_batch_cache_get_loose_edges(mesh_eval);
3140         }
3141         else {
3142                 /* TODO */
3143                 UNUSED_VARS(cu);
3144                 return NULL;
3145         }
3146 }
3147
3148 GPUBatch *DRW_cache_curve_face_wireframe_get(Object *ob)
3149 {
3150         BLI_assert(ob->type == OB_CURVE);
3151
3152         struct Curve *cu = ob->data;
3153         struct Mesh *mesh_eval = ob->runtime.mesh_eval;
3154         if (mesh_eval != NULL) {
3155                 return DRW_mesh_batch_cache_get_wireframes_face(mesh_eval);
3156         }
3157         else {
3158                 return DRW_curve_batch_cache_get_wireframes_face(cu);
3159         }
3160 }
3161
3162 /* Return list of batches */
3163 GPUBatch **DRW_cache_curve_surface_shaded_get(
3164         Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len)
3165 {
3166         BLI_assert(ob->type == OB_CURVE);
3167
3168         struct Curve *cu = ob->data;
3169         struct Mesh *mesh_eval = ob->runtime.mesh_eval;
3170         if (mesh_eval != NULL) {
3171                 return DRW_mesh_batch_cache_get_surface_shaded(mesh_eval, gpumat_array, gpumat_array_len, NULL, NULL, NULL);
3172         }
3173         else {
3174                 return DRW_curve_batch_cache_get_surface_shaded(cu, gpumat_array, gpumat_array_len);
3175         }
3176 }
3177
3178 /** \} */
3179
3180 /* -------------------------------------------------------------------- */