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