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