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