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