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