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