89ffa0101456a1dc23fc0e98d2f155bee25ec2ad
[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_object_types.h"
30
31 #include "BLI_utildefines.h"
32 #include "BLI_math.h"
33
34 #include "BKE_mesh_render.h"
35
36 #include "GPU_batch.h"
37
38 #include "draw_cache.h"
39
40 static struct DRWShapeCache {
41         Batch *drw_single_vertice;
42         Batch *drw_fullscreen_quad;
43         Batch *drw_screenspace_circle;
44         Batch *drw_plain_axes;
45         Batch *drw_single_arrow;
46         Batch *drw_cube;
47         Batch *drw_circle;
48         Batch *drw_square;
49         Batch *drw_line;
50         Batch *drw_line_endpoints;
51         Batch *drw_empty_sphere;
52         Batch *drw_empty_cone;
53         Batch *drw_arrows;
54         Batch *drw_axis_names;
55         Batch *drw_field_wind;
56         Batch *drw_field_force;
57         Batch *drw_field_vortex;
58         Batch *drw_field_tube_limit;
59         Batch *drw_field_cone_limit;
60         Batch *drw_lamp;
61         Batch *drw_lamp_sunrays;
62         Batch *drw_lamp_area;
63         Batch *drw_lamp_hemi;
64         Batch *drw_lamp_spot;
65         Batch *drw_lamp_spot_square;
66         Batch *drw_speaker;
67         Batch *drw_bone_octahedral;
68         Batch *drw_bone_octahedral_wire;
69         Batch *drw_bone_point;
70         Batch *drw_bone_point_wire;
71         Batch *drw_bone_arrows;
72         Batch *drw_camera;
73         Batch *drw_camera_tria;
74         Batch *drw_camera_focus;
75 } SHC = {NULL};
76
77 void DRW_shape_cache_free(void)
78 {
79         if (SHC.drw_single_vertice)
80                 Batch_discard_all(SHC.drw_single_vertice);
81         if (SHC.drw_fullscreen_quad)
82                 Batch_discard_all(SHC.drw_fullscreen_quad);
83         if (SHC.drw_plain_axes)
84                 Batch_discard_all(SHC.drw_plain_axes);
85         if (SHC.drw_single_arrow)
86                 Batch_discard_all(SHC.drw_single_arrow);
87         if (SHC.drw_cube)
88                 Batch_discard_all(SHC.drw_cube);
89         if (SHC.drw_circle)
90                 Batch_discard_all(SHC.drw_circle);
91         if (SHC.drw_square)
92                 Batch_discard_all(SHC.drw_square);
93         if (SHC.drw_line)
94                 Batch_discard_all(SHC.drw_line);
95         if (SHC.drw_line_endpoints)
96                 Batch_discard_all(SHC.drw_line_endpoints);
97         if (SHC.drw_empty_sphere)
98                 Batch_discard_all(SHC.drw_empty_sphere);
99         if (SHC.drw_empty_cone)
100                 Batch_discard_all(SHC.drw_empty_cone);
101         if (SHC.drw_arrows)
102                 Batch_discard_all(SHC.drw_arrows);
103         if (SHC.drw_axis_names)
104                 Batch_discard_all(SHC.drw_axis_names);
105         if (SHC.drw_field_wind)
106                 Batch_discard_all(SHC.drw_field_wind);
107         if (SHC.drw_field_force)
108                 Batch_discard_all(SHC.drw_field_force);
109         if (SHC.drw_field_vortex)
110                 Batch_discard_all(SHC.drw_field_vortex);
111         if (SHC.drw_field_tube_limit)
112                 Batch_discard_all(SHC.drw_field_tube_limit);
113         if (SHC.drw_field_cone_limit)
114                 Batch_discard_all(SHC.drw_field_cone_limit);
115         if (SHC.drw_lamp)
116                 Batch_discard_all(SHC.drw_lamp);
117         if (SHC.drw_lamp_sunrays)
118                 Batch_discard_all(SHC.drw_lamp_sunrays);
119         if (SHC.drw_lamp_area)
120                 Batch_discard_all(SHC.drw_lamp_area);
121         if (SHC.drw_lamp_hemi)
122                 Batch_discard_all(SHC.drw_lamp_hemi);
123         if (SHC.drw_lamp_spot)
124                 Batch_discard_all(SHC.drw_lamp_spot);
125         if (SHC.drw_lamp_spot_square)
126                 Batch_discard_all(SHC.drw_lamp_spot_square);
127         if (SHC.drw_speaker)
128                 Batch_discard_all(SHC.drw_speaker);
129         if (SHC.drw_bone_octahedral)
130                 Batch_discard_all(SHC.drw_bone_octahedral);
131         if (SHC.drw_bone_octahedral_wire)
132                 Batch_discard_all(SHC.drw_bone_octahedral_wire);
133         if (SHC.drw_bone_point)
134                 Batch_discard_all(SHC.drw_bone_point);
135         if (SHC.drw_bone_point_wire)
136                 Batch_discard_all(SHC.drw_bone_point_wire);
137         if (SHC.drw_bone_arrows)
138                 Batch_discard_all(SHC.drw_bone_arrows);
139         if (SHC.drw_camera)
140                 Batch_discard_all(SHC.drw_camera);
141         if (SHC.drw_camera_tria)
142                 Batch_discard_all(SHC.drw_camera_tria);
143         if (SHC.drw_camera_focus)
144                 Batch_discard_all(SHC.drw_camera_focus);
145 }
146
147 /* Helper functions */
148
149 static void add_fancy_edge(VertexBuffer *vbo, unsigned int pos_id, unsigned int n1_id, unsigned int n2_id,
150                            unsigned int *v_idx, const float co1[3], const float co2[3],
151                            const float n1[3], const float n2[3])
152 {
153         VertexBuffer_set_attrib(vbo, n1_id, *v_idx, n1);
154         VertexBuffer_set_attrib(vbo, n2_id, *v_idx, n2);
155         VertexBuffer_set_attrib(vbo, pos_id, (*v_idx)++, co1);
156
157         VertexBuffer_set_attrib(vbo, n1_id, *v_idx, n1);
158         VertexBuffer_set_attrib(vbo, n2_id, *v_idx, n2);
159         VertexBuffer_set_attrib(vbo, pos_id, (*v_idx)++, co2);
160 }
161
162 static void add_lat_lon_vert(VertexBuffer *vbo, unsigned int pos_id, unsigned int nor_id,
163                              unsigned int *v_idx, const float rad, const float lat, const float lon)
164 {
165         float pos[3], nor[3];
166         nor[0] = sinf(lat) * cosf(lon);
167         nor[1] = cosf(lat);
168         nor[2] = sinf(lat) * sinf(lon);
169         mul_v3_v3fl(pos, nor, rad);
170
171         VertexBuffer_set_attrib(vbo, nor_id, *v_idx, nor);
172         VertexBuffer_set_attrib(vbo, pos_id, (*v_idx)++, pos);
173 }
174
175 static VertexBuffer *fill_arrows_vbo(const float scale)
176 {
177         /* Position Only 3D format */
178         static VertexFormat format = { 0 };
179         static unsigned int pos_id;
180         if (format.attrib_ct == 0) {
181                 pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
182         }
183
184         /* Line */
185         VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
186         VertexBuffer_allocate_data(vbo, 6 * 3);
187
188         float v1[3] = {0.0, 0.0, 0.0};
189         float v2[3] = {0.0, 0.0, 0.0};
190         float vtmp1[3], vtmp2[3];
191
192         for (int axis = 0; axis < 3; axis++) {
193                 const int arrow_axis = (axis == 0) ? 1 : 0;
194
195                 v2[axis] = 1.0f;
196                 mul_v3_v3fl(vtmp1, v1, scale);
197                 mul_v3_v3fl(vtmp2, v2, scale);
198                 VertexBuffer_set_attrib(vbo, pos_id, axis * 6 + 0, vtmp1);
199                 VertexBuffer_set_attrib(vbo, pos_id, axis * 6 + 1, vtmp2);
200
201                 v1[axis] = 0.85f;
202                 v1[arrow_axis] = -0.08f;
203                 mul_v3_v3fl(vtmp1, v1, scale);
204                 mul_v3_v3fl(vtmp2, v2, scale);
205                 VertexBuffer_set_attrib(vbo, pos_id, axis * 6 + 2, vtmp1);
206                 VertexBuffer_set_attrib(vbo, pos_id, axis * 6 + 3, vtmp2);
207
208                 v1[arrow_axis] = 0.08f;
209                 mul_v3_v3fl(vtmp1, v1, scale);
210                 mul_v3_v3fl(vtmp2, v2, scale);
211                 VertexBuffer_set_attrib(vbo, pos_id, axis * 6 + 4, vtmp1);
212                 VertexBuffer_set_attrib(vbo, pos_id, axis * 6 + 5, vtmp2);
213
214                 /* reset v1 & v2 to zero */
215                 v1[arrow_axis] = v1[axis] = v2[axis] = 0.0f;
216         }
217
218         return vbo;
219 }
220
221 static VertexBuffer *sphere_wire_vbo(const float rad)
222 {
223 #define NSEGMENTS 16
224         /* Position Only 3D format */
225         static VertexFormat format = { 0 };
226         static unsigned int pos_id;
227         if (format.attrib_ct == 0) {
228                 pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
229         }
230
231         VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
232         VertexBuffer_allocate_data(vbo, NSEGMENTS * 2 * 3);
233
234         /* a single ring of vertices */
235         float p[NSEGMENTS][2];
236         for (int i = 0; i < NSEGMENTS; ++i) {
237                 float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS);
238                 p[i][0] = rad * cosf(angle);
239                 p[i][1] = rad * sinf(angle);
240         }
241
242         for (int axis = 0; axis < 3; ++axis) {
243                 for (int i = 0; i < NSEGMENTS; ++i) {
244                         for (int j = 0; j < 2; ++j) {
245                                 float cv[2], v[3];
246
247                                 cv[0] = p[(i + j) % NSEGMENTS][0];
248                                 cv[1] = p[(i + j) % NSEGMENTS][1];
249
250                                 if (axis == 0)
251                                         v[0] = cv[0], v[1] = cv[1], v[2] = 0.0f;
252                                 else if (axis == 1)
253                                         v[0] = cv[0], v[1] = 0.0f,  v[2] = cv[1];
254                                 else
255                                         v[0] = 0.0f,  v[1] = cv[0], v[2] = cv[1];
256
257                                 VertexBuffer_set_attrib(vbo, pos_id, i * 2 + j + (NSEGMENTS * 2 * axis), v);
258                         }
259                 }
260         }
261
262         return vbo;
263 #undef NSEGMENTS
264 }
265
266 /* Quads */
267 Batch *DRW_cache_fullscreen_quad_get(void)
268 {
269         if (!SHC.drw_fullscreen_quad) {
270                 float pos[4][2] = {{-1.0f, -1.0f}, { 1.0f, -1.0f}, {-1.0f,  1.0f}, { 1.0f,  1.0f}};
271                 float uvs[4][2] = {{ 0.0f,  0.0f}, { 1.0f,  0.0f}, { 0.0f,  1.0f}, { 1.0f,  1.0f}};
272
273                 /* Position Only 2D format */
274                 static VertexFormat format = { 0 };
275                 static unsigned int pos_id, uvs_id;
276                 if (format.attrib_ct == 0) {
277                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 2, KEEP_FLOAT);
278                         uvs_id = VertexFormat_add_attrib(&format, "uvs", COMP_F32, 2, KEEP_FLOAT);
279                 }
280
281                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
282                 VertexBuffer_allocate_data(vbo, 4);
283
284                 for (int i = 0; i < 4; ++i)     {
285                         VertexBuffer_set_attrib(vbo, pos_id, i, pos[i]);
286                         VertexBuffer_set_attrib(vbo, uvs_id, i, uvs[i]);
287                 }
288
289                 SHC.drw_fullscreen_quad = Batch_create(PRIM_TRIANGLE_STRIP, vbo, NULL);
290         }
291         return SHC.drw_fullscreen_quad;
292 }
293
294 /* Common */
295
296 Batch *DRW_cache_cube_get(void)
297 {
298         if (!SHC.drw_cube) {
299                 const GLfloat verts[8][3] = {
300                         {-1.0f, -1.0f, -1.0f},
301                         {-1.0f, -1.0f,  1.0f},
302                         {-1.0f,  1.0f, -1.0f},
303                         {-1.0f,  1.0f,  1.0f},
304                         { 1.0f, -1.0f, -1.0f},
305                         { 1.0f, -1.0f,  1.0f},
306                         { 1.0f,  1.0f, -1.0f},
307                         { 1.0f,  1.0f,  1.0f}
308                 };
309
310                 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};
311
312                 /* Position Only 3D format */
313                 static VertexFormat format = { 0 };
314                 static unsigned int pos_id;
315                 if (format.attrib_ct == 0) {
316                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
317                 }
318
319                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
320                 VertexBuffer_allocate_data(vbo, 24);
321
322                 for (int i = 0; i < 24; ++i) {
323                         VertexBuffer_set_attrib(vbo, pos_id, i, verts[indices[i]]);
324                 }
325
326                 SHC.drw_cube = Batch_create(PRIM_LINES, vbo, NULL);
327         }
328         return SHC.drw_cube;
329 }
330
331 Batch *DRW_cache_circle_get(void)
332 {
333 #define CIRCLE_RESOL 32
334         if (!SHC.drw_circle) {
335                 float v[3] = {0.0f, 0.0f, 0.0f};
336
337                 /* Position Only 3D format */
338                 static VertexFormat format = { 0 };
339                 static unsigned int pos_id;
340                 if (format.attrib_ct == 0) {
341                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
342                 }
343
344                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
345                 VertexBuffer_allocate_data(vbo, CIRCLE_RESOL * 2);
346
347                 for (int a = 0; a < CIRCLE_RESOL; a++) {
348                         v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
349                         v[2] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
350                         v[1] = 0.0f;
351                         VertexBuffer_set_attrib(vbo, pos_id, a * 2, v);
352
353                         v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
354                         v[2] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
355                         v[1] = 0.0f;
356                         VertexBuffer_set_attrib(vbo, pos_id, a * 2 + 1, v);
357                 }
358
359                 SHC.drw_circle = Batch_create(PRIM_LINES, vbo, NULL);
360         }
361         return SHC.drw_circle;
362 #undef CIRCLE_RESOL
363 }
364
365 Batch *DRW_cache_square_get(void)
366 {
367         if (!SHC.drw_square) {
368                 float p[4][3] = {{ 1.0f, 0.0f,  1.0f},
369                                  { 1.0f, 0.0f, -1.0f},
370                                  {-1.0f, 0.0f, -1.0f},
371                                  {-1.0f, 0.0f,  1.0f}};
372
373                 /* Position Only 3D format */
374                 static VertexFormat format = { 0 };
375                 static unsigned int pos_id;
376                 if (format.attrib_ct == 0) {
377                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
378                 }
379
380                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
381                 VertexBuffer_allocate_data(vbo, 8);
382
383                 for (int i = 0; i < 4; i++) {
384                         VertexBuffer_set_attrib(vbo, pos_id, i * 2,     p[i % 4]);
385                         VertexBuffer_set_attrib(vbo, pos_id, i * 2 + 1, p[(i+1) % 4]);
386                 }
387
388                 SHC.drw_square = Batch_create(PRIM_LINES, vbo, NULL);
389         }
390         return SHC.drw_square;
391 }
392
393 Batch *DRW_cache_single_line_get(void)
394 {
395         /* Z axis line */
396         if (!SHC.drw_line) {
397                 float v1[3] = {0.0f, 0.0f, 0.0f};
398                 float v2[3] = {0.0f, 0.0f, 1.0f};
399
400                 /* Position Only 3D format */
401                 static VertexFormat format = { 0 };
402                 static unsigned int pos_id;
403                 if (format.attrib_ct == 0) {
404                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
405                 }
406
407                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
408                 VertexBuffer_allocate_data(vbo, 2);
409
410                 VertexBuffer_set_attrib(vbo, pos_id, 0, v1);
411                 VertexBuffer_set_attrib(vbo, pos_id, 1, v2);
412
413                 SHC.drw_line = Batch_create(PRIM_LINES, vbo, NULL);
414         }
415         return SHC.drw_line;
416 }
417
418 Batch *DRW_cache_single_line_endpoints_get(void)
419 {
420         /* Z axis line */
421         if (!SHC.drw_line_endpoints) {
422                 float v1[3] = {0.0f, 0.0f, 0.0f};
423                 float v2[3] = {0.0f, 0.0f, 1.0f};
424
425                 /* Position Only 3D format */
426                 static VertexFormat format = { 0 };
427                 static unsigned int pos_id;
428                 if (format.attrib_ct == 0) {
429                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
430                 }
431
432                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
433                 VertexBuffer_allocate_data(vbo, 2);
434
435                 VertexBuffer_set_attrib(vbo, pos_id, 0, v1);
436                 VertexBuffer_set_attrib(vbo, pos_id, 1, v2);
437
438                 SHC.drw_line_endpoints = Batch_create(PRIM_POINTS, vbo, NULL);
439         }
440         return SHC.drw_line_endpoints;
441 }
442
443 Batch *DRW_cache_screenspace_circle_get(void)
444 {
445 #define CIRCLE_RESOL 32
446         if (!SHC.drw_screenspace_circle) {
447                 float v[3] = {0.0f, 0.0f, 0.0f};
448
449                 /* Position Only 3D format */
450                 static VertexFormat format = { 0 };
451                 static unsigned int pos_id;
452                 if (format.attrib_ct == 0) {
453                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
454                 }
455
456                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
457                 VertexBuffer_allocate_data(vbo, CIRCLE_RESOL + 1);
458
459                 for (int a = 0; a <= CIRCLE_RESOL; a++) {
460                         v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
461                         v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
462                         VertexBuffer_set_attrib(vbo, pos_id, a, v);
463                 }
464
465                 SHC.drw_screenspace_circle = Batch_create(PRIM_LINE_STRIP, vbo, NULL);
466         }
467         return SHC.drw_screenspace_circle;
468 #undef CIRCLE_RESOL
469 }
470
471 /* Empties */
472 Batch *DRW_cache_plain_axes_get(void)
473 {
474         if (!SHC.drw_plain_axes) {
475                 int axis;
476                 float v1[3] = {0.0f, 0.0f, 0.0f};
477                 float v2[3] = {0.0f, 0.0f, 0.0f};
478
479                 /* Position Only 3D format */
480                 static VertexFormat format = { 0 };
481                 static unsigned int pos_id;
482                 if (format.attrib_ct == 0) {
483                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
484                 }
485
486                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
487                 VertexBuffer_allocate_data(vbo, 6);
488
489                 for (axis = 0; axis < 3; axis++) {
490                         v1[axis] = 1.0f;
491                         v2[axis] = -1.0f;
492
493                         VertexBuffer_set_attrib(vbo, pos_id, axis * 2, v1);
494                         VertexBuffer_set_attrib(vbo, pos_id, axis * 2 + 1, v2);
495
496                         /* reset v1 & v2 to zero for next axis */
497                         v1[axis] = v2[axis] = 0.0f;
498                 }
499
500                 SHC.drw_plain_axes = Batch_create(PRIM_LINES, vbo, NULL);
501         }
502         return SHC.drw_plain_axes;
503 }
504
505 Batch *DRW_cache_single_arrow_get(void)
506 {
507         if (!SHC.drw_single_arrow) {
508                 float v1[3] = {0.0f, 0.0f, 1.0f}, v2[3], v3[3];
509
510                 /* Position Only 3D format */
511                 static VertexFormat format = { 0 };
512                 static unsigned int pos_id;
513                 if (format.attrib_ct == 0) {
514                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
515                 }
516
517                 /* Square Pyramid */
518                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
519                 VertexBuffer_allocate_data(vbo, 12);
520
521                 v2[0] = 0.035f; v2[1] = 0.035f;
522                 v3[0] = -0.035f; v3[1] = 0.035f;
523                 v2[2] = v3[2] = 0.75f;
524
525                 for (int sides = 0; sides < 4; sides++) {
526                         if (sides % 2 == 1) {
527                                 v2[0] = -v2[0];
528                                 v3[1] = -v3[1];
529                         }
530                         else {
531                                 v2[1] = -v2[1];
532                                 v3[0] = -v3[0];
533                         }
534
535                         VertexBuffer_set_attrib(vbo, pos_id, sides * 3 + 0, v1);
536                         VertexBuffer_set_attrib(vbo, pos_id, sides * 3 + 1, v2);
537                         VertexBuffer_set_attrib(vbo, pos_id, sides * 3 + 2, v3);
538                 }
539
540                 SHC.drw_single_arrow = Batch_create(PRIM_TRIANGLES, vbo, NULL);
541         }
542         return SHC.drw_single_arrow;
543 }
544
545 Batch *DRW_cache_empty_sphere_get(void)
546 {
547         if (!SHC.drw_empty_sphere) {
548                 VertexBuffer *vbo = sphere_wire_vbo(1.0f);
549                 SHC.drw_empty_sphere = Batch_create(PRIM_LINES, vbo, NULL);
550         }
551         return SHC.drw_empty_sphere;
552 }
553
554 Batch *DRW_cache_empty_cone_get(void)
555 {
556 #define NSEGMENTS 8
557         if (!SHC.drw_empty_cone) {
558                 /* a single ring of vertices */
559                 float p[NSEGMENTS][2];
560                 for (int i = 0; i < NSEGMENTS; ++i) {
561                         float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS);
562                         p[i][0] = cosf(angle);
563                         p[i][1] = sinf(angle);
564                 }
565
566                 /* Position Only 3D format */
567                 static VertexFormat format = { 0 };
568                 static unsigned int pos_id;
569                 if (format.attrib_ct == 0) {
570                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
571                 }
572
573                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
574                 VertexBuffer_allocate_data(vbo, NSEGMENTS * 4);
575
576                 for (int i = 0; i < NSEGMENTS; ++i) {
577                         float cv[2], v[3];
578                         cv[0] = p[(i) % NSEGMENTS][0];
579                         cv[1] = p[(i) % NSEGMENTS][1];
580
581                         /* cone sides */
582                         v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1];
583                         VertexBuffer_set_attrib(vbo, pos_id, i * 4, v);
584                         v[0] = 0.0f, v[1] = 2.0f, v[2] = 0.0f;
585                         VertexBuffer_set_attrib(vbo, pos_id, i * 4 + 1, v);
586
587                         /* end ring */
588                         v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1];
589                         VertexBuffer_set_attrib(vbo, pos_id, i * 4 + 2, v);
590                         cv[0] = p[(i + 1) % NSEGMENTS][0];
591                         cv[1] = p[(i + 1) % NSEGMENTS][1];
592                         v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1];
593                         VertexBuffer_set_attrib(vbo, pos_id, i * 4 + 3, v);
594                 }
595
596                 SHC.drw_empty_cone = Batch_create(PRIM_LINES, vbo, NULL);
597         }
598         return SHC.drw_empty_cone;
599 #undef NSEGMENTS
600 }
601
602 Batch *DRW_cache_arrows_get(void)
603 {
604         if (!SHC.drw_arrows) {
605                 VertexBuffer *vbo = fill_arrows_vbo(1.0f);
606
607                 SHC.drw_arrows = Batch_create(PRIM_LINES, vbo, NULL);
608         }
609         return SHC.drw_arrows;
610 }
611
612 Batch *DRW_cache_axis_names_get(void)
613 {
614         if (!SHC.drw_axis_names) {
615                 const float size = 0.1f;
616                 float v1[3], v2[3];
617
618                 /* Position Only 3D format */
619                 static VertexFormat format = { 0 };
620                 static unsigned int pos_id;
621                 if (format.attrib_ct == 0) {
622                         /* Using 3rd component as axis indicator */
623                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
624                 }
625
626                 /* Line */
627                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
628                 VertexBuffer_allocate_data(vbo, 14);
629
630                 /* X */
631                 copy_v3_fl3(v1, -size,  size, 0.0f);
632                 copy_v3_fl3(v2,  size, -size, 0.0f);
633                 VertexBuffer_set_attrib(vbo, pos_id, 0, v1);
634                 VertexBuffer_set_attrib(vbo, pos_id, 1, v2);
635
636                 copy_v3_fl3(v1,  size,  size, 0.0f);
637                 copy_v3_fl3(v2, -size, -size, 0.0f);
638                 VertexBuffer_set_attrib(vbo, pos_id, 2, v1);
639                 VertexBuffer_set_attrib(vbo, pos_id, 3, v2);
640
641                 /* Y */
642                 copy_v3_fl3(v1, -size + 0.25f * size,  size, 1.0f);
643                 copy_v3_fl3(v2,  0.0f,  0.0f, 1.0f);
644                 VertexBuffer_set_attrib(vbo, pos_id, 4, v1);
645                 VertexBuffer_set_attrib(vbo, pos_id, 5, v2);
646
647                 copy_v3_fl3(v1,  size - 0.25f * size,  size, 1.0f);
648                 copy_v3_fl3(v2, -size + 0.25f * size, -size, 1.0f);
649                 VertexBuffer_set_attrib(vbo, pos_id, 6, v1);
650                 VertexBuffer_set_attrib(vbo, pos_id, 7, v2);
651
652                 /* Z */
653                 copy_v3_fl3(v1, -size,  size, 2.0f);
654                 copy_v3_fl3(v2,  size,  size, 2.0f);
655                 VertexBuffer_set_attrib(vbo, pos_id, 8, v1);
656                 VertexBuffer_set_attrib(vbo, pos_id, 9, v2);
657
658                 copy_v3_fl3(v1,  size,  size, 2.0f);
659                 copy_v3_fl3(v2, -size, -size, 2.0f);
660                 VertexBuffer_set_attrib(vbo, pos_id, 10, v1);
661                 VertexBuffer_set_attrib(vbo, pos_id, 11, v2);
662
663                 copy_v3_fl3(v1, -size, -size, 2.0f);
664                 copy_v3_fl3(v2,  size, -size, 2.0f);
665                 VertexBuffer_set_attrib(vbo, pos_id, 12, v1);
666                 VertexBuffer_set_attrib(vbo, pos_id, 13, v2);
667
668                 SHC.drw_axis_names = Batch_create(PRIM_LINES, vbo, NULL);
669         }
670         return SHC.drw_axis_names;
671 }
672
673 /* Force Field */
674 Batch *DRW_cache_field_wind_get(void)
675 {
676 #define CIRCLE_RESOL 32
677         if (!SHC.drw_field_wind) {
678                 float v[3] = {0.0f, 0.0f, 0.0f};
679
680                 /* Position Only 3D format */
681                 static VertexFormat format = { 0 };
682                 static unsigned int pos_id;
683                 if (format.attrib_ct == 0) {
684                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
685                 }
686
687                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
688                 VertexBuffer_allocate_data(vbo, CIRCLE_RESOL * 2 * 4);
689
690                 for (int i = 0; i < 4; i++) {
691                         float z = 0.05f * (float)i;
692                         for (int a = 0; a < CIRCLE_RESOL; a++) {
693                                 v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
694                                 v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
695                                 v[2] = z;
696                                 VertexBuffer_set_attrib(vbo, pos_id, i * CIRCLE_RESOL * 2 + a * 2, v);
697
698                                 v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
699                                 v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
700                                 v[2] = z;
701                                 VertexBuffer_set_attrib(vbo, pos_id, i * CIRCLE_RESOL * 2 + a * 2 + 1, v);
702                         }
703                 }
704
705                 SHC.drw_field_wind = Batch_create(PRIM_LINES, vbo, NULL);
706         }
707         return SHC.drw_field_wind;
708 #undef CIRCLE_RESOL
709 }
710
711 Batch *DRW_cache_field_force_get(void)
712 {
713 #define CIRCLE_RESOL 32
714         if (!SHC.drw_field_force) {
715                 float v[3] = {0.0f, 0.0f, 0.0f};
716
717                 /* Position Only 3D format */
718                 static VertexFormat format = { 0 };
719                 static unsigned int pos_id;
720                 if (format.attrib_ct == 0) {
721                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
722                 }
723
724                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
725                 VertexBuffer_allocate_data(vbo, CIRCLE_RESOL * 2 * 3);
726
727                 for (int i = 0; i < 3; i++) {
728                         float radius = 1.0f + 0.5f * (float)i;
729                         for (int a = 0; a < CIRCLE_RESOL; a++) {
730                                 v[0] = radius * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
731                                 v[1] = radius * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
732                                 v[2] = 0.0f;
733                                 VertexBuffer_set_attrib(vbo, pos_id, i * CIRCLE_RESOL * 2 + a * 2, v);
734
735                                 v[0] = radius * sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
736                                 v[1] = radius * cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
737                                 v[2] = 0.0f;
738                                 VertexBuffer_set_attrib(vbo, pos_id, i * CIRCLE_RESOL * 2 + a * 2 + 1, v);
739                         }
740                 }
741
742                 SHC.drw_field_force = Batch_create(PRIM_LINES, vbo, NULL);
743         }
744         return SHC.drw_field_force;
745 #undef CIRCLE_RESOL
746 }
747
748 Batch *DRW_cache_field_vortex_get(void)
749 {
750 #define SPIRAL_RESOL 32
751         if (!SHC.drw_field_vortex) {
752                 float v[3] = {0.0f, 0.0f, 0.0f};
753                 unsigned int v_idx = 0;
754
755                 /* Position Only 3D format */
756                 static VertexFormat format = { 0 };
757                 static unsigned int pos_id;
758                 if (format.attrib_ct == 0) {
759                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
760                 }
761
762                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
763                 VertexBuffer_allocate_data(vbo, SPIRAL_RESOL * 2 + 1);
764
765                 for (int a = SPIRAL_RESOL; a > -1; a--) {
766                         v[0] = sinf((2.0f * M_PI * a) / ((float)SPIRAL_RESOL)) * (a / (float)SPIRAL_RESOL);
767                         v[1] = cosf((2.0f * M_PI * a) / ((float)SPIRAL_RESOL)) * (a / (float)SPIRAL_RESOL);
768
769                         VertexBuffer_set_attrib(vbo, pos_id, v_idx++, v);
770                 }
771
772                 for (int a = 1; a <= SPIRAL_RESOL; a++) {
773                         v[0] = -sinf((2.0f * M_PI * a) / ((float)SPIRAL_RESOL)) * (a / (float)SPIRAL_RESOL);
774                         v[1] = -cosf((2.0f * M_PI * a) / ((float)SPIRAL_RESOL)) * (a / (float)SPIRAL_RESOL);
775
776                         VertexBuffer_set_attrib(vbo, pos_id, v_idx++, v);
777                 }
778
779                 SHC.drw_field_vortex = Batch_create(PRIM_LINE_STRIP, vbo, NULL);
780         }
781         return SHC.drw_field_vortex;
782 #undef SPIRAL_RESOL
783 }
784
785 Batch *DRW_cache_field_tube_limit_get(void)
786 {
787 #define CIRCLE_RESOL 32
788         if (!SHC.drw_field_tube_limit) {
789                 float v[3] = {0.0f, 0.0f, 0.0f};
790                 unsigned int v_idx = 0;
791
792                 /* Position Only 3D format */
793                 static VertexFormat format = { 0 };
794                 static unsigned int pos_id;
795                 if (format.attrib_ct == 0) {
796                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
797                 }
798
799                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
800                 VertexBuffer_allocate_data(vbo, CIRCLE_RESOL * 2 * 2 + 8);
801
802                 /* Caps */
803                 for (int i = 0; i < 2; i++) {
804                         float z = (float)i * 2.0f - 1.0f;
805                         for (int a = 0; a < CIRCLE_RESOL; a++) {
806                                 v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
807                                 v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
808                                 v[2] = z;
809                                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, v);
810
811                                 v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
812                                 v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
813                                 v[2] = z;
814                                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, v);
815                         }
816                 }
817                 /* Side Edges */
818                 for (int a = 0; a < 4; a++) {
819                         for (int i = 0; i < 2; i++) {
820                                 float z = (float)i * 2.0f - 1.0f;
821                                 v[0] = sinf((2.0f * M_PI * a) / 4.0f);
822                                 v[1] = cosf((2.0f * M_PI * a) / 4.0f);
823                                 v[2] = z;
824                                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, v);
825                         }
826                 }
827
828                 SHC.drw_field_tube_limit = Batch_create(PRIM_LINES, vbo, NULL);
829         }
830         return SHC.drw_field_tube_limit;
831 #undef CIRCLE_RESOL
832 }
833
834 Batch *DRW_cache_field_cone_limit_get(void)
835 {
836 #define CIRCLE_RESOL 32
837         if (!SHC.drw_field_cone_limit) {
838                 float v[3] = {0.0f, 0.0f, 0.0f};
839                 unsigned int v_idx = 0;
840
841                 /* Position Only 3D format */
842                 static VertexFormat format = { 0 };
843                 static unsigned int pos_id;
844                 if (format.attrib_ct == 0) {
845                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
846                 }
847
848                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
849                 VertexBuffer_allocate_data(vbo, CIRCLE_RESOL * 2 * 2 + 8);
850
851                 /* Caps */
852                 for (int i = 0; i < 2; i++) {
853                         float z = (float)i * 2.0f - 1.0f;
854                         for (int a = 0; a < CIRCLE_RESOL; a++) {
855                                 v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
856                                 v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
857                                 v[2] = z;
858                                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, v);
859
860                                 v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
861                                 v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
862                                 v[2] = z;
863                                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, v);
864                         }
865                 }
866                 /* Side Edges */
867                 for (int a = 0; a < 4; a++) {
868                         for (int i = 0; i < 2; i++) {
869                                 float z = (float)i * 2.0f - 1.0f;
870                                 v[0] = z * sinf((2.0f * M_PI * a) / 4.0f);
871                                 v[1] = z * cosf((2.0f * M_PI * a) / 4.0f);
872                                 v[2] = z;
873                                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, v);
874                         }
875                 }
876
877                 SHC.drw_field_cone_limit = Batch_create(PRIM_LINES, vbo, NULL);
878         }
879         return SHC.drw_field_cone_limit;
880 #undef CIRCLE_RESOL
881 }
882
883 /* Lamps */
884 Batch *DRW_cache_lamp_get(void)
885 {
886 #define NSEGMENTS 8
887         if (!SHC.drw_lamp) {
888                 float v[2];
889
890                 /* Position Only 3D format */
891                 static VertexFormat format = { 0 };
892                 static unsigned int pos_id;
893                 if (format.attrib_ct == 0) {
894                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 2, KEEP_FLOAT);
895                 }
896
897                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
898                 VertexBuffer_allocate_data(vbo, NSEGMENTS * 2);
899
900                 for (int a = 0; a < NSEGMENTS; a++) {
901                         v[0] = sinf((2.0f * M_PI * a) / ((float)NSEGMENTS));
902                         v[1] = cosf((2.0f * M_PI * a) / ((float)NSEGMENTS));
903                         VertexBuffer_set_attrib(vbo, pos_id, a * 2, v);
904
905                         v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS));
906                         v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS));
907                         VertexBuffer_set_attrib(vbo, pos_id, a * 2 + 1, v);
908                 }
909
910                 SHC.drw_lamp = Batch_create(PRIM_LINES, vbo, NULL);
911         }
912         return SHC.drw_lamp;
913 #undef NSEGMENTS
914 }
915
916 Batch *DRW_cache_lamp_sunrays_get(void)
917 {
918         if (!SHC.drw_lamp_sunrays) {
919                 float v[2], v1[2], v2[2];
920
921                 /* Position Only 3D format */
922                 static VertexFormat format = { 0 };
923                 static unsigned int pos_id;
924                 if (format.attrib_ct == 0) {
925                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 2, KEEP_FLOAT);
926                 }
927
928                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
929                 VertexBuffer_allocate_data(vbo, 16);
930
931                 for (int a = 0; a < 8; a++) {
932                         v[0] = sinf((2.0f * M_PI * a) / 8.0f);
933                         v[1] = cosf((2.0f * M_PI * a) / 8.0f);
934
935                         mul_v2_v2fl(v1, v, 1.2f);
936                         mul_v2_v2fl(v2, v, 2.5f);
937
938                         VertexBuffer_set_attrib(vbo, pos_id, a * 2, v1);
939                         VertexBuffer_set_attrib(vbo, pos_id, a * 2 + 1, v2);
940                 }
941
942                 SHC.drw_lamp_sunrays = Batch_create(PRIM_LINES, vbo, NULL);
943         }
944         return SHC.drw_lamp_sunrays;
945 }
946
947 Batch *DRW_cache_lamp_area_get(void)
948 {
949         if (!SHC.drw_lamp_area) {
950                 float v1[3] = {0.0f, 0.0f, 0.0f};
951
952                 /* Position Only 3D format */
953                 static VertexFormat format = { 0 };
954                 static unsigned int pos_id;
955                 if (format.attrib_ct == 0) {
956                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
957                 }
958
959                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
960                 VertexBuffer_allocate_data(vbo, 8);
961
962                 v1[0] = v1[1] = 0.5f;
963                 VertexBuffer_set_attrib(vbo, pos_id, 0, v1);
964                 v1[0] = -0.5f;
965                 VertexBuffer_set_attrib(vbo, pos_id, 1, v1);
966                 VertexBuffer_set_attrib(vbo, pos_id, 2, v1);
967                 v1[1] = -0.5f;
968                 VertexBuffer_set_attrib(vbo, pos_id, 3, v1);
969                 VertexBuffer_set_attrib(vbo, pos_id, 4, v1);
970                 v1[0] = 0.5f;
971                 VertexBuffer_set_attrib(vbo, pos_id, 5, v1);
972                 VertexBuffer_set_attrib(vbo, pos_id, 6, v1);
973                 v1[1] = 0.5f;
974                 VertexBuffer_set_attrib(vbo, pos_id, 7, v1);
975
976                 SHC.drw_lamp_area = Batch_create(PRIM_LINES, vbo, NULL);
977         }
978         return SHC.drw_lamp_area;
979 }
980
981 Batch *DRW_cache_lamp_hemi_get(void)
982 {
983 #define CIRCLE_RESOL 32
984         if (!SHC.drw_lamp_hemi) {
985                 float v[3];
986                 int vidx = 0;
987
988                 /* Position Only 3D format */
989                 static VertexFormat format = { 0 };
990                 static unsigned int pos_id;
991                 if (format.attrib_ct == 0) {
992                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
993                 }
994
995                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
996                 VertexBuffer_allocate_data(vbo, CIRCLE_RESOL * 2 * 2 - 6 * 2 * 2);
997
998                 /* XZ plane */
999                 for (int a = 3; a < CIRCLE_RESOL / 2 - 3; a++) {
1000                         v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL) - M_PI / 2);
1001                         v[2] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL) - M_PI / 2) - 1.0f;
1002                         v[1] = 0.0f;
1003                         VertexBuffer_set_attrib(vbo, pos_id, vidx++, v);
1004
1005                         v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL) - M_PI / 2);
1006                         v[2] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL) - M_PI / 2) - 1.0f;
1007                         v[1] = 0.0f;
1008                         VertexBuffer_set_attrib(vbo, pos_id, vidx++, v);
1009                 }
1010
1011                 /* XY plane */
1012                 for (int a = 3; a < CIRCLE_RESOL / 2 - 3; a++) {
1013                         v[2] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)) - 1.0f;
1014                         v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
1015                         v[0] = 0.0f;
1016                         VertexBuffer_set_attrib(vbo, pos_id, vidx++, v);
1017
1018                         v[2] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL)) - 1.0f;
1019                         v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
1020                         v[0] = 0.0f;
1021                         VertexBuffer_set_attrib(vbo, pos_id, vidx++, v);
1022                 }
1023
1024                 /* YZ plane full circle */
1025                 /* lease v[2] as it is */
1026                 const float rad = cosf((2.0f * M_PI * 3) / ((float)CIRCLE_RESOL));
1027                 for (int a = 0; a < CIRCLE_RESOL; a++) {
1028                         v[1] = rad * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
1029                         v[0] = rad * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
1030                         VertexBuffer_set_attrib(vbo, pos_id, vidx++, v);
1031
1032                         v[1] = rad * sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
1033                         v[0] = rad * cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
1034                         VertexBuffer_set_attrib(vbo, pos_id, vidx++, v);
1035                 }
1036
1037
1038                 SHC.drw_lamp_hemi = Batch_create(PRIM_LINES, vbo, NULL);
1039         }
1040         return SHC.drw_lamp_hemi;
1041 #undef CIRCLE_RESOL
1042 }
1043
1044
1045 Batch *DRW_cache_lamp_spot_get(void)
1046 {
1047 #define NSEGMENTS 32
1048         if (!SHC.drw_lamp_spot) {
1049                 /* a single ring of vertices */
1050                 float p[NSEGMENTS][2];
1051                 float n[NSEGMENTS][3];
1052                 float neg[NSEGMENTS][3];
1053                 float half_angle = 2 * M_PI / ((float)NSEGMENTS * 2);
1054                 for (int i = 0; i < NSEGMENTS; ++i) {
1055                         float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS);
1056                         p[i][0] = cosf(angle);
1057                         p[i][1] = sinf(angle);
1058
1059                         n[i][0] = cosf(angle - half_angle);
1060                         n[i][1] = sinf(angle - half_angle);
1061                         n[i][2] = cosf(M_PI / 16.0f); /* slope of the cone */
1062                         normalize_v3(n[i]); /* necessary ? */
1063                         negate_v3_v3(neg[i], n[i]);
1064                 }
1065
1066                 /* Position Only 3D format */
1067                 static VertexFormat format = { 0 };
1068                 static unsigned int pos_id, n1_id, n2_id;
1069                 if (format.attrib_ct == 0) {
1070                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
1071                         n1_id = VertexFormat_add_attrib(&format, "N1", COMP_F32, 3, KEEP_FLOAT);
1072                         n2_id = VertexFormat_add_attrib(&format, "N2", COMP_F32, 3, KEEP_FLOAT);
1073                 }
1074
1075                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
1076                 VertexBuffer_allocate_data(vbo, NSEGMENTS * 4);
1077
1078                 for (int i = 0; i < NSEGMENTS; ++i) {
1079                         float cv[2], v[3];
1080                         cv[0] = p[i % NSEGMENTS][0];
1081                         cv[1] = p[i % NSEGMENTS][1];
1082
1083                         /* cone sides */
1084                         v[0] = cv[0], v[1] = cv[1], v[2] = -1.0f;
1085                         VertexBuffer_set_attrib(vbo, pos_id, i * 4, v);
1086                         v[0] = 0.0f, v[1] = 0.0f, v[2] = 0.0f;
1087                         VertexBuffer_set_attrib(vbo, pos_id, i * 4 + 1, v);
1088
1089                         VertexBuffer_set_attrib(vbo, n1_id, i * 4,     n[(i) % NSEGMENTS]);
1090                         VertexBuffer_set_attrib(vbo, n1_id, i * 4 + 1, n[(i) % NSEGMENTS]);
1091                         VertexBuffer_set_attrib(vbo, n2_id, i * 4,     n[(i+1) % NSEGMENTS]);
1092                         VertexBuffer_set_attrib(vbo, n2_id, i * 4 + 1, n[(i+1) % NSEGMENTS]);
1093
1094                         /* end ring */
1095                         v[0] = cv[0], v[1] = cv[1], v[2] = -1.0f;
1096                         VertexBuffer_set_attrib(vbo, pos_id, i * 4 + 2, v);
1097                         cv[0] = p[(i + 1) % NSEGMENTS][0];
1098                         cv[1] = p[(i + 1) % NSEGMENTS][1];
1099                         v[0] = cv[0], v[1] = cv[1], v[2] = -1.0f;
1100                         VertexBuffer_set_attrib(vbo, pos_id, i * 4 + 3, v);
1101
1102                         VertexBuffer_set_attrib(vbo, n1_id, i * 4 + 2, n[(i) % NSEGMENTS]);
1103                         VertexBuffer_set_attrib(vbo, n1_id, i * 4 + 3, n[(i) % NSEGMENTS]);
1104                         VertexBuffer_set_attrib(vbo, n2_id, i * 4 + 2, neg[(i) % NSEGMENTS]);
1105                         VertexBuffer_set_attrib(vbo, n2_id, i * 4 + 3, neg[(i) % NSEGMENTS]);
1106                 }
1107
1108                 SHC.drw_lamp_spot = Batch_create(PRIM_LINES, vbo, NULL);
1109         }
1110         return SHC.drw_lamp_spot;
1111 #undef NSEGMENTS
1112 }
1113
1114 Batch *DRW_cache_lamp_spot_square_get(void)
1115 {
1116         if (!SHC.drw_lamp_spot_square) {
1117                 float p[5][3] = {{ 0.0f,  0.0f,  0.0f},
1118                                  { 1.0f,  1.0f, -1.0f},
1119                                  { 1.0f, -1.0f, -1.0f},
1120                                  {-1.0f, -1.0f, -1.0f},
1121                                  {-1.0f,  1.0f, -1.0f}};
1122
1123                 unsigned int v_idx = 0;
1124
1125                 /* Position Only 3D format */
1126                 static VertexFormat format = { 0 };
1127                 static unsigned int pos_id;
1128                 if (format.attrib_ct == 0) {
1129                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
1130                 }
1131
1132                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
1133                 VertexBuffer_allocate_data(vbo, 16);
1134
1135                 /* piramid sides */
1136                 for (int i = 1; i <= 4; ++i) {
1137                         VertexBuffer_set_attrib(vbo, pos_id, v_idx++, p[0]);
1138                         VertexBuffer_set_attrib(vbo, pos_id, v_idx++, p[i]);
1139
1140                         VertexBuffer_set_attrib(vbo, pos_id, v_idx++, p[(i % 4)+1]);
1141                         VertexBuffer_set_attrib(vbo, pos_id, v_idx++, p[((i+1) % 4)+1]);
1142                 }
1143
1144                 SHC.drw_lamp_spot_square = Batch_create(PRIM_LINES, vbo, NULL);
1145         }
1146         return SHC.drw_lamp_spot_square;
1147 }
1148
1149 /* Speaker */
1150 Batch *DRW_cache_speaker_get(void)
1151 {
1152         if (!SHC.drw_speaker) {
1153                 float v[3];
1154                 const int segments = 16;
1155                 int vidx = 0;
1156
1157                 /* Position Only 3D format */
1158                 static VertexFormat format = { 0 };
1159                 static unsigned int pos_id;
1160                 if (format.attrib_ct == 0) {
1161                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
1162                 }
1163
1164                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
1165                 VertexBuffer_allocate_data(vbo, 3 * segments * 2 + 4 * 4);
1166
1167                 for (int j = 0; j < 3; j++) {
1168                         float z = 0.25f * j - 0.125f;
1169                         float r = (j == 0 ? 0.5f : 0.25f);
1170
1171                         copy_v3_fl3(v, r, 0.0f, z);
1172                         VertexBuffer_set_attrib(vbo, pos_id, vidx++, v);
1173                         for (int i = 1; i < segments; i++) {
1174                                 float x = cosf(2.f * (float)M_PI * i / segments) * r;
1175                                 float y = sinf(2.f * (float)M_PI * i / segments) * r;
1176                                 copy_v3_fl3(v, x, y, z);
1177                                 VertexBuffer_set_attrib(vbo, pos_id, vidx++, v);
1178                                 VertexBuffer_set_attrib(vbo, pos_id, vidx++, v);
1179                         }
1180                         copy_v3_fl3(v, r, 0.0f, z);
1181                         VertexBuffer_set_attrib(vbo, pos_id, vidx++, v);
1182                 }
1183
1184                 for (int j = 0; j < 4; j++) {
1185                         float x = (((j + 1) % 2) * (j - 1)) * 0.5f;
1186                         float y = ((j % 2) * (j - 2)) * 0.5f;
1187                         for (int i = 0; i < 3; i++) {
1188                                 if (i == 1) {
1189                                         x *= 0.5f;
1190                                         y *= 0.5f;
1191                                 }
1192
1193                                 float z = 0.25f * i - 0.125f;
1194                                 copy_v3_fl3(v, x, y, z);
1195                                 VertexBuffer_set_attrib(vbo, pos_id, vidx++, v);
1196                                 if (i == 1) {
1197                                         VertexBuffer_set_attrib(vbo, pos_id, vidx++, v);
1198                                 }
1199                         }
1200                 }
1201
1202                 SHC.drw_speaker = Batch_create(PRIM_LINES, vbo, NULL);
1203         }
1204         return SHC.drw_speaker;
1205 }
1206
1207 /* Armature bones */
1208 static const float bone_octahedral_verts[6][3] = {
1209         { 0.0f, 0.0f,  0.0f},
1210         { 0.1f, 0.1f,  0.1f},
1211         { 0.1f, 0.1f, -0.1f},
1212         {-0.1f, 0.1f, -0.1f},
1213         {-0.1f, 0.1f,  0.1f},
1214         { 0.0f, 1.0f,  0.0f}
1215 };
1216
1217 static const unsigned int bone_octahedral_wire[24] = {
1218         0, 1,  1, 5,  5, 3,  3, 0,
1219         0, 4,  4, 5,  5, 2,  2, 0,
1220         1, 2,  2, 3,  3, 4,  4, 1,
1221 };
1222
1223 /* aligned with bone_octahedral_wire
1224  * Contains adjacent normal index */
1225 static const unsigned int bone_octahedral_wire_adjacent_face[24] = {
1226         0, 3,  4, 7,  5, 6,  1, 2,
1227         2, 3,  6, 7,  4, 5,  0, 1,
1228         0, 4,  1, 5,  2, 6,  3, 7,
1229 };
1230
1231 static const unsigned int bone_octahedral_solid_tris[8][3] = {
1232         {2, 1, 0}, /* bottom */
1233         {3, 2, 0},
1234         {4, 3, 0},
1235         {1, 4, 0},
1236
1237         {5, 1, 2}, /* top */
1238         {5, 2, 3},
1239         {5, 3, 4},
1240         {5, 4, 1}
1241 };
1242
1243 /* aligned with bone_octahedral_solid_tris */
1244 static const float bone_octahedral_solid_normals[8][3] = {
1245         { M_SQRT1_2,   -M_SQRT1_2,    0.00000000f},
1246         {-0.00000000f, -M_SQRT1_2,   -M_SQRT1_2},
1247         {-M_SQRT1_2,   -M_SQRT1_2,    0.00000000f},
1248         { 0.00000000f, -M_SQRT1_2,    M_SQRT1_2},
1249         { 0.99388373f,  0.11043154f, -0.00000000f},
1250         { 0.00000000f,  0.11043154f, -0.99388373f},
1251         {-0.99388373f,  0.11043154f,  0.00000000f},
1252         { 0.00000000f,  0.11043154f,  0.99388373f}
1253 };
1254
1255 Batch *DRW_cache_bone_octahedral_get(void)
1256 {
1257         if (!SHC.drw_bone_octahedral) {
1258                 unsigned int v_idx = 0;
1259
1260                 static VertexFormat format = { 0 };
1261                 static unsigned int pos_id, nor_id;
1262                 if (format.attrib_ct == 0) {
1263                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
1264                         nor_id = VertexFormat_add_attrib(&format, "nor", COMP_F32, 3, KEEP_FLOAT);
1265                 }
1266
1267                 /* Vertices */
1268                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
1269                 VertexBuffer_allocate_data(vbo, 24);
1270
1271                 for (int i = 0; i < 8; i++) {
1272                         VertexBuffer_set_attrib(vbo, nor_id, v_idx, bone_octahedral_solid_normals[i]);
1273                         VertexBuffer_set_attrib(vbo, pos_id, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][0]]);
1274                         VertexBuffer_set_attrib(vbo, nor_id, v_idx, bone_octahedral_solid_normals[i]);
1275                         VertexBuffer_set_attrib(vbo, pos_id, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][1]]);
1276                         VertexBuffer_set_attrib(vbo, nor_id, v_idx, bone_octahedral_solid_normals[i]);
1277                         VertexBuffer_set_attrib(vbo, pos_id, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][2]]);
1278                 }
1279
1280                 SHC.drw_bone_octahedral = Batch_create(PRIM_TRIANGLES, vbo, NULL);
1281         }
1282         return SHC.drw_bone_octahedral;
1283 }
1284
1285 Batch *DRW_cache_bone_octahedral_wire_outline_get(void)
1286 {
1287         if (!SHC.drw_bone_octahedral_wire) {
1288                 unsigned int v_idx = 0;
1289
1290                 static VertexFormat format = { 0 };
1291                 static unsigned int pos_id, n1_id, n2_id;
1292                 if (format.attrib_ct == 0) {
1293                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
1294                         n1_id = VertexFormat_add_attrib(&format, "N1", COMP_F32, 3, KEEP_FLOAT);
1295                         n2_id = VertexFormat_add_attrib(&format, "N2", COMP_F32, 3, KEEP_FLOAT);
1296                 }
1297
1298                 /* Vertices */
1299                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
1300                 VertexBuffer_allocate_data(vbo, 12 * 2);
1301
1302                 for (int i = 0; i < 12; i++) {
1303                         const float *co1 = bone_octahedral_verts[bone_octahedral_wire[i * 2]];
1304                         const float *co2 = bone_octahedral_verts[bone_octahedral_wire[i * 2 + 1]];
1305                         const float *n1 = bone_octahedral_solid_normals[bone_octahedral_wire_adjacent_face[i * 2]];
1306                         const float *n2 = bone_octahedral_solid_normals[bone_octahedral_wire_adjacent_face[i * 2 + 1]];
1307                         add_fancy_edge(vbo, pos_id, n1_id, n2_id, &v_idx, co1, co2, n1, n2);
1308                 }
1309
1310                 SHC.drw_bone_octahedral_wire = Batch_create(PRIM_LINES, vbo, NULL);
1311         }
1312         return SHC.drw_bone_octahedral_wire;
1313 }
1314
1315 Batch *DRW_cache_bone_point_get(void)
1316 {
1317         if (!SHC.drw_bone_point) {
1318                 const int lon_res = 16;
1319                 const int lat_res = 8;
1320                 const float rad = 0.05f;
1321                 const float lon_inc = 2 * M_PI / lon_res;
1322                 const float lat_inc = M_PI / lat_res;
1323                 unsigned int v_idx = 0;
1324
1325                 static VertexFormat format = { 0 };
1326                 static unsigned int pos_id, nor_id;
1327                 if (format.attrib_ct == 0) {
1328                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
1329                         nor_id = VertexFormat_add_attrib(&format, "nor", COMP_F32, 3, KEEP_FLOAT);
1330                 }
1331
1332                 /* Vertices */
1333                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
1334                 VertexBuffer_allocate_data(vbo, (lat_res - 1) * lon_res * 6);
1335
1336                 float lon = 0.0f;
1337                 for (int i = 0; i < lon_res; i++, lon += lon_inc) {
1338                         float lat = 0.0f;
1339                         for (int j = 0; j < lat_res; j++, lat += lat_inc) {
1340                                 if (j != lat_res - 1) { /* Pole */
1341                                         add_lat_lon_vert(vbo, pos_id, nor_id, &v_idx, rad, lat + lat_inc, lon + lon_inc);
1342                                         add_lat_lon_vert(vbo, pos_id, nor_id, &v_idx, rad, lat + lat_inc, lon);
1343                                         add_lat_lon_vert(vbo, pos_id, nor_id, &v_idx, rad, lat,           lon);
1344                                 }
1345
1346                                 if (j != 0) { /* Pole */
1347                                         add_lat_lon_vert(vbo, pos_id, nor_id, &v_idx, rad, lat,           lon + lon_inc);
1348                                         add_lat_lon_vert(vbo, pos_id, nor_id, &v_idx, rad, lat + lat_inc, lon + lon_inc);
1349                                         add_lat_lon_vert(vbo, pos_id, nor_id, &v_idx, rad, lat,           lon);
1350                                 }
1351                         }
1352                 }
1353
1354                 SHC.drw_bone_point = Batch_create(PRIM_TRIANGLES, vbo, NULL);
1355         }
1356         return SHC.drw_bone_point;
1357 }
1358
1359 Batch *DRW_cache_bone_point_wire_outline_get(void)
1360 {
1361         if (!SHC.drw_bone_point_wire) {
1362                 VertexBuffer *vbo = sphere_wire_vbo(0.05f);
1363                 SHC.drw_bone_point_wire = Batch_create(PRIM_LINES, vbo, NULL);
1364         }
1365         return SHC.drw_bone_point_wire;
1366 }
1367
1368 Batch *DRW_cache_bone_arrows_get(void)
1369 {
1370         if (!SHC.drw_bone_arrows) {
1371                 VertexBuffer *vbo = fill_arrows_vbo(0.25f);
1372                 SHC.drw_bone_arrows = Batch_create(PRIM_LINES, vbo, NULL);
1373         }
1374         return SHC.drw_bone_arrows;
1375 }
1376
1377 /* Camera */
1378 Batch *DRW_cache_camera_get(void)
1379 {
1380         if (!SHC.drw_camera) {
1381                 float v0 = 0.0f; /* Center point */
1382                 float v1 = 1.0f; /* + X + Y */
1383                 float v2 = 2.0f; /* + X - Y */
1384                 float v3 = 3.0f; /* - X - Y */
1385                 float v4 = 4.0f; /* - X + Y */
1386                 float v5 = 5.0f; /* tria + X */
1387                 float v6 = 6.0f; /* tria - X */
1388                 float v7 = 7.0f; /* tria + Y */
1389                 int v_idx = 0;
1390
1391                 static VertexFormat format = { 0 };
1392                 static unsigned int pos_id;
1393                 if (format.attrib_ct == 0) {
1394                         /* use x coordinate to identify the vertex
1395                          * the vertex shader take care to place it
1396                          * appropriatelly */
1397                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 1, KEEP_FLOAT);
1398                 }
1399
1400                 /* Vertices */
1401                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
1402                 VertexBuffer_allocate_data(vbo, 22);
1403
1404                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v0);
1405                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v1);
1406
1407                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v0);
1408                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v2);
1409
1410                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v0);
1411                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v3);
1412
1413                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v0);
1414                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v4);
1415
1416                 /* camera frame */
1417                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v1);
1418                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v2);
1419
1420                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v2);
1421                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v3);
1422
1423                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v3);
1424                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v4);
1425
1426                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v4);
1427                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v1);
1428
1429                 /* tria */
1430                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v5);
1431                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v6);
1432
1433                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v6);
1434                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v7);
1435
1436                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v7);
1437                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v5);
1438
1439                 SHC.drw_camera = Batch_create(PRIM_LINES, vbo, NULL);
1440         }
1441         return SHC.drw_camera;
1442 }
1443
1444 Batch *DRW_cache_camera_tria_get(void)
1445 {
1446         if (!SHC.drw_camera_tria) {
1447                 float v5 = 5.0f; /* tria + X */
1448                 float v6 = 6.0f; /* tria - X */
1449                 float v7 = 7.0f; /* tria + Y */
1450                 int v_idx = 0;
1451
1452                 static VertexFormat format = { 0 };
1453                 static unsigned int pos_id;
1454                 if (format.attrib_ct == 0) {
1455                         /* use x coordinate to identify the vertex
1456                          * the vertex shader take care to place it
1457                          * appropriatelly */
1458                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 1, KEEP_FLOAT);
1459                 }
1460
1461                 /* Vertices */
1462                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
1463                 VertexBuffer_allocate_data(vbo, 6);
1464
1465                 /* tria */
1466                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v5);
1467                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v6);
1468                 VertexBuffer_set_attrib(vbo, pos_id, v_idx++, &v7);
1469
1470                 SHC.drw_camera_tria = Batch_create(PRIM_TRIANGLES, vbo, NULL);
1471         }
1472         return SHC.drw_camera_tria;
1473 }
1474
1475 /* Object Center */
1476 Batch *DRW_cache_single_vert_get(void)
1477 {
1478         if (!SHC.drw_single_vertice) {
1479                 float v1[3] = {0.0f, 0.0f, 0.0f};
1480
1481                 /* Position Only 3D format */
1482                 static VertexFormat format = { 0 };
1483                 static unsigned int pos_id;
1484                 if (format.attrib_ct == 0) {
1485                         pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
1486                 }
1487
1488                 VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
1489                 VertexBuffer_allocate_data(vbo, 1);
1490
1491                 VertexBuffer_set_attrib(vbo, pos_id, 0, v1);
1492
1493                 SHC.drw_single_vertice = Batch_create(PRIM_POINTS, vbo, NULL);
1494         }
1495         return SHC.drw_single_vertice;
1496 }
1497
1498 /* Meshes */
1499 void DRW_cache_wire_overlay_get(Object *ob, Batch **tris, Batch **ledges, Batch **lverts)
1500 {
1501         BLI_assert(ob->type == OB_MESH);
1502
1503         Mesh *me = ob->data;
1504
1505         *tris = BKE_mesh_batch_cache_get_overlay_triangles(me);
1506         *ledges = BKE_mesh_batch_cache_get_overlay_loose_edges(me);
1507         *lverts = BKE_mesh_batch_cache_get_overlay_loose_verts(me);
1508 }
1509
1510 Batch *DRW_cache_face_centers_get(Object *ob)
1511 {
1512         BLI_assert(ob->type == OB_MESH);
1513
1514         Mesh *me = ob->data;
1515
1516         return BKE_mesh_batch_cache_get_overlay_facedots(me);
1517 }
1518
1519 Batch *DRW_cache_wire_outline_get(Object *ob)
1520 {
1521         Batch *fancy_wire = NULL;
1522
1523         BLI_assert(ob->type == OB_MESH);
1524
1525         Mesh *me = ob->data;
1526         fancy_wire = BKE_mesh_batch_cache_get_fancy_edges(me);
1527
1528         return fancy_wire;
1529 }
1530
1531 Batch *DRW_cache_surface_get(Object *ob)
1532 {
1533         Batch *surface = NULL;
1534
1535         BLI_assert(ob->type == OB_MESH);
1536
1537         Mesh *me = ob->data;
1538         surface = BKE_mesh_batch_cache_get_triangles_with_normals(me);
1539
1540         return surface;
1541 }
1542
1543 Batch *DRW_cache_surface_verts_get(Object *ob)
1544 {
1545         Batch *surface = NULL;
1546
1547         BLI_assert(ob->type == OB_MESH);
1548
1549         Mesh *me = ob->data;
1550         surface = BKE_mesh_batch_cache_get_points_with_normals(me);
1551
1552         return surface;
1553 }
1554
1555 Batch *DRW_cache_verts_get(Object *ob)
1556 {
1557         Batch *surface = NULL;
1558
1559         BLI_assert(ob->type == OB_MESH);
1560
1561         Mesh *me = ob->data;
1562         surface = BKE_mesh_batch_cache_get_all_verts(me);
1563
1564         return surface;
1565 }
1566
1567 #if 0 /* TODO */
1568 struct Batch *DRW_cache_surface_material_get(Object *ob, int nr) {
1569         /* TODO */
1570         return NULL;
1571 }
1572 #endif