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