7d51e0eac757802981eeff28bd8af577aa825c42
[blender.git] / source / blender / editors / space_view3d / drawobject.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
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  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation, full recode and added functions
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/space_view3d/drawobject.c
27  *  \ingroup spview3d
28  */
29
30 #include "MEM_guardedalloc.h"
31
32 #include "DNA_camera_types.h"
33 #include "DNA_curve_types.h"
34 #include "DNA_constraint_types.h"  /* for drawing constraint */
35 #include "DNA_lamp_types.h"
36 #include "DNA_lattice_types.h"
37 #include "DNA_material_types.h"
38 #include "DNA_mesh_types.h"
39 #include "DNA_meta_types.h"
40 #include "DNA_rigidbody_types.h"
41 #include "DNA_scene_types.h"
42 #include "DNA_smoke_types.h"
43 #include "DNA_world_types.h"
44 #include "DNA_object_types.h"
45
46 #include "BLI_blenlib.h"
47 #include "BLI_math.h"
48
49 #include "BKE_anim.h"  /* for the where_on_path function */
50 #include "BKE_armature.h"
51 #include "BKE_camera.h"
52 #include "BKE_constraint.h"  /* for the get_constraint_target function */
53 #include "BKE_curve.h"
54 #include "BKE_DerivedMesh.h"
55 #include "BKE_deform.h"
56 #include "BKE_displist.h"
57 #include "BKE_font.h"
58 #include "BKE_global.h"
59 #include "BKE_image.h"
60 #include "BKE_key.h"
61 #include "BKE_lattice.h"
62 #include "BKE_main.h"
63 #include "BKE_mesh.h"
64 #include "BKE_material.h"
65 #include "BKE_mball.h"
66 #include "BKE_modifier.h"
67 #include "BKE_object.h"
68 #include "BKE_paint.h"
69 #include "BKE_particle.h"
70 #include "BKE_pointcache.h"
71 #include "BKE_scene.h"
72 #include "BKE_unit.h"
73 #include "BKE_tracking.h"
74
75 #include "BKE_editmesh.h"
76
77 #include "IMB_imbuf.h"
78 #include "IMB_imbuf_types.h"
79
80 #include "BIF_gl.h"
81 #include "BIF_glutil.h"
82
83 #include "GPU_draw.h"
84 #include "GPU_extensions.h"
85
86 #include "ED_mesh.h"
87 #include "ED_particle.h"
88 #include "ED_screen.h"
89 #include "ED_sculpt.h"
90 #include "ED_types.h"
91
92 #include "UI_resources.h"
93 #include "UI_interface_icons.h"
94
95 #include "WM_api.h"
96 #include "BLF_api.h"
97
98 #include "view3d_intern.h"  /* bad level include */
99
100 typedef enum eWireDrawMode {
101         OBDRAW_WIRE_OFF = 0,
102         OBDRAW_WIRE_ON = 1,
103         OBDRAW_WIRE_ON_DEPTH = 2
104 } eWireDrawMode;
105
106 typedef struct drawDMVerts_userData {
107         BMesh *bm;
108
109         BMVert *eve_act;
110         char sel;
111
112         /* cached theme values */
113         unsigned char th_editmesh_active[4];
114         unsigned char th_vertex_select[4];
115         unsigned char th_vertex[4];
116         unsigned char th_skin_root[4];
117         float th_vertex_size;
118
119         /* for skin node drawing */
120         int cd_vskin_offset;
121         float imat[4][4];
122 } drawDMVerts_userData;
123
124 typedef struct drawDMEdgesSel_userData {
125         BMesh *bm;
126
127         unsigned char *baseCol, *selCol, *actCol;
128         BMEdge *eed_act;
129 } drawDMEdgesSel_userData;
130
131 typedef struct drawDMFacesSel_userData {
132 #ifdef WITH_FREESTYLE
133         unsigned char *cols[4];
134 #else
135         unsigned char *cols[3];
136 #endif
137
138         DerivedMesh *dm;
139         BMesh *bm;
140
141         BMFace *efa_act;
142         int *orig_index_mf_to_mpoly;
143         int *orig_index_mp_to_orig;
144 } drawDMFacesSel_userData;
145
146 typedef struct drawDMNormal_userData {
147         BMesh *bm;
148         int uniform_scale;
149         float normalsize;
150         float tmat[3][3];
151         float imat[3][3];
152 } drawDMNormal_userData;
153
154 typedef struct bbsObmodeMeshVerts_userData {
155         void *offset;
156         MVert *mvert;
157 } bbsObmodeMeshVerts_userData;
158
159 typedef struct drawDMLayer_userData {
160         BMesh *bm;
161         int cd_layer_offset;
162 } drawDMLayer_userData;
163
164 static void draw_bounding_volume(Object *ob, char type);
165
166 static void drawcube_size(float size);
167 static void drawcircle_size(float size);
168 static void draw_empty_sphere(float size);
169 static void draw_empty_cone(float size);
170
171 static void ob_wire_color_blend_theme_id(const unsigned char ob_wire_col[4], const int theme_id, float fac)
172 {
173         float col_wire[3], col_bg[3], col[3];
174
175         rgb_uchar_to_float(col_wire, ob_wire_col);
176
177         UI_GetThemeColor3fv(theme_id, col_bg);
178         interp_v3_v3v3(col, col_bg, col_wire, fac);
179         glColor3fv(col);
180 }
181
182 /* this condition has been made more complex since editmode can draw textures */
183 static bool check_object_draw_texture(Scene *scene, View3D *v3d, const char drawtype)
184 {
185         /* texture and material draw modes */
186         if (ELEM(v3d->drawtype, OB_TEXTURE, OB_MATERIAL) && drawtype > OB_SOLID) {
187                 return true;
188         }
189
190         /* textured solid */
191         if ((v3d->drawtype == OB_SOLID) &&
192             (v3d->flag2 & V3D_SOLID_TEX) &&
193             (BKE_scene_use_new_shading_nodes(scene) == false))
194         {
195                 return true;
196         }
197         
198         if (v3d->flag2 & V3D_SHOW_SOLID_MATCAP) {
199                 return true;
200         }
201         
202         return false;
203 }
204
205 static bool check_object_draw_editweight(Mesh *me, DerivedMesh *finalDM)
206 {
207         if (me->drawflag & ME_DRAWEIGHT) {
208                 /* editmesh handles its own weight drawing */
209                 if (finalDM->type != DM_TYPE_EDITBMESH) {
210                         return true;
211                 }
212         }
213
214         return false;
215 }
216
217 static bool check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
218 {
219         if ((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0)
220                 return false;
221
222         if (G.f & G_BACKBUFSEL)
223                 return false;
224
225         if ((vd->flag & V3D_ZBUF_SELECT) == 0)
226                 return true;
227
228         /* if its drawing textures with zbuf sel, then don't draw dots */
229         if (dt == OB_TEXTURE && vd->drawtype == OB_TEXTURE)
230                 return false;
231
232         if ((vd->drawtype >= OB_SOLID) && (vd->flag2 & V3D_SOLID_TEX))
233                 return false;
234
235         return true;
236 }
237
238 /* ************************ */
239
240 /* check for glsl drawing */
241
242 bool draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt)
243 {
244         if (!GPU_glsl_support())
245                 return false;
246         if (G.f & G_PICKSEL)
247                 return false;
248         if (!check_object_draw_texture(scene, v3d, dt))
249                 return false;
250         if (ob == OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
251                 return false;
252         
253         if (v3d->flag2 & V3D_SHOW_SOLID_MATCAP)
254                 return true;
255         
256         if (BKE_scene_use_new_shading_nodes(scene))
257                 return false;
258         
259         return (scene->gm.matmode == GAME_MAT_GLSL) && (dt > OB_SOLID);
260 }
261
262 static bool check_alpha_pass(Base *base)
263 {
264         if (base->flag & OB_FROMDUPLI)
265                 return false;
266
267         if (G.f & G_PICKSEL)
268                 return false;
269
270         if (base->object->mode & OB_MODE_ALL_PAINT)
271                 return false;
272
273         return (base->object->dtx & OB_DRAWTRANSP);
274 }
275
276 /***/
277 static const unsigned int colortab[] = {
278         0x0, 0x403000, 0xFFFF88
279 };
280
281 /* ----------------- OpenGL Circle Drawing - Tables for Optimized Drawing Speed ------------------ */
282 /* 32 values of sin function (still same result!) */
283 #define CIRCLE_RESOL 32
284
285 static const float sinval[CIRCLE_RESOL] = {
286         0.00000000,
287         0.20129852,
288         0.39435585,
289         0.57126821,
290         0.72479278,
291         0.84864425,
292         0.93775213,
293         0.98846832,
294         0.99871650,
295         0.96807711,
296         0.89780453,
297         0.79077573,
298         0.65137248,
299         0.48530196,
300         0.29936312,
301         0.10116832,
302         -0.10116832,
303         -0.29936312,
304         -0.48530196,
305         -0.65137248,
306         -0.79077573,
307         -0.89780453,
308         -0.96807711,
309         -0.99871650,
310         -0.98846832,
311         -0.93775213,
312         -0.84864425,
313         -0.72479278,
314         -0.57126821,
315         -0.39435585,
316         -0.20129852,
317         0.00000000
318 };
319
320 /* 32 values of cos function (still same result!) */
321 static const float cosval[CIRCLE_RESOL] = {
322         1.00000000,
323         0.97952994,
324         0.91895781,
325         0.82076344,
326         0.68896691,
327         0.52896401,
328         0.34730525,
329         0.15142777,
330         -0.05064916,
331         -0.25065253,
332         -0.44039415,
333         -0.61210598,
334         -0.75875812,
335         -0.87434661,
336         -0.95413925,
337         -0.99486932,
338         -0.99486932,
339         -0.95413925,
340         -0.87434661,
341         -0.75875812,
342         -0.61210598,
343         -0.44039415,
344         -0.25065253,
345         -0.05064916,
346         0.15142777,
347         0.34730525,
348         0.52896401,
349         0.68896691,
350         0.82076344,
351         0.91895781,
352         0.97952994,
353         1.00000000
354 };
355
356 static void draw_xyz_wire(const float c[3], float size, int axis)
357 {
358         float v1[3] = {0.f, 0.f, 0.f}, v2[3] = {0.f, 0.f, 0.f};
359         float dim = size * 0.1f;
360         float dx[3], dy[3], dz[3];
361
362         dx[0] = dim; dx[1] = 0.f; dx[2] = 0.f;
363         dy[0] = 0.f; dy[1] = dim; dy[2] = 0.f;
364         dz[0] = 0.f; dz[1] = 0.f; dz[2] = dim;
365
366         switch (axis) {
367                 case 0:     /* x axis */
368                         glBegin(GL_LINES);
369                         
370                         /* bottom left to top right */
371                         sub_v3_v3v3(v1, c, dx);
372                         sub_v3_v3(v1, dy);
373                         add_v3_v3v3(v2, c, dx);
374                         add_v3_v3(v2, dy);
375                         
376                         glVertex3fv(v1);
377                         glVertex3fv(v2);
378                         
379                         /* top left to bottom right */
380                         mul_v3_fl(dy, 2.f);
381                         add_v3_v3(v1, dy);
382                         sub_v3_v3(v2, dy);
383                         
384                         glVertex3fv(v1);
385                         glVertex3fv(v2);
386                         
387                         glEnd();
388                         break;
389                 case 1:     /* y axis */
390                         glBegin(GL_LINES);
391                         
392                         /* bottom left to top right */
393                         mul_v3_fl(dx, 0.75f);
394                         sub_v3_v3v3(v1, c, dx);
395                         sub_v3_v3(v1, dy);
396                         add_v3_v3v3(v2, c, dx);
397                         add_v3_v3(v2, dy);
398                         
399                         glVertex3fv(v1);
400                         glVertex3fv(v2);
401                         
402                         /* top left to center */
403                         mul_v3_fl(dy, 2.f);
404                         add_v3_v3(v1, dy);
405                         copy_v3_v3(v2, c);
406                         
407                         glVertex3fv(v1);
408                         glVertex3fv(v2);
409                         
410                         glEnd();
411                         break;
412                 case 2:     /* z axis */
413                         glBegin(GL_LINE_STRIP);
414                         
415                         /* start at top left */
416                         sub_v3_v3v3(v1, c, dx);
417                         add_v3_v3v3(v1, c, dz);
418                         
419                         glVertex3fv(v1);
420                         
421                         mul_v3_fl(dx, 2.f);
422                         add_v3_v3(v1, dx);
423
424                         glVertex3fv(v1);
425                         
426                         mul_v3_fl(dz, 2.f);
427                         sub_v3_v3(v1, dx);
428                         sub_v3_v3(v1, dz);
429                         
430                         glVertex3fv(v1);
431                         
432                         add_v3_v3(v1, dx);
433                 
434                         glVertex3fv(v1);
435                         
436                         glEnd();
437                         break;
438         }
439         
440 }
441
442 void drawaxes(float size, char drawtype)
443 {
444         int axis;
445         float v1[3] = {0.0, 0.0, 0.0};
446         float v2[3] = {0.0, 0.0, 0.0};
447         float v3[3] = {0.0, 0.0, 0.0};
448         
449         switch (drawtype) {
450
451                 case OB_PLAINAXES:
452                         for (axis = 0; axis < 3; axis++) {
453                                 glBegin(GL_LINES);
454
455                                 v1[axis] = size;
456                                 v2[axis] = -size;
457                                 glVertex3fv(v1);
458                                 glVertex3fv(v2);
459
460                                 /* reset v1 & v2 to zero */
461                                 v1[axis] = v2[axis] = 0.0f;
462
463                                 glEnd();
464                         }
465                         break;
466                 case OB_SINGLE_ARROW:
467
468                         glBegin(GL_LINES);
469                         /* in positive z direction only */
470                         v1[2] = size;
471                         glVertex3fv(v1);
472                         glVertex3fv(v2);
473                         glEnd();
474
475                         /* square pyramid */
476                         glBegin(GL_TRIANGLES);
477
478                         v2[0] = size * 0.035f; v2[1] = size * 0.035f;
479                         v3[0] = size * -0.035f; v3[1] = size * 0.035f;
480                         v2[2] = v3[2] = size * 0.75f;
481
482                         for (axis = 0; axis < 4; axis++) {
483                                 if (axis % 2 == 1) {
484                                         v2[0] = -v2[0];
485                                         v3[1] = -v3[1];
486                                 }
487                                 else {
488                                         v2[1] = -v2[1];
489                                         v3[0] = -v3[0];
490                                 }
491
492                                 glVertex3fv(v1);
493                                 glVertex3fv(v2);
494                                 glVertex3fv(v3);
495
496                         }
497                         glEnd();
498
499                         break;
500                 case OB_CUBE:
501                         drawcube_size(size);
502                         break;
503
504                 case OB_CIRCLE:
505                         drawcircle_size(size);
506                         break;
507
508                 case OB_EMPTY_SPHERE:
509                         draw_empty_sphere(size);
510                         break;
511
512                 case OB_EMPTY_CONE:
513                         draw_empty_cone(size);
514                         break;
515
516                 case OB_ARROWS:
517                 default:
518                 {
519                         for (axis = 0; axis < 3; axis++) {
520                                 const int arrow_axis = (axis == 0) ? 1 : 0;
521
522                                 glBegin(GL_LINES);
523
524                                 v2[axis] = size;
525                                 glVertex3fv(v1);
526                                 glVertex3fv(v2);
527                                 
528                                 v1[axis] = size * 0.85f;
529                                 v1[arrow_axis] = -size * 0.08f;
530                                 glVertex3fv(v1);
531                                 glVertex3fv(v2);
532                                 
533                                 v1[arrow_axis] = size * 0.08f;
534                                 glVertex3fv(v1);
535                                 glVertex3fv(v2);
536
537                                 glEnd();
538                                 
539                                 v2[axis] += size * 0.125f;
540
541                                 draw_xyz_wire(v2, size, axis);
542
543
544                                 /* reset v1 & v2 to zero */
545                                 v1[arrow_axis] = v1[axis] = v2[axis] = 0.0f;
546                         }
547                         break;
548                 }
549         }
550 }
551
552
553 /* Function to draw an Image on a empty Object */
554 static void draw_empty_image(Object *ob, const short dflag, const unsigned char ob_wire_col[4])
555 {
556         Image *ima = (Image *)ob->data;
557         ImBuf *ibuf = BKE_image_acquire_ibuf(ima, ob->iuser, NULL);
558
559         float scale, ofs_x, ofs_y, sca_x, sca_y;
560         int ima_x, ima_y;
561
562         if (ibuf && (ibuf->rect == NULL) && (ibuf->rect_float != NULL)) {
563                 IMB_rect_from_float(ibuf);
564         }
565
566         /* Get the buffer dimensions so we can fallback to fake ones */
567         if (ibuf && ibuf->rect) {
568                 ima_x = ibuf->x;
569                 ima_y = ibuf->y;
570         }
571         else {
572                 ima_x = 1;
573                 ima_y = 1;
574         }
575
576         /* Get the image aspect even if the buffer is invalid */
577         if (ima) {
578                 if (ima->aspx > ima->aspy) {
579                         sca_x = 1.0f;
580                         sca_y = ima->aspy / ima->aspx;
581                 }
582                 else if (ima->aspx < ima->aspy) {
583                         sca_x = ima->aspx / ima->aspy;
584                         sca_y = 1.0f;
585                 }
586                 else {
587                         sca_x = 1.0f;
588                         sca_y = 1.0f;
589                 }
590         }
591         else {
592                 sca_x = 1.0f;
593                 sca_y = 1.0f;
594         }
595
596         /* Calculate the scale center based on objects origin */
597         ofs_x = ob->ima_ofs[0] * ima_x;
598         ofs_y = ob->ima_ofs[1] * ima_y;
599
600         glMatrixMode(GL_MODELVIEW);
601         glPushMatrix();
602
603         /* Make sure we are drawing at the origin */
604         glTranslatef(0.0f,  0.0f,  0.0f);
605
606         /* Calculate Image scale */
607         scale = (ob->empty_drawsize / max_ff((float)ima_x * sca_x, (float)ima_y * sca_y));
608
609         /* Set the object scale */
610         glScalef(scale * sca_x, scale * sca_y, 1.0f);
611
612         if (ibuf && ibuf->rect) {
613                 const bool use_clip = (U.glalphaclip != 1.0f);
614                 int zoomfilter = (U.gameflags & USER_DISABLE_MIPMAP ) ? GL_NEAREST : GL_LINEAR;
615                 /* Setup GL params */
616                 glEnable(GL_BLEND);
617                 glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA);
618
619                 if (use_clip) {
620                         glEnable(GL_ALPHA_TEST);
621                         glAlphaFunc(GL_GREATER, U.glalphaclip);
622                 }
623
624                 /* Use the object color and alpha */
625                 glColor4fv(ob->col);
626
627                 /* Draw the Image on the screen */
628                 glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_RGBA, GL_UNSIGNED_BYTE, zoomfilter, ibuf->rect);
629                 glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
630
631                 glDisable(GL_BLEND);
632
633                 if (use_clip) {
634                         glDisable(GL_ALPHA_TEST);
635                         glAlphaFunc(GL_GREATER, 0.0f);
636                 }
637         }
638
639         if ((dflag & DRAW_CONSTCOLOR) == 0) {
640                 glColor3ubv(ob_wire_col);
641         }
642
643         /* Calculate the outline vertex positions */
644         glBegin(GL_LINE_LOOP);
645         glVertex2f(ofs_x, ofs_y);
646         glVertex2f(ofs_x + ima_x, ofs_y);
647         glVertex2f(ofs_x + ima_x, ofs_y + ima_y);
648         glVertex2f(ofs_x, ofs_y + ima_y);
649         glEnd();
650
651
652         /* Reset GL settings */
653         glMatrixMode(GL_MODELVIEW);
654         glPopMatrix();
655
656         BKE_image_release_ibuf(ima, ibuf, NULL);
657 }
658
659 static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3], float rad, float tmat[4][4])
660 {
661         float vx[3], vy[3];
662         float *viter = (float *)verts;
663         unsigned int a;
664
665         mul_v3_v3fl(vx, tmat[0], rad);
666         mul_v3_v3fl(vy, tmat[1], rad);
667
668         for (a = 0; a < CIRCLE_RESOL; a++, viter += 3) {
669                 viter[0] = cent[0] + sinval[a] * vx[0] + cosval[a] * vy[0];
670                 viter[1] = cent[1] + sinval[a] * vx[1] + cosval[a] * vy[1];
671                 viter[2] = cent[2] + sinval[a] * vx[2] + cosval[a] * vy[2];
672         }
673 }
674
675 void drawcircball(int mode, const float cent[3], float rad, float tmat[4][4])
676 {
677         float verts[CIRCLE_RESOL][3];
678
679         circball_array_fill(verts, cent, rad, tmat);
680
681         glEnableClientState(GL_VERTEX_ARRAY);
682         glVertexPointer(3, GL_FLOAT, 0, verts);
683         glDrawArrays(mode, 0, CIRCLE_RESOL);
684         glDisableClientState(GL_VERTEX_ARRAY);
685 }
686
687 /* circle for object centers, special_color is for library or ob users */
688 static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], int selstate, int special_color)
689 {
690         const float size = ED_view3d_pixel_size(rv3d, co) * (float)U.obcenter_dia * 0.5f;
691         float verts[CIRCLE_RESOL][3];
692
693         /* using gldepthfunc guarantees that it does write z values,
694          * but not checks for it, so centers remain visible independent order of drawing */
695         if (v3d->zbuf) glDepthFunc(GL_ALWAYS);
696         glEnable(GL_BLEND);
697         
698         if (special_color) {
699                 if (selstate == ACTIVE || selstate == SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
700
701                 else glColor4ub(0x55, 0xCC, 0xCC, 155);
702         }
703         else {
704                 if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
705                 else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
706                 else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
707         }
708
709         circball_array_fill(verts, co, size, rv3d->viewinv);
710
711         /* enable vertex array */
712         glEnableClientState(GL_VERTEX_ARRAY);
713         glVertexPointer(3, GL_FLOAT, 0, verts);
714
715         /* 1. draw filled, blended polygon */
716         glDrawArrays(GL_POLYGON, 0, CIRCLE_RESOL);
717
718         /* 2. draw outline */
719         UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
720         glDrawArrays(GL_LINE_LOOP, 0, CIRCLE_RESOL);
721
722         /* finish up */
723         glDisableClientState(GL_VERTEX_ARRAY);
724
725         glDisable(GL_BLEND);
726
727         if (v3d->zbuf) glDepthFunc(GL_LEQUAL);
728 }
729
730 /* *********** text drawing for object/particles/armature ************* */
731 static ListBase CachedText[3];
732 static int CachedTextLevel = 0;
733
734 typedef struct ViewCachedString {
735         struct ViewCachedString *next, *prev;
736         float vec[3];
737         union {
738                 unsigned char ub[4];
739                 int pack;
740         } col;
741         short sco[2];
742         short xoffs;
743         short flag;
744         int str_len, pad;
745         /* str is allocated past the end */
746 } ViewCachedString;
747
748 void view3d_cached_text_draw_begin(void)
749 {
750         ListBase *strings = &CachedText[CachedTextLevel];
751         strings->first = strings->last = NULL;
752         CachedTextLevel++;
753 }
754
755 void view3d_cached_text_draw_add(const float co[3],
756                                  const char *str,
757                                  short xoffs, short flag,
758                                  const unsigned char col[4])
759 {
760         int alloc_len = strlen(str) + 1;
761         ListBase *strings = &CachedText[CachedTextLevel - 1];
762         /* TODO, replace with more efficient malloc, perhaps memarena per draw? */
763         ViewCachedString *vos = MEM_callocN(sizeof(ViewCachedString) + alloc_len, "ViewCachedString");
764
765         BLI_addtail(strings, vos);
766         copy_v3_v3(vos->vec, co);
767         copy_v4_v4_char((char *)vos->col.ub, (const char *)col);
768         vos->xoffs = xoffs;
769         vos->flag = flag;
770         vos->str_len = alloc_len - 1;
771
772         /* allocate past the end */
773         memcpy(++vos, str, alloc_len);
774 }
775
776 void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, float mat[4][4])
777 {
778         RegionView3D *rv3d = ar->regiondata;
779         ListBase *strings = &CachedText[CachedTextLevel - 1];
780         ViewCachedString *vos;
781         int tot = 0;
782         
783         /* project first and test */
784         for (vos = strings->first; vos; vos = vos->next) {
785                 if (mat && !(vos->flag & V3D_CACHE_TEXT_WORLDSPACE))
786                         mul_m4_v3(mat, vos->vec);
787
788                 if (ED_view3d_project_short_ex(ar,
789                                                (vos->flag & V3D_CACHE_TEXT_GLOBALSPACE) ? rv3d->persmat : rv3d->persmatob,
790                                                (vos->flag & V3D_CACHE_TEXT_LOCALCLIP) != 0,
791                                                vos->vec, vos->sco,
792                                                V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
793                 {
794                         tot++;
795                 }
796                 else {
797                         vos->sco[0] = IS_CLIPPED;
798                 }
799         }
800
801         if (tot) {
802                 int col_pack_prev = 0;
803
804 #if 0
805                 bglMats mats; /* ZBuffer depth vars */
806                 double ux, uy, uz;
807                 float depth;
808
809                 if (v3d->zbuf)
810                         bgl_get_mats(&mats);
811 #endif
812                 if (rv3d->rflag & RV3D_CLIPPING) {
813                         ED_view3d_clipping_disable();
814                 }
815
816                 glMatrixMode(GL_PROJECTION);
817                 glPushMatrix();
818                 glMatrixMode(GL_MODELVIEW);
819                 glPushMatrix();
820                 ED_region_pixelspace(ar);
821                 
822                 if (depth_write) {
823                         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
824                 }
825                 else {
826                         glDepthMask(0);
827                 }
828                 
829                 for (vos = strings->first; vos; vos = vos->next) {
830                         if (vos->sco[0] != IS_CLIPPED) {
831                                 const char *str = (char *)(vos + 1);
832
833                                 if (col_pack_prev != vos->col.pack) {
834                                         glColor3ubv(vos->col.ub);
835                                         col_pack_prev = vos->col.pack;
836                                 }
837
838                                 ((vos->flag & V3D_CACHE_TEXT_ASCII) ?
839                                  BLF_draw_default_ascii :
840                                  BLF_draw_default
841                                 )( (float)vos->sco[0] + vos->xoffs,
842                                    (float)vos->sco[1],
843                                    (depth_write) ? 0.0f : 2.0f,
844                                    str,
845                                    vos->str_len);
846                         }
847                 }
848                 
849                 if (depth_write) {
850                         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
851                 }
852                 else {
853                         glDepthMask(1);
854                 }
855                 
856                 glMatrixMode(GL_PROJECTION);
857                 glPopMatrix();
858                 glMatrixMode(GL_MODELVIEW);
859                 glPopMatrix();
860
861                 if (rv3d->rflag & RV3D_CLIPPING) {
862                         ED_view3d_clipping_enable();
863                 }
864         }
865         
866         if (strings->first)
867                 BLI_freelistN(strings);
868         
869         CachedTextLevel--;
870 }
871
872 /* ******************** primitive drawing ******************* */
873
874 /* draws a cube on given the scaling of the cube, assuming that
875  * all required matrices have been set (used for drawing empties)
876  */
877 static void drawcube_size(float size)
878 {
879         glBegin(GL_LINE_STRIP);
880         glVertex3f(-size, -size, -size); glVertex3f(-size, -size, size);
881         glVertex3f(-size, size, size); glVertex3f(-size, size, -size);
882
883         glVertex3f(-size, -size, -size); glVertex3f(size, -size, -size);
884         glVertex3f(size, -size, size); glVertex3f(size, size, size);
885
886         glVertex3f(size, size, -size); glVertex3f(size, -size, -size);
887         glEnd();
888
889         glBegin(GL_LINE_STRIP);
890         glVertex3f(-size, -size, size); glVertex3f(size, -size, size);
891         glEnd();
892
893         glBegin(GL_LINE_STRIP);
894         glVertex3f(-size, size, size); glVertex3f(size, size, size);
895         glEnd();
896
897         glBegin(GL_LINE_STRIP);
898         glVertex3f(-size, size, -size); glVertex3f(size, size, -size);
899         glEnd();
900 }
901
902 /* this is an unused (old) cube-drawing function based on a given size */
903 #if 0
904 static void drawcube_size(const float size[3])
905 {
906
907         glPushMatrix();
908         glScalef(size[0],  size[1],  size[2]);
909         
910
911         glBegin(GL_LINE_STRIP);
912         glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]);
913         glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[6]);
914         glVertex3fv(cube[7]); glVertex3fv(cube[4]);
915         glEnd();
916
917         glBegin(GL_LINE_STRIP);
918         glVertex3fv(cube[1]); glVertex3fv(cube[5]);
919         glEnd();
920
921         glBegin(GL_LINE_STRIP);
922         glVertex3fv(cube[2]); glVertex3fv(cube[6]);
923         glEnd();
924
925         glBegin(GL_LINE_STRIP);
926         glVertex3fv(cube[3]); glVertex3fv(cube[7]);
927         glEnd();
928         
929         glPopMatrix();
930 }
931 #endif
932
933 static void drawshadbuflimits(Lamp *la, float mat[4][4])
934 {
935         float sta[3], end[3], lavec[3];
936
937         negate_v3_v3(lavec, mat[2]);
938         normalize_v3(lavec);
939
940         madd_v3_v3v3fl(sta, mat[3], lavec, la->clipsta);
941         madd_v3_v3v3fl(end, mat[3], lavec, la->clipend);
942
943         glBegin(GL_LINE_STRIP);
944         glVertex3fv(sta);
945         glVertex3fv(end);
946         glEnd();
947
948         glPointSize(3.0);
949         bglBegin(GL_POINTS);
950         bglVertex3fv(sta);
951         bglVertex3fv(end);
952         bglEnd();
953         glPointSize(1.0);
954 }
955
956
957
958 static void spotvolume(float lvec[3], float vvec[3], const float inp)
959 {
960         /* camera is at 0,0,0 */
961         float temp[3], plane[3], mat1[3][3], mat2[3][3], mat3[3][3], mat4[3][3], q[4], co, si, angle;
962
963         normalize_v3(lvec);
964         normalize_v3(vvec);             /* is this the correct vector ? */
965
966         cross_v3_v3v3(temp, vvec, lvec);      /* equation for a plane through vvec en lvec */
967         cross_v3_v3v3(plane, lvec, temp);     /* a plane perpendicular to this, parrallel with lvec */
968
969         /* vectors are exactly aligned, use the X axis, this is arbitrary */
970         if (normalize_v3(plane) == 0.0f)
971                 plane[1] = 1.0f;
972
973         /* now we've got two equations: one of a cone and one of a plane, but we have
974          * three unknowns. We remove one unknown by rotating the plane to z=0 (the plane normal) */
975
976         /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
977         /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
978
979         /* translating this comment to english didnt really help me understanding the math! :-) (ton) */
980         
981         q[1] =  plane[1];
982         q[2] = -plane[0];
983         q[3] =  0;
984         normalize_v3(&q[1]);
985
986         angle = saacos(plane[2]) / 2.0f;
987         co = cosf(angle);
988         si = sqrtf(1 - co * co);
989
990         q[0] =  co;
991         q[1] *= si;
992         q[2] *= si;
993         q[3] =  0;
994
995         quat_to_mat3(mat1, q);
996
997         /* rotate lamp vector now over acos(inp) degrees */
998         copy_v3_v3(vvec, lvec);
999
1000         unit_m3(mat2);
1001         co = inp;
1002         si = sqrtf(1.0f - inp * inp);
1003
1004         mat2[0][0] =  co;
1005         mat2[1][0] = -si;
1006         mat2[0][1] =  si;
1007         mat2[1][1] =  co;
1008         mul_m3_m3m3(mat3, mat2, mat1);
1009
1010         mat2[1][0] =  si;
1011         mat2[0][1] = -si;
1012         mul_m3_m3m3(mat4, mat2, mat1);
1013         transpose_m3(mat1);
1014
1015         mul_m3_m3m3(mat2, mat1, mat3);
1016         mul_m3_v3(mat2, lvec);
1017         mul_m3_m3m3(mat2, mat1, mat4);
1018         mul_m3_v3(mat2, vvec);
1019
1020         return;
1021 }
1022
1023 static void draw_spot_cone(Lamp *la, float x, float z)
1024 {
1025         z = fabs(z);
1026
1027         glBegin(GL_TRIANGLE_FAN);
1028         glVertex3f(0.0f, 0.0f, -x);
1029
1030         if (la->mode & LA_SQUARE) {
1031                 glVertex3f(z, z, 0);
1032                 glVertex3f(-z, z, 0);
1033                 glVertex3f(-z, -z, 0);
1034                 glVertex3f(z, -z, 0);
1035                 glVertex3f(z, z, 0);
1036         }
1037         else {
1038                 float angle;
1039                 int a;
1040
1041                 for (a = 0; a < 33; a++) {
1042                         angle = a * M_PI * 2 / (33 - 1);
1043                         glVertex3f(z * cosf(angle), z * sinf(angle), 0);
1044                 }
1045         }
1046
1047         glEnd();
1048 }
1049
1050 static void draw_transp_spot_volume(Lamp *la, float x, float z)
1051 {
1052         glEnable(GL_CULL_FACE);
1053         glEnable(GL_BLEND);
1054         glDepthMask(0);
1055
1056         /* draw backside darkening */
1057         glCullFace(GL_FRONT);
1058
1059         glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
1060         glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
1061
1062         draw_spot_cone(la, x, z);
1063
1064         /* draw front side lighting */
1065         glCullFace(GL_BACK);
1066
1067         glBlendFunc(GL_ONE, GL_ONE);
1068         glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
1069
1070         draw_spot_cone(la, x, z);
1071
1072         /* restore state */
1073         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1074         glDisable(GL_BLEND);
1075         glDepthMask(1);
1076         glDisable(GL_CULL_FACE);
1077         glCullFace(GL_BACK);
1078 }
1079
1080 static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
1081                      const char dt, const short dflag, const unsigned char ob_wire_col[4])
1082 {
1083         Object *ob = base->object;
1084         const float pixsize = ED_view3d_pixel_size(rv3d, ob->obmat[3]);
1085         Lamp *la = ob->data;
1086         float vec[3], lvec[3], vvec[3], circrad, x, y, z;
1087         float lampsize;
1088         float imat[4][4];
1089
1090         unsigned char curcol[4];
1091         unsigned char col[4];
1092         /* cone can't be drawn for duplicated lamps, because duplilist would be freed to */
1093         /* the moment of view3d_draw_transp() call */
1094         const bool is_view = (rv3d->persp == RV3D_CAMOB && v3d->camera == base->object);
1095         const bool drawcone = ((dt > OB_WIRE) &&
1096                                !(G.f & G_PICKSEL) &&
1097                                (la->type == LA_SPOT) &&
1098                                (la->mode & LA_SHOW_CONE) &&
1099                                !(base->flag & OB_FROMDUPLI) &&
1100                                !is_view);
1101
1102         if (drawcone && !v3d->transp) {
1103                 /* in this case we need to draw delayed */
1104                 ED_view3d_after_add(&v3d->afterdraw_transp, base, dflag);
1105                 return;
1106         }
1107         
1108         /* we first draw only the screen aligned & fixed scale stuff */
1109         glPushMatrix();
1110         glLoadMatrixf(rv3d->viewmat);
1111
1112         /* lets calculate the scale: */
1113         lampsize = pixsize * ((float)U.obcenter_dia * 0.5f);
1114
1115         /* and view aligned matrix: */
1116         copy_m4_m4(imat, rv3d->viewinv);
1117         normalize_v3(imat[0]);
1118         normalize_v3(imat[1]);
1119
1120         /* lamp center */
1121         copy_v3_v3(vec, ob->obmat[3]);
1122
1123         if ((dflag & DRAW_CONSTCOLOR) == 0) {
1124                 /* for AA effects */
1125                 curcol[0] = ob_wire_col[0];
1126                 curcol[1] = ob_wire_col[1];
1127                 curcol[2] = ob_wire_col[2];
1128                 curcol[3] = 154;
1129                 glColor4ubv(curcol);
1130         }
1131
1132         if (lampsize > 0.0f) {
1133
1134                 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1135                         if (ob->id.us > 1) {
1136                                 if (ob == OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155);
1137                                 else glColor4ub(0x77, 0xCC, 0xCC, 155);
1138                         }
1139                 }
1140                 
1141                 /* Inner Circle */
1142                 glEnable(GL_BLEND);
1143                 drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
1144                 glDisable(GL_BLEND);
1145                 drawcircball(GL_POLYGON, vec, lampsize, imat);
1146                 
1147                 /* restore */
1148                 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1149                         if (ob->id.us > 1)
1150                                 glColor4ubv(curcol);
1151                 }
1152
1153                 /* Outer circle */
1154                 circrad = 3.0f * lampsize;
1155                 setlinestyle(3);
1156
1157                 drawcircball(GL_LINE_LOOP, vec, circrad, imat);
1158
1159                 /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
1160                 if (la->type != LA_HEMI) {
1161                         if ((la->mode & LA_SHAD_RAY) || ((la->mode & LA_SHAD_BUF) && (la->type == LA_SPOT))) {
1162                                 drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f * pixsize, imat);
1163                         }
1164                 }
1165         }
1166         else {
1167                 setlinestyle(3);
1168                 circrad = 0.0f;
1169         }
1170         
1171         /* draw the pretty sun rays */
1172         if (la->type == LA_SUN) {
1173                 float v1[3], v2[3], mat[3][3];
1174                 short axis;
1175                 
1176                 /* setup a 45 degree rotation matrix */
1177                 axis_angle_normalized_to_mat3(mat, imat[2], (float)M_PI / 4.0f);
1178
1179                 /* vectors */
1180                 mul_v3_v3fl(v1, imat[0], circrad * 1.2f);
1181                 mul_v3_v3fl(v2, imat[0], circrad * 2.5f);
1182                 
1183                 /* center */
1184                 glTranslatef(vec[0], vec[1], vec[2]);
1185                 
1186                 setlinestyle(3);
1187                 
1188                 glBegin(GL_LINES);
1189                 for (axis = 0; axis < 8; axis++) {
1190                         glVertex3fv(v1);
1191                         glVertex3fv(v2);
1192                         mul_m3_v3(mat, v1);
1193                         mul_m3_v3(mat, v2);
1194                 }
1195                 glEnd();
1196                 
1197                 glTranslatef(-vec[0], -vec[1], -vec[2]);
1198
1199         }
1200         
1201         if (la->type == LA_LOCAL) {
1202                 if (la->mode & LA_SPHERE) {
1203                         drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
1204                 }
1205         }
1206         
1207         glPopMatrix();  /* back in object space */
1208         zero_v3(vec);
1209         
1210         if (is_view) {
1211                 /* skip drawing extra info */
1212         }
1213         else if ((la->type == LA_SPOT) || (la->type == LA_YF_PHOTON)) {
1214
1215                 copy_v3_fl3(lvec, 0.0f, 0.0f, 1.0f);
1216                 copy_v3_fl3(vvec, rv3d->persmat[0][2], rv3d->persmat[1][2], rv3d->persmat[2][2]);
1217                 mul_mat3_m4_v3(ob->obmat, vvec);
1218
1219                 x = -la->dist;
1220                 y = cosf(la->spotsize * 0.5f);
1221                 z = x * sqrtf(1.0f - y * y);
1222
1223                 spotvolume(lvec, vvec, y);
1224                 mul_v3_fl(lvec, x);
1225                 mul_v3_fl(vvec, x);
1226
1227                 /* draw the angled sides of the cone */
1228                 glBegin(GL_LINE_STRIP);
1229                 glVertex3fv(vvec);
1230                 glVertex3fv(vec);
1231                 glVertex3fv(lvec);
1232                 glEnd();
1233                 
1234                 x *= y;
1235
1236                 /* draw the circle/square at the end of the cone */
1237                 glTranslatef(0.0, 0.0,  x);
1238                 if (la->mode & LA_SQUARE) {
1239                         float tvec[3];
1240                         float z_abs = fabs(z);
1241
1242                         tvec[0] = tvec[1] = z_abs;
1243                         tvec[2] = 0.0;
1244
1245                         glBegin(GL_LINE_LOOP);
1246                         glVertex3fv(tvec);
1247                         tvec[1] = -z_abs; /* neg */
1248                         glVertex3fv(tvec);
1249                         tvec[0] = -z_abs; /* neg */
1250                         glVertex3fv(tvec);
1251                         tvec[1] = z_abs; /* pos */
1252                         glVertex3fv(tvec);
1253                         glEnd();
1254                 }
1255                 else {
1256                         circ(0.0, 0.0, fabsf(z));
1257                 }
1258
1259                 /* draw the circle/square representing spotbl */
1260                 if (la->type == LA_SPOT) {
1261                         float spotblcirc = fabs(z) * (1 - pow(la->spotblend, 2));
1262                         /* hide line if it is zero size or overlaps with outer border,
1263                          * previously it adjusted to always to show it but that seems
1264                          * confusing because it doesn't show the actual blend size */
1265                         if (spotblcirc != 0 && spotblcirc != fabsf(z))
1266                                 circ(0.0, 0.0, spotblcirc);
1267                 }
1268
1269                 if (drawcone)
1270                         draw_transp_spot_volume(la, x, z);
1271
1272                 /* draw clip start, useful for wide cones where its not obvious where the start is */
1273                 glTranslatef(0.0, 0.0, -x);  /* reverse translation above */
1274                 if (la->type == LA_SPOT && (la->mode & LA_SHAD_BUF) ) {
1275                         float lvec_clip[3];
1276                         float vvec_clip[3];
1277                         float clipsta_fac = la->clipsta / -x;
1278
1279                         interp_v3_v3v3(lvec_clip, vec, lvec, clipsta_fac);
1280                         interp_v3_v3v3(vvec_clip, vec, vvec, clipsta_fac);
1281
1282                         glBegin(GL_LINE_STRIP);
1283                         glVertex3fv(lvec_clip);
1284                         glVertex3fv(vvec_clip);
1285                         glEnd();
1286                 }
1287                 /* Else, draw spot direction (using distance as end limit, same as for Area lamp). */
1288                 else {
1289                         glBegin(GL_LINE_STRIP);
1290                         glVertex3f(0.0, 0.0, -circrad);
1291                         glVertex3f(0.0, 0.0, -la->dist);
1292                         glEnd();
1293                 }
1294         }
1295         else if (ELEM(la->type, LA_HEMI, LA_SUN)) {
1296                 
1297                 /* draw the line from the circle along the dist */
1298                 glBegin(GL_LINE_STRIP);
1299                 vec[2] = -circrad;
1300                 glVertex3fv(vec);
1301                 vec[2] = -la->dist;
1302                 glVertex3fv(vec);
1303                 glEnd();
1304                 
1305                 if (la->type == LA_HEMI) {
1306                         /* draw the hemisphere curves */
1307                         short axis, steps, dir;
1308                         float outdist, zdist, mul;
1309                         zero_v3(vec);
1310                         outdist = 0.14; mul = 1.4; dir = 1;
1311                         
1312                         setlinestyle(4);
1313                         /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
1314                         for (axis = 0; axis < 4; axis++) {
1315                                 float v[3] = {0.0, 0.0, 0.0};
1316                                 zdist = 0.02;
1317                                 
1318                                 glBegin(GL_LINE_STRIP);
1319                                 
1320                                 for (steps = 0; steps < 6; steps++) {
1321                                         if (axis == 0 || axis == 1) {       /* x axis up, x axis down */
1322                                                 /* make the arcs start at the edge of the energy circle */
1323                                                 if (steps == 0) v[0] = dir * circrad;
1324                                                 else v[0] = v[0] + dir * (steps * outdist);
1325                                         }
1326                                         else if (axis == 2 || axis == 3) {      /* y axis up, y axis down */
1327                                                 /* make the arcs start at the edge of the energy circle */
1328                                                 v[1] = (steps == 0) ? (dir * circrad) : (v[1] + dir * (steps * outdist));
1329                                         }
1330
1331                                         v[2] = v[2] - steps * zdist;
1332                                         
1333                                         glVertex3fv(v);
1334                                         
1335                                         zdist = zdist * mul;
1336                                 }
1337                                 
1338                                 glEnd();
1339                                 /* flip the direction */
1340                                 dir = -dir;
1341                         }
1342                 }
1343         }
1344         else if (la->type == LA_AREA) {
1345                 setlinestyle(3);
1346                 if (la->area_shape == LA_AREA_SQUARE)
1347                         fdrawbox(-la->area_size * 0.5f, -la->area_size * 0.5f, la->area_size * 0.5f, la->area_size * 0.5f);
1348                 else if (la->area_shape == LA_AREA_RECT)
1349                         fdrawbox(-la->area_size * 0.5f, -la->area_sizey * 0.5f, la->area_size * 0.5f, la->area_sizey * 0.5f);
1350
1351                 glBegin(GL_LINE_STRIP);
1352                 glVertex3f(0.0, 0.0, -circrad);
1353                 glVertex3f(0.0, 0.0, -la->dist);
1354                 glEnd();
1355         }
1356         
1357         /* and back to viewspace */
1358         glPushMatrix();
1359         glLoadMatrixf(rv3d->viewmat);
1360         copy_v3_v3(vec, ob->obmat[3]);
1361
1362         setlinestyle(0);
1363         
1364         if ((la->type == LA_SPOT) && (la->mode & LA_SHAD_BUF) && (is_view == false)) {
1365                 drawshadbuflimits(la, ob->obmat);
1366         }
1367         
1368         UI_GetThemeColor4ubv(TH_LAMP, col);
1369         glColor4ubv(col);
1370
1371         glEnable(GL_BLEND);
1372         
1373         if (vec[2] > 0) vec[2] -= circrad;
1374         else vec[2] += circrad;
1375         
1376         glBegin(GL_LINE_STRIP);
1377         glVertex3fv(vec);
1378         vec[2] = 0;
1379         glVertex3fv(vec);
1380         glEnd();
1381         
1382         glPointSize(2.0);
1383         glBegin(GL_POINTS);
1384         glVertex3fv(vec);
1385         glEnd();
1386         glPointSize(1.0);
1387         
1388         glDisable(GL_BLEND);
1389         
1390         if ((dflag & DRAW_CONSTCOLOR) == 0) {
1391                 /* restore for drawing extra stuff */
1392                 glColor3ubv(ob_wire_col);
1393         }
1394         /* and finally back to org object space! */
1395         glPopMatrix();
1396 }
1397
1398 static void draw_limit_line(float sta, float end, const short dflag, unsigned int col)
1399 {
1400         glBegin(GL_LINES);
1401         glVertex3f(0.0, 0.0, -sta);
1402         glVertex3f(0.0, 0.0, -end);
1403         glEnd();
1404
1405         if (!(dflag & DRAW_PICKING)) {
1406                 glPointSize(3.0);
1407                 glBegin(GL_POINTS);
1408                 cpack(col);
1409                 glVertex3f(0.0, 0.0, -sta);
1410                 glVertex3f(0.0, 0.0, -end);
1411                 glEnd();
1412                 glPointSize(1.0);
1413         }
1414 }
1415
1416
1417 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
1418 /* qdn: now also enabled for Blender to set focus point for defocus composite node */
1419 static void draw_focus_cross(float dist, float size)
1420 {
1421         glBegin(GL_LINES);
1422         glVertex3f(-size, 0.f, -dist);
1423         glVertex3f(size, 0.f, -dist);
1424         glVertex3f(0.f, -size, -dist);
1425         glVertex3f(0.f, size, -dist);
1426         glEnd();
1427 }
1428
1429 #ifdef VIEW3D_CAMERA_BORDER_HACK
1430 unsigned char view3d_camera_border_hack_col[3];
1431 bool view3d_camera_border_hack_test = false;
1432 #endif
1433
1434 /* ****************** draw clip data *************** */
1435
1436 static void draw_bundle_sphere(void)
1437 {
1438         static GLuint displist = 0;
1439
1440         if (displist == 0) {
1441                 GLUquadricObj *qobj;
1442
1443                 displist = glGenLists(1);
1444                 glNewList(displist, GL_COMPILE);
1445
1446                 qobj = gluNewQuadric();
1447                 gluQuadricDrawStyle(qobj, GLU_FILL);
1448                 glShadeModel(GL_SMOOTH);
1449                 gluSphere(qobj, 0.05, 8, 8);
1450                 glShadeModel(GL_FLAT);
1451                 gluDeleteQuadric(qobj);
1452
1453                 glEndList();
1454         }
1455
1456         glCallList(displist);
1457 }
1458
1459 static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D *v3d,
1460                                                 MovieClip *clip, MovieTrackingObject *tracking_object,
1461                                                 const short dflag, const unsigned char ob_wire_col[4],
1462                                                 int *global_track_index, bool draw_selected)
1463 {
1464         MovieTracking *tracking = &clip->tracking;
1465         MovieTrackingTrack *track;
1466         float mat[4][4], imat[4][4];
1467         unsigned char col_unsel[4], col_sel[4];
1468         int tracknr = *global_track_index;
1469         ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
1470         float camera_size[3];
1471
1472         UI_GetThemeColor4ubv(TH_TEXT, col_unsel);
1473         UI_GetThemeColor4ubv(TH_SELECT, col_sel);
1474
1475         BKE_tracking_get_camera_object_matrix(scene, base->object, mat);
1476
1477         /* we're compensating camera size for bundles size,
1478          * to make it so bundles are always displayed with the same size
1479          */
1480         copy_v3_v3(camera_size, base->object->size);
1481         if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0)
1482                 mul_v3_fl(camera_size, tracking_object->scale);
1483
1484         glPushMatrix();
1485
1486         if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
1487                 /* current ogl matrix is translated in camera space, bundles should
1488                  * be rendered in world space, so camera matrix should be "removed"
1489                  * from current ogl matrix */
1490                 invert_m4_m4(imat, base->object->obmat);
1491
1492                 glMultMatrixf(imat);
1493                 glMultMatrixf(mat);
1494         }
1495         else {
1496                 float obmat[4][4];
1497
1498                 BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object, scene->r.cfra, obmat);
1499
1500                 invert_m4_m4(imat, obmat);
1501                 glMultMatrixf(imat);
1502         }
1503
1504         for (track = tracksbase->first; track; track = track->next) {
1505                 int selected = TRACK_SELECTED(track);
1506
1507                 if (draw_selected && !selected)
1508                         continue;
1509
1510                 if ((track->flag & TRACK_HAS_BUNDLE) == 0)
1511                         continue;
1512
1513                 if (dflag & DRAW_PICKING)
1514                         glLoadName(base->selcol + (tracknr << 16));
1515
1516                 glPushMatrix();
1517                 glTranslatef(track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]);
1518                 glScalef(v3d->bundle_size / 0.05f / camera_size[0],
1519                          v3d->bundle_size / 0.05f / camera_size[1],
1520                          v3d->bundle_size / 0.05f / camera_size[2]);
1521
1522                 if (v3d->drawtype == OB_WIRE) {
1523                         glDisable(GL_LIGHTING);
1524
1525                         if ((dflag & DRAW_CONSTCOLOR) == 0) {
1526                                 if (selected && (track->flag & TRACK_CUSTOMCOLOR) == 0) {
1527                                         glColor3ubv(ob_wire_col);
1528                                 }
1529                                 else {
1530                                         glColor3fv(track->color);
1531                                 }
1532                         }
1533
1534                         drawaxes(0.05f, v3d->bundle_drawtype);
1535
1536                         glEnable(GL_LIGHTING);
1537                 }
1538                 else if (v3d->drawtype > OB_WIRE) {
1539                         if (v3d->bundle_drawtype == OB_EMPTY_SPHERE) {
1540                                 /* selection outline */
1541                                 if (selected) {
1542                                         if ((dflag & DRAW_CONSTCOLOR) == 0) {
1543                                                 glColor3ubv(ob_wire_col);
1544                                         }
1545
1546                                         glLineWidth(2.f);
1547                                         glDisable(GL_LIGHTING);
1548                                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1549
1550                                         draw_bundle_sphere();
1551
1552                                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1553                                         glEnable(GL_LIGHTING);
1554                                         glLineWidth(1.f);
1555                                 }
1556
1557                                 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1558                                         if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1559                                         else UI_ThemeColor(TH_BUNDLE_SOLID);
1560                                 }
1561
1562                                 draw_bundle_sphere();
1563                         }
1564                         else {
1565                                 glDisable(GL_LIGHTING);
1566
1567                                 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1568                                         if (selected) {
1569                                                 glColor3ubv(ob_wire_col);
1570                                         }
1571                                         else {
1572                                                 if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1573                                                 else UI_ThemeColor(TH_WIRE);
1574                                         }
1575                                 }
1576
1577                                 drawaxes(0.05f, v3d->bundle_drawtype);
1578
1579                                 glEnable(GL_LIGHTING);
1580                         }
1581                 }
1582
1583                 glPopMatrix();
1584
1585                 if ((dflag & DRAW_PICKING) == 0 && (v3d->flag2 & V3D_SHOW_BUNDLENAME)) {
1586                         float pos[3];
1587
1588                         mul_v3_m4v3(pos, mat, track->bundle_pos);
1589                         view3d_cached_text_draw_add(pos, track->name, 10, V3D_CACHE_TEXT_GLOBALSPACE, selected ? col_sel : col_unsel);
1590                 }
1591
1592                 tracknr++;
1593         }
1594
1595         if ((dflag & DRAW_PICKING) == 0) {
1596                 if ((v3d->flag2 & V3D_SHOW_CAMERAPATH) && (tracking_object->flag & TRACKING_OBJECT_CAMERA)) {
1597                         MovieTrackingReconstruction *reconstruction;
1598                         reconstruction = BKE_tracking_object_get_reconstruction(tracking, tracking_object);
1599
1600                         if (reconstruction->camnr) {
1601                                 MovieReconstructedCamera *camera = reconstruction->cameras;
1602                                 int a = 0;
1603
1604                                 glDisable(GL_LIGHTING);
1605                                 UI_ThemeColor(TH_CAMERA_PATH);
1606                                 glLineWidth(2.0f);
1607
1608                                 glBegin(GL_LINE_STRIP);
1609                                 for (a = 0; a < reconstruction->camnr; a++, camera++) {
1610                                         glVertex3fv(camera->mat[3]);
1611                                 }
1612                                 glEnd();
1613
1614                                 glLineWidth(1.0f);
1615                                 glEnable(GL_LIGHTING);
1616                         }
1617                 }
1618         }
1619
1620         glPopMatrix();
1621
1622         *global_track_index = tracknr;
1623 }
1624
1625 static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, MovieClip *clip,
1626                                          const short dflag, const unsigned char ob_wire_col[4],
1627                                          const bool draw_selected)
1628 {
1629         MovieTracking *tracking = &clip->tracking;
1630         MovieTrackingObject *tracking_object;
1631         int global_track_index = 1;
1632
1633         if ((v3d->flag2 & V3D_SHOW_RECONSTRUCTION) == 0)
1634                 return;
1635
1636         if (v3d->flag2 & V3D_RENDER_OVERRIDE)
1637                 return;
1638
1639         glEnable(GL_LIGHTING);
1640         glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1641         glEnable(GL_COLOR_MATERIAL);
1642         glShadeModel(GL_SMOOTH);
1643
1644         tracking_object = tracking->objects.first;
1645         while (tracking_object) {
1646                 draw_viewport_object_reconstruction(scene, base, v3d, clip, tracking_object,
1647                                                     dflag, ob_wire_col, &global_track_index, draw_selected);
1648
1649                 tracking_object = tracking_object->next;
1650         }
1651
1652         /* restore */
1653         glShadeModel(GL_FLAT);
1654         glDisable(GL_COLOR_MATERIAL);
1655         glDisable(GL_LIGHTING);
1656
1657         if ((dflag & DRAW_CONSTCOLOR) == 0) {
1658                 glColor3ubv(ob_wire_col);
1659         }
1660
1661         if (dflag & DRAW_PICKING)
1662                 glLoadName(base->selcol);
1663 }
1664
1665 /* flag similar to draw_object() */
1666 static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
1667                        const short dflag, const unsigned char ob_wire_col[4])
1668 {
1669         /* a standing up pyramid with (0,0,0) as top */
1670         Camera *cam;
1671         Object *ob = base->object;
1672         float tvec[3];
1673         float vec[4][3], asp[2], shift[2], scale[3];
1674         int i;
1675         float drawsize;
1676         const bool is_view = (rv3d->persp == RV3D_CAMOB && ob == v3d->camera);
1677         MovieClip *clip = BKE_object_movieclip_get(scene, base->object, false);
1678
1679         /* draw data for movie clip set as active for scene */
1680         if (clip) {
1681                 draw_viewport_reconstruction(scene, base, v3d, clip, dflag, ob_wire_col, false);
1682                 draw_viewport_reconstruction(scene, base, v3d, clip, dflag, ob_wire_col, true);
1683         }
1684
1685 #ifdef VIEW3D_CAMERA_BORDER_HACK
1686         if (is_view && !(G.f & G_PICKSEL)) {
1687                 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1688                         view3d_camera_border_hack_col[0] = ob_wire_col[0];
1689                         view3d_camera_border_hack_col[1] = ob_wire_col[1];
1690                         view3d_camera_border_hack_col[2] = ob_wire_col[2];
1691                 }
1692                 else {
1693                         float col[4];
1694                         glGetFloatv(GL_CURRENT_COLOR, col);
1695                         rgb_float_to_uchar(view3d_camera_border_hack_col, col);
1696                 }
1697                 view3d_camera_border_hack_test = true;
1698                 return;
1699         }
1700 #endif
1701
1702         cam = ob->data;
1703
1704         scale[0] = 1.0f / len_v3(ob->obmat[0]);
1705         scale[1] = 1.0f / len_v3(ob->obmat[1]);
1706         scale[2] = 1.0f / len_v3(ob->obmat[2]);
1707
1708         BKE_camera_view_frame_ex(scene, cam, cam->drawsize, is_view, scale,
1709                                  asp, shift, &drawsize, vec);
1710
1711         glDisable(GL_LIGHTING);
1712         glDisable(GL_CULL_FACE);
1713
1714         /* camera frame */
1715         glBegin(GL_LINE_LOOP);
1716         glVertex3fv(vec[0]);
1717         glVertex3fv(vec[1]);
1718         glVertex3fv(vec[2]);
1719         glVertex3fv(vec[3]);
1720         glEnd();
1721
1722         if (is_view)
1723                 return;
1724
1725         zero_v3(tvec);
1726
1727         /* center point to camera frame */
1728         glBegin(GL_LINE_STRIP);
1729         glVertex3fv(vec[1]);
1730         glVertex3fv(tvec);
1731         glVertex3fv(vec[0]);
1732         glVertex3fv(vec[3]);
1733         glVertex3fv(tvec);
1734         glVertex3fv(vec[2]);
1735         glEnd();
1736
1737
1738         /* arrow on top */
1739         tvec[2] = vec[1][2]; /* copy the depth */
1740
1741
1742         /* draw an outline arrow for inactive cameras and filled
1743          * for active cameras. We actually draw both outline+filled
1744          * for active cameras so the wire can be seen side-on */
1745         for (i = 0; i < 2; i++) {
1746                 if (i == 0) glBegin(GL_LINE_LOOP);
1747                 else if (i == 1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1748                 else break;
1749
1750                 tvec[0] = shift[0] + ((-0.7f * drawsize) * scale[0]);
1751                 tvec[1] = shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]);
1752                 glVertex3fv(tvec); /* left */
1753                 
1754                 tvec[0] = shift[0] + ((0.7f * drawsize) * scale[0]);
1755                 glVertex3fv(tvec); /* right */
1756                 
1757                 tvec[0] = shift[0];
1758                 tvec[1] = shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]);
1759                 glVertex3fv(tvec); /* top */
1760
1761                 glEnd();
1762         }
1763
1764         if ((dflag & DRAW_SCENESET) == 0) {
1765                 if (cam->flag & (CAM_SHOWLIMITS | CAM_SHOWMIST)) {
1766                         float nobmat[4][4];
1767
1768                         /* draw in normalized object matrix space */
1769                         copy_m4_m4(nobmat, ob->obmat);
1770                         normalize_m4(nobmat);
1771
1772                         glPushMatrix();
1773                         glLoadMatrixf(rv3d->viewmat);
1774                         glMultMatrixf(nobmat);
1775
1776                         if (cam->flag & CAM_SHOWLIMITS) {
1777                                 draw_limit_line(cam->clipsta, cam->clipend, dflag, 0x77FFFF);
1778                                 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composite node */
1779                                 draw_focus_cross(BKE_camera_object_dof_distance(ob), cam->drawsize);
1780                         }
1781
1782                         if (cam->flag & CAM_SHOWMIST) {
1783                                 World *world = scene->world;
1784                                 if (world) {
1785                                         draw_limit_line(world->miststa, world->miststa + world->mistdist, dflag, 0xFFFFFF);
1786                                 }
1787                         }
1788                         glPopMatrix();
1789                 }
1790         }
1791 }
1792
1793 /* flag similar to draw_object() */
1794 static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D *UNUSED(rv3d),
1795                         Object *UNUSED(ob), int UNUSED(flag))
1796 {
1797         //Speaker *spk = ob->data;
1798
1799         float vec[3];
1800         int i, j;
1801
1802         glEnable(GL_BLEND);
1803
1804         for (j = 0; j < 3; j++) {
1805                 vec[2] = 0.25f * j - 0.125f;
1806
1807                 glBegin(GL_LINE_LOOP);
1808                 for (i = 0; i < 16; i++) {
1809                         vec[0] = cosf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1810                         vec[1] = sinf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1811                         glVertex3fv(vec);
1812                 }
1813                 glEnd();
1814         }
1815
1816         for (j = 0; j < 4; j++) {
1817                 vec[0] = (((j + 1) % 2) * (j - 1)) * 0.5f;
1818                 vec[1] = ((j % 2) * (j - 2)) * 0.5f;
1819                 glBegin(GL_LINE_STRIP);
1820                 for (i = 0; i < 3; i++) {
1821                         if (i == 1) {
1822                                 vec[0] *= 0.5f;
1823                                 vec[1] *= 0.5f;
1824                         }
1825
1826                         vec[2] = 0.25f * i - 0.125f;
1827                         glVertex3fv(vec);
1828                 }
1829                 glEnd();
1830         }
1831
1832         glDisable(GL_BLEND);
1833 }
1834
1835 static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short sel)
1836 {
1837         BPoint *bp = lt->def;
1838         float *co = dl ? dl->verts : NULL;
1839         int u, v, w;
1840
1841         const int color = sel ? TH_VERTEX_SELECT : TH_VERTEX;
1842         UI_ThemeColor(color);
1843
1844         glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1845         bglBegin(GL_POINTS);
1846
1847         for (w = 0; w < lt->pntsw; w++) {
1848                 int wxt = (w == 0 || w == lt->pntsw - 1);
1849                 for (v = 0; v < lt->pntsv; v++) {
1850                         int vxt = (v == 0 || v == lt->pntsv - 1);
1851                         for (u = 0; u < lt->pntsu; u++, bp++, co += 3) {
1852                                 int uxt = (u == 0 || u == lt->pntsu - 1);
1853                                 if (!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1854                                         if (bp->hide == 0) {
1855                                                 /* check for active BPoint and ensure selected */
1856                                                 if ((bp == actbp) && (bp->f1 & SELECT)) {
1857                                                         UI_ThemeColor(TH_LASTSEL_POINT);
1858                                                         bglVertex3fv(dl ? co : bp->vec);
1859                                                         UI_ThemeColor(color);
1860                                                 }
1861                                                 else if ((bp->f1 & SELECT) == sel) {
1862                                                         bglVertex3fv(dl ? co : bp->vec);
1863                                                 }
1864                                         }
1865                                 }
1866                         }
1867                 }
1868         }
1869         
1870         glPointSize(1.0);
1871         bglEnd();
1872 }
1873
1874 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int actdef_wcol)
1875 {
1876         int index = ((w * lt->pntsv + v) * lt->pntsu) + u;
1877
1878         if (actdef_wcol) {
1879                 float col[3];
1880                 MDeformWeight *mdw = defvert_find_index(lt->dvert + index, actdef_wcol - 1);
1881                 
1882                 weight_to_rgb(col, mdw ? mdw->weight : 0.0f);
1883                 glColor3fv(col);
1884
1885         }
1886         
1887         if (dl) {
1888                 glVertex3fv(&dl->verts[index * 3]);
1889         }
1890         else {
1891                 glVertex3fv(lt->def[index].vec);
1892         }
1893 }
1894
1895 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1896 static void drawlattice(View3D *v3d, Object *ob)
1897 {
1898         Lattice *lt = ob->data;
1899         DispList *dl;
1900         int u, v, w;
1901         int actdef_wcol = 0;
1902         const bool is_edit = (lt->editlatt != NULL);
1903
1904         dl = BKE_displist_find(&ob->curve_cache->disp, DL_VERTS);
1905         
1906         if (is_edit) {
1907                 lt = lt->editlatt->latt;
1908
1909                 UI_ThemeColor(TH_WIRE_EDIT);
1910                 
1911                 if (ob->defbase.first && lt->dvert) {
1912                         actdef_wcol = ob->actdef;
1913                         glShadeModel(GL_SMOOTH);
1914                 }
1915         }
1916         
1917         glBegin(GL_LINES);
1918         for (w = 0; w < lt->pntsw; w++) {
1919                 int wxt = (w == 0 || w == lt->pntsw - 1);
1920                 for (v = 0; v < lt->pntsv; v++) {
1921                         int vxt = (v == 0 || v == lt->pntsv - 1);
1922                         for (u = 0; u < lt->pntsu; u++) {
1923                                 int uxt = (u == 0 || u == lt->pntsu - 1);
1924
1925                                 if (w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1926                                         drawlattice__point(lt, dl, u, v, w - 1, actdef_wcol);
1927                                         drawlattice__point(lt, dl, u, v, w, actdef_wcol);
1928                                 }
1929                                 if (v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1930                                         drawlattice__point(lt, dl, u, v - 1, w, actdef_wcol);
1931                                         drawlattice__point(lt, dl, u, v, w, actdef_wcol);
1932                                 }
1933                                 if (u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1934                                         drawlattice__point(lt, dl, u - 1, v, w, actdef_wcol);
1935                                         drawlattice__point(lt, dl, u, v, w, actdef_wcol);
1936                                 }
1937                         }
1938                 }
1939         }
1940         glEnd();
1941         
1942         /* restoration for weight colors */
1943         if (actdef_wcol)
1944                 glShadeModel(GL_FLAT);
1945
1946         if (is_edit) {
1947                 BPoint *actbp = BKE_lattice_active_point_get(lt);
1948
1949                 if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
1950                 
1951                 lattice_draw_verts(lt, dl, actbp, 0);
1952                 lattice_draw_verts(lt, dl, actbp, 1);
1953                 
1954                 if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
1955         }
1956 }
1957
1958 /* ***************** ******************** */
1959
1960 /*  draw callback */
1961
1962 typedef struct drawDMVertSel_userData {
1963         MVert *mvert;
1964         int active;
1965         unsigned char *col[3];  /* (base, sel, act) */
1966         char sel_prev;
1967 } drawDMVertSel_userData;
1968
1969 static void drawSelectedVertices__mapFunc(void *userData, int index, const float co[3],
1970                                           const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
1971 {
1972         drawDMVertSel_userData *data = userData;
1973         MVert *mv = &data->mvert[index];
1974
1975         if (!(mv->flag & ME_HIDE)) {
1976                 const char sel = (index == data->active) ? 2 : (mv->flag & SELECT);
1977                 if (sel != data->sel_prev) {
1978                         glColor3ubv(data->col[sel]);
1979                         data->sel_prev = sel;
1980                 }
1981
1982                 glVertex3fv(co);
1983         }
1984 }
1985
1986 static void drawSelectedVertices(DerivedMesh *dm, Mesh *me)
1987 {
1988         drawDMVertSel_userData data;
1989
1990         /* TODO define selected color */
1991         unsigned char base_col[3] = {0x0, 0x0, 0x0};
1992         unsigned char sel_col[3] = {0xd8, 0xb8, 0x0};
1993         unsigned char act_col[3] = {0xff, 0xff, 0xff};
1994
1995         data.mvert = me->mvert;
1996         data.active = BKE_mesh_mselect_active_get(me, ME_VSEL);
1997         data.sel_prev = 0xff;
1998
1999         data.col[0] = base_col;
2000         data.col[1] = sel_col;
2001         data.col[2] = act_col;
2002
2003         glBegin(GL_POINTS);
2004         dm->foreachMappedVert(dm, drawSelectedVertices__mapFunc, &data, DM_FOREACH_NOP);
2005         glEnd();
2006 }
2007
2008 /* ************** DRAW MESH ****************** */
2009
2010 /* First section is all the "simple" draw routines,
2011  * ones that just pass some sort of primitive to GL,
2012  * with perhaps various options to control lighting,
2013  * color, etc.
2014  *
2015  * These routines should not have user interface related
2016  * logic!!!
2017  */
2018
2019 static void calcDrawDMNormalScale(Object *ob, drawDMNormal_userData *data)
2020 {
2021         float obmat[3][3];
2022
2023         copy_m3_m4(obmat, ob->obmat);
2024
2025         data->uniform_scale = is_uniform_scaled_m3(obmat);
2026
2027         if (!data->uniform_scale) {
2028                 /* inverted matrix */
2029                 invert_m3_m3(data->imat, obmat);
2030
2031                 /* transposed inverted matrix */
2032                 copy_m3_m3(data->tmat, data->imat);
2033                 transpose_m3(data->tmat);
2034         }
2035 }
2036
2037 static void draw_dm_face_normals__mapFunc(void *userData, int index, const float cent[3], const float no[3])
2038 {
2039         drawDMNormal_userData *data = userData;
2040         BMFace *efa = BM_face_at_index(data->bm, index);
2041         float n[3];
2042
2043         if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
2044                 if (!data->uniform_scale) {
2045                         mul_v3_m3v3(n, data->tmat, no);
2046                         normalize_v3(n);
2047                         mul_m3_v3(data->imat, n);
2048                 }
2049                 else {
2050                         copy_v3_v3(n, no);
2051                 }
2052
2053                 glVertex3fv(cent);
2054                 glVertex3f(cent[0] + n[0] * data->normalsize,
2055                            cent[1] + n[1] * data->normalsize,
2056                            cent[2] + n[2] * data->normalsize);
2057         }
2058 }
2059
2060 static void draw_dm_face_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm)
2061 {
2062         drawDMNormal_userData data;
2063
2064         data.bm = em->bm;
2065         data.normalsize = scene->toolsettings->normalsize;
2066
2067         calcDrawDMNormalScale(ob, &data);
2068
2069         glBegin(GL_LINES);
2070         dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, &data, DM_FOREACH_USE_NORMAL);
2071         glEnd();
2072 }
2073
2074 static void draw_dm_face_centers__mapFunc(void *userData, int index, const float cent[3], const float UNUSED(no[3]))
2075 {
2076         BMFace *efa = BM_face_at_index(((void **)userData)[0], index);
2077         const char sel = *(((char **)userData)[1]);
2078         
2079         if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) &&
2080             (BM_elem_flag_test(efa, BM_ELEM_SELECT) == sel))
2081         {
2082                 bglVertex3fv(cent);
2083         }
2084 }
2085 static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, char sel)
2086 {
2087         void *ptrs[2] = {em->bm, &sel};
2088
2089         bglBegin(GL_POINTS);
2090         dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, ptrs, DM_FOREACH_NOP);
2091         bglEnd();
2092 }
2093
2094 static void draw_dm_vert_normals__mapFunc(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3])
2095 {
2096         drawDMNormal_userData *data = userData;
2097         BMVert *eve = BM_vert_at_index(data->bm, index);
2098
2099         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
2100                 float no[3], n[3];
2101
2102                 if (no_f) {
2103                         copy_v3_v3(no, no_f);
2104                 }
2105                 else {
2106                         normal_short_to_float_v3(no, no_s);
2107                 }
2108
2109                 if (!data->uniform_scale) {
2110                         mul_v3_m3v3(n, data->tmat, no);
2111                         normalize_v3(n);
2112                         mul_m3_v3(data->imat, n);
2113                 }
2114                 else {
2115                         copy_v3_v3(n, no);
2116                 }
2117
2118                 glVertex3fv(co);
2119                 glVertex3f(co[0] + n[0] * data->normalsize,
2120                            co[1] + n[1] * data->normalsize,
2121                            co[2] + n[2] * data->normalsize);
2122         }
2123 }
2124
2125 static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm)
2126 {
2127         drawDMNormal_userData data;
2128
2129         data.bm = em->bm;
2130         data.normalsize = scene->toolsettings->normalsize;
2131
2132         calcDrawDMNormalScale(ob, &data);
2133
2134         glBegin(GL_LINES);
2135         dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, &data, DM_FOREACH_USE_NORMAL);
2136         glEnd();
2137 }
2138
2139 /* Draw verts with color set based on selection */
2140 static void draw_dm_verts__mapFunc(void *userData, int index, const float co[3],
2141                                    const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2142 {
2143         drawDMVerts_userData *data = userData;
2144         BMVert *eve = BM_vert_at_index(data->bm, index);
2145
2146         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->sel) {
2147                 /* skin nodes: draw a red circle around the root
2148                  * node(s) */
2149                 if (data->cd_vskin_offset != -1) {
2150                         const MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, data->cd_vskin_offset);
2151                         if (vs->flag & MVERT_SKIN_ROOT) {
2152                                 float radius = (vs->radius[0] + vs->radius[1]) * 0.5f;
2153                                 bglEnd();
2154                         
2155                                 glColor4ubv(data->th_skin_root);
2156                                 drawcircball(GL_LINES, co, radius, data->imat);
2157
2158                                 glColor4ubv(data->sel ? data->th_vertex_select : data->th_vertex);
2159                                 bglBegin(GL_POINTS);
2160                         }
2161                 }
2162
2163                 /* draw active larger - need to stop/start point drawing for this :/ */
2164                 if (eve == data->eve_act) {
2165                         glColor4ubv(data->th_editmesh_active);
2166                         
2167                         bglEnd();
2168                         
2169                         glPointSize(data->th_vertex_size);
2170                         bglBegin(GL_POINTS);
2171                         bglVertex3fv(co);
2172                         bglEnd();
2173
2174                         glColor4ubv(data->sel ? data->th_vertex_select : data->th_vertex);
2175                         glPointSize(data->th_vertex_size);
2176                         bglBegin(GL_POINTS);
2177                 }
2178                 else {
2179                         bglVertex3fv(co);
2180                 }
2181         }
2182 }
2183
2184 static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, const char sel, BMVert *eve_act,
2185                           RegionView3D *rv3d)
2186 {
2187         drawDMVerts_userData data;
2188         data.sel = sel;
2189         data.eve_act = eve_act;
2190         data.bm = em->bm;
2191
2192         /* Cache theme values */
2193         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, data.th_editmesh_active);
2194         UI_GetThemeColor4ubv(TH_VERTEX_SELECT, data.th_vertex_select);
2195         UI_GetThemeColor4ubv(TH_VERTEX, data.th_vertex);
2196         UI_GetThemeColor4ubv(TH_SKIN_ROOT, data.th_skin_root);
2197         data.th_vertex_size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2198
2199         /* For skin root drawing */
2200         data.cd_vskin_offset = CustomData_get_offset(&em->bm->vdata, CD_MVERT_SKIN);
2201         /* view-aligned matrix */
2202         mul_m4_m4m4(data.imat, rv3d->viewmat, em->ob->obmat);
2203         invert_m4(data.imat);
2204
2205         bglBegin(GL_POINTS);
2206         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data, DM_FOREACH_NOP);
2207         bglEnd();
2208 }
2209
2210 /* Draw edges with color set based on selection */
2211 static DMDrawOption draw_dm_edges_sel__setDrawOptions(void *userData, int index)
2212 {
2213         BMEdge *eed;
2214         //unsigned char **cols = userData, *col;
2215         drawDMEdgesSel_userData *data = userData;
2216         unsigned char *col;
2217
2218         eed = BM_edge_at_index(data->bm, index);
2219
2220         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
2221                 if (eed == data->eed_act) {
2222                         glColor4ubv(data->actCol);
2223                 }
2224                 else {
2225                         if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
2226                                 col = data->selCol;
2227                         }
2228                         else {
2229                                 col = data->baseCol;
2230                         }
2231                         /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode  */
2232                         if (col[3] == 0)
2233                                 return DM_DRAW_OPTION_SKIP;
2234                         
2235                         glColor4ubv(col);
2236                 }
2237                 return DM_DRAW_OPTION_NORMAL;
2238         }
2239         else {
2240                 return DM_DRAW_OPTION_SKIP;
2241         }
2242 }
2243 static void draw_dm_edges_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
2244                               unsigned char *selCol, unsigned char *actCol, BMEdge *eed_act)
2245 {
2246         drawDMEdgesSel_userData data;
2247         
2248         data.baseCol = baseCol;
2249         data.selCol = selCol;
2250         data.actCol = actCol;
2251         data.bm = em->bm;
2252         data.eed_act = eed_act;
2253         dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
2254 }
2255
2256 /* Draw edges */
2257 static DMDrawOption draw_dm_edges__setDrawOptions(void *userData, int index)
2258 {
2259         if (BM_elem_flag_test(BM_edge_at_index(userData, index), BM_ELEM_HIDDEN))
2260                 return DM_DRAW_OPTION_SKIP;
2261         else
2262                 return DM_DRAW_OPTION_NORMAL;
2263 }
2264
2265 static void draw_dm_edges(BMEditMesh *em, DerivedMesh *dm)
2266 {
2267         dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, em->bm);
2268 }
2269
2270 /* Draw edges with color interpolated based on selection */
2271 static DMDrawOption draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
2272 {
2273         if (BM_elem_flag_test(BM_edge_at_index(((void **)userData)[0], index), BM_ELEM_HIDDEN))
2274                 return DM_DRAW_OPTION_SKIP;
2275         else
2276                 return DM_DRAW_OPTION_NORMAL;
2277 }
2278 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
2279 {
2280         BMEdge *eed = BM_edge_at_index(((void **)userData)[0], index);
2281         unsigned char **cols = userData;
2282         unsigned char *col0 = cols[(BM_elem_flag_test(eed->v1, BM_ELEM_SELECT)) ? 2 : 1];
2283         unsigned char *col1 = cols[(BM_elem_flag_test(eed->v2, BM_ELEM_SELECT)) ? 2 : 1];
2284
2285         glColor4ub(col0[0] + (col1[0] - col0[0]) * t,
2286                    col0[1] + (col1[1] - col0[1]) * t,
2287                    col0[2] + (col1[2] - col0[2]) * t,
2288                    col0[3] + (col1[3] - col0[3]) * t);
2289 }
2290
2291 static void draw_dm_edges_sel_interp(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
2292 {
2293         void *cols[3] = {em->bm, baseCol, selCol};
2294
2295         dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
2296 }
2297
2298 /* Draw only seam edges */
2299 static DMDrawOption draw_dm_edges_seams__setDrawOptions(void *userData, int index)
2300 {
2301         BMEdge *eed = BM_edge_at_index(userData, index);
2302
2303         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BM_elem_flag_test(eed, BM_ELEM_SEAM))
2304                 return DM_DRAW_OPTION_NORMAL;
2305         else
2306                 return DM_DRAW_OPTION_SKIP;
2307 }
2308
2309 static void draw_dm_edges_seams(BMEditMesh *em, DerivedMesh *dm)
2310 {
2311         dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, em->bm);
2312 }
2313
2314 /* Draw only sharp edges */
2315 static DMDrawOption draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
2316 {
2317         BMEdge *eed = BM_edge_at_index(userData, index);
2318
2319         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && !BM_elem_flag_test(eed, BM_ELEM_SMOOTH))
2320                 return DM_DRAW_OPTION_NORMAL;
2321         else
2322                 return DM_DRAW_OPTION_SKIP;
2323 }
2324
2325 static void draw_dm_edges_sharp(BMEditMesh *em, DerivedMesh *dm)
2326 {
2327         dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, em->bm);
2328 }
2329
2330 #ifdef WITH_FREESTYLE
2331
2332 static int draw_dm_test_freestyle_edge_mark(BMesh *bm, BMEdge *eed)
2333 {
2334         FreestyleEdge *fed = CustomData_bmesh_get(&bm->edata, eed->head.data, CD_FREESTYLE_EDGE);
2335         if (!fed)
2336                 return 0;
2337         return (fed->flag & FREESTYLE_EDGE_MARK) != 0;
2338 }
2339
2340 /* Draw only Freestyle feature edges */
2341 static DMDrawOption draw_dm_edges_freestyle__setDrawOptions(void *userData, int index)
2342 {
2343         BMEdge *eed = BM_edge_at_index(userData, index);
2344
2345         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && draw_dm_test_freestyle_edge_mark(userData, eed))
2346                 return DM_DRAW_OPTION_NORMAL;
2347         else
2348                 return DM_DRAW_OPTION_SKIP;
2349 }
2350
2351 static void draw_dm_edges_freestyle(BMEditMesh *em, DerivedMesh *dm)
2352 {
2353         dm->drawMappedEdges(dm, draw_dm_edges_freestyle__setDrawOptions, em->bm);
2354 }
2355
2356 static int draw_dm_test_freestyle_face_mark(BMesh *bm, BMFace *efa)
2357 {
2358         FreestyleFace *ffa = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_FREESTYLE_FACE);
2359         if (!ffa)
2360                 return 0;
2361         return (ffa->flag & FREESTYLE_FACE_MARK) != 0;
2362 }
2363
2364 #endif
2365
2366 /* Draw faces with color set based on selection
2367  * return 2 for the active face so it renders with stipple enabled */
2368 static DMDrawOption draw_dm_faces_sel__setDrawOptions(void *userData, int index)
2369 {
2370         drawDMFacesSel_userData *data = userData;
2371         BMFace *efa = BM_face_at_index(data->bm, index);
2372         unsigned char *col;
2373         
2374         if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
2375                 if (efa == data->efa_act) {
2376                         glColor4ubv(data->cols[2]);
2377                         return DM_DRAW_OPTION_STIPPLE;
2378                 }
2379                 else {
2380 #ifdef WITH_FREESTYLE
2381                         col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : draw_dm_test_freestyle_face_mark(data->bm, efa) ? 3 : 0];
2382 #else
2383                         col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : 0];
2384 #endif
2385                         if (col[3] == 0)
2386                                 return DM_DRAW_OPTION_SKIP;
2387                         glColor4ubv(col);
2388                         return DM_DRAW_OPTION_NORMAL;
2389                 }
2390         }
2391         return DM_DRAW_OPTION_SKIP;
2392 }
2393
2394 static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index)
2395 {
2396
2397         drawDMFacesSel_userData *data = userData;
2398         int i;
2399         BMFace *efa;
2400         BMFace *next_efa;
2401
2402         unsigned char *col, *next_col;
2403
2404         if (!data->orig_index_mf_to_mpoly)
2405                 return 0;
2406
2407         i = DM_origindex_mface_mpoly(data->orig_index_mf_to_mpoly, data->orig_index_mp_to_orig, index);
2408         efa = (i != ORIGINDEX_NONE) ? BM_face_at_index(data->bm, i) : NULL;
2409         i = DM_origindex_mface_mpoly(data->orig_index_mf_to_mpoly, data->orig_index_mp_to_orig, next_index);
2410         next_efa = (i != ORIGINDEX_NONE) ? BM_face_at_index(data->bm, i) : NULL;
2411
2412         if (ELEM(NULL, efa, next_efa))
2413                 return 0;
2414
2415         if (efa == next_efa)
2416                 return 1;
2417
2418         if (efa == data->efa_act || next_efa == data->efa_act)
2419                 return 0;
2420
2421 #ifdef WITH_FREESTYLE
2422         col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : draw_dm_test_freestyle_face_mark(data->bm, efa) ? 3 : 0];
2423         next_col = data->cols[BM_elem_flag_test(next_efa, BM_ELEM_SELECT) ? 1 : draw_dm_test_freestyle_face_mark(data->bm, efa) ? 3 : 0];
2424 #else
2425         col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : 0];
2426         next_col = data->cols[BM_elem_flag_test(next_efa, BM_ELEM_SELECT) ? 1 : 0];
2427 #endif
2428
2429         if (col[3] == 0 || next_col[3] == 0)
2430                 return 0;
2431
2432         return col == next_col;
2433 }
2434
2435 /* also draws the active face */
2436 #ifdef WITH_FREESTYLE
2437 static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
2438                               unsigned char *selCol, unsigned char *actCol, unsigned char *markCol, BMFace *efa_act)
2439 #else
2440 static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
2441                               unsigned char *selCol, unsigned char *actCol, BMFace *efa_act)
2442 #endif
2443 {
2444         drawDMFacesSel_userData data;
2445         data.dm = dm;
2446         data.cols[0] = baseCol;
2447         data.bm = em->bm;
2448         data.cols[1] = selCol;
2449         data.cols[2] = actCol;
2450 #ifdef WITH_FREESTYLE
2451         data.cols[3] = markCol;
2452 #endif
2453         data.efa_act = efa_act;
2454         /* double lookup */
2455         data.orig_index_mf_to_mpoly = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
2456         data.orig_index_mp_to_orig  = DM_get_poly_data_layer(dm, CD_ORIGINDEX);
2457         if ((data.orig_index_mf_to_mpoly && data.orig_index_mp_to_orig) == false) {
2458                 data.orig_index_mf_to_mpoly = data.orig_index_mp_to_orig = NULL;
2459         }
2460
2461         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions, &data, 0);
2462 }
2463
2464 static DMDrawOption draw_dm_creases__setDrawOptions(void *userData, int index)
2465 {
2466         drawDMLayer_userData *data = userData;
2467         BMesh *bm = data->bm;
2468         BMEdge *eed = BM_edge_at_index(bm, index);
2469         
2470         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
2471                 const float crease = BM_ELEM_CD_GET_FLOAT(eed, data->cd_layer_offset);
2472                 if (crease != 0.0f) {
2473                         UI_ThemeColorBlend(TH_WIRE_EDIT, TH_EDGE_CREASE, crease);
2474                         return DM_DRAW_OPTION_NORMAL;
2475                 }
2476         }
2477         return DM_DRAW_OPTION_SKIP;
2478 }
2479 static void draw_dm_creases(BMEditMesh *em, DerivedMesh *dm)
2480 {
2481         drawDMLayer_userData data;
2482
2483         data.bm = em->bm;
2484         data.cd_layer_offset = CustomData_get_offset(&em->bm->edata, CD_CREASE);
2485
2486         if (data.cd_layer_offset != -1) {
2487                 glLineWidth(3.0);
2488                 dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, &data);
2489                 glLineWidth(1.0);
2490         }
2491 }
2492
2493 static DMDrawOption draw_dm_bweights__setDrawOptions(void *userData, int index)
2494 {
2495         drawDMLayer_userData *data = userData;
2496         BMesh *bm = data->bm;
2497         BMEdge *eed = BM_edge_at_index(bm, index);
2498
2499         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
2500                 const float bweight = BM_ELEM_CD_GET_FLOAT(eed, data->cd_layer_offset);
2501                 if (bweight != 0.0f) {
2502                         UI_ThemeColorBlend(TH_WIRE_EDIT, TH_EDGE_SELECT, bweight);
2503                         return DM_DRAW_OPTION_NORMAL;
2504                 }
2505         }
2506         return DM_DRAW_OPTION_SKIP;
2507 }
2508 static void draw_dm_bweights__mapFunc(void *userData, int index, const float co[3],
2509                                       const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2510 {
2511         drawDMLayer_userData *data = userData;
2512         BMesh *bm = data->bm;
2513         BMVert *eve = BM_vert_at_index(bm, index);
2514
2515         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
2516                 const float bweight = BM_ELEM_CD_GET_FLOAT(eve, data->cd_layer_offset);
2517                 if (bweight != 0.0f) {
2518                         UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, bweight);
2519                         bglVertex3fv(co);
2520                 }
2521         }
2522 }
2523 static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
2524 {
2525         ToolSettings *ts = scene->toolsettings;
2526
2527         if (ts->selectmode & SCE_SELECT_VERTEX) {
2528                 drawDMLayer_userData data;
2529
2530                 data.bm = em->bm;
2531                 data.cd_layer_offset = CustomData_get_offset(&em->bm->vdata, CD_BWEIGHT);
2532
2533                 if (data.cd_layer_offset != -1) {
2534                         glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2535                         bglBegin(GL_POINTS);
2536                         dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, &data, DM_FOREACH_NOP);
2537                         bglEnd();
2538                 }
2539         }
2540         else {
2541                 drawDMLayer_userData data;
2542
2543                 data.bm = em->bm;
2544                 data.cd_layer_offset = CustomData_get_offset(&em->bm->edata, CD_BWEIGHT);
2545
2546                 if (data.cd_layer_offset != -1) {
2547                         glLineWidth(3.0);
2548                         dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, &data);
2549                         glLineWidth(1.0);
2550                 }
2551         }
2552 }
2553
2554 static int draw_dm_override_material_color(int UNUSED(nr), void *UNUSED(attribs))
2555 {
2556         return 1;
2557 }
2558
2559 /* Second section of routines: Combine first sets to form fancy
2560  * drawing routines (for example rendering twice to get overlays).
2561  *
2562  * Also includes routines that are basic drawing but are too
2563  * specialized to be split out (like drawing creases or measurements).
2564  */
2565
2566 /* EditMesh drawing routines*/
2567
2568 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit,
2569                                 BMEditMesh *em, DerivedMesh *cageDM, BMVert *eve_act,
2570                                 RegionView3D *rv3d)
2571 {
2572         ToolSettings *ts = scene->toolsettings;
2573         int sel;
2574
2575         if (v3d->zbuf) glDepthMask(0);  /* disable write in zbuffer, zbuf select */
2576
2577         for (sel = 0; sel < 2; sel++) {
2578                 unsigned char col[4], fcol[4];
2579                 int pass;
2580
2581                 UI_GetThemeColor3ubv(sel ? TH_VERTEX_SELECT : TH_VERTEX, col);
2582                 UI_GetThemeColor3ubv(sel ? TH_FACE_DOT : TH_WIRE_EDIT, fcol);
2583
2584                 for (pass = 0; pass < 2; pass++) {
2585                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2586                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2587
2588                         if (pass == 0) {
2589                                 if (v3d->zbuf && !(v3d->flag & V3D_ZBUF_SELECT)) {
2590                                         glDisable(GL_DEPTH_TEST);
2591
2592                                         glEnable(GL_BLEND);
2593                                 }
2594                                 else {
2595                                         continue;
2596                                 }
2597
2598                                 size = (size > 2.1f ? size / 2.0f : size);
2599                                 fsize = (fsize > 2.1f ? fsize / 2.0f : fsize);
2600                                 col[3] = fcol[3] = 100;
2601                         }
2602                         else {
2603                                 col[3] = fcol[3] = 255;
2604                         }
2605
2606                         if (ts->selectmode & SCE_SELECT_VERTEX) {
2607                                 glPointSize(size);
2608                                 glColor4ubv(col);
2609                                 draw_dm_verts(em, cageDM, sel, eve_act, rv3d);
2610                         }
2611                         
2612                         if (check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2613                                 glPointSize(fsize);
2614                                 glColor4ubv(fcol);
2615                                 draw_dm_face_centers(em, cageDM, sel);
2616                         }
2617                         
2618                         if (pass == 0) {
2619                                 glDisable(GL_BLEND);
2620                                 glEnable(GL_DEPTH_TEST);
2621                         }
2622                 }
2623         }
2624
2625         if (v3d->zbuf) glDepthMask(1);
2626         glPointSize(1.0);
2627 }
2628
2629 static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d,
2630                                 Mesh *me, DerivedMesh *cageDM, short sel_only,
2631                                 BMEdge *eed_act)
2632 {
2633         ToolSettings *ts = scene->toolsettings;
2634         int pass;
2635         unsigned char wireCol[4], selCol[4], actCol[4];
2636
2637         /* since this function does transparent... */
2638         UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2639         UI_GetThemeColor4ubv(TH_WIRE_EDIT, wireCol);
2640         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2641         
2642         /* when sel only is used, don't render wire, only selected, this is used for
2643          * textured draw mode when the 'edges' option is disabled */
2644         if (sel_only)
2645                 wireCol[3] = 0;
2646
2647         for (pass = 0; pass < 2; pass++) {
2648                 /* show wires in transparent when no zbuf clipping for select */
2649                 if (pass == 0) {
2650                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT) == 0) {
2651                                 glEnable(GL_BLEND);
2652                                 glDisable(GL_DEPTH_TEST);
2653                                 selCol[3] = 85;
2654                                 if (!sel_only) wireCol[3] = 85;
2655                         }
2656                         else {
2657                                 continue;
2658                         }
2659                 }
2660                 else {
2661                         selCol[3] = 255;
2662                         if (!sel_only) wireCol[3] = 255;
2663                 }
2664
2665                 if (ts->selectmode == SCE_SELECT_FACE) {
2666                         draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
2667                 }
2668                 else if ((me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE)) {
2669                         if (cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2670                                 glShadeModel(GL_SMOOTH);
2671                                 draw_dm_edges_sel_interp(em, cageDM, wireCol, selCol);
2672                                 glShadeModel(GL_FLAT);
2673                         }
2674                         else {
2675                                 draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
2676                         }
2677                 }
2678                 else {
2679                         if (!sel_only) {
2680                                 glColor4ubv(wireCol);
2681                                 draw_dm_edges(em, cageDM);
2682                         }
2683                 }
2684
2685                 if (pass == 0) {
2686                         glDisable(GL_BLEND);
2687                         glEnable(GL_DEPTH_TEST);
2688                 }
2689         }
2690 }
2691
2692 static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMesh *em, UnitSettings *unit)
2693 {
2694         /* Do not use ascii when using non-default unit system, some unit chars are utf8 (micro, square, etc.).
2695          * See bug #36090.
2696          */
2697         const short txt_flag = V3D_CACHE_TEXT_LOCALCLIP | (unit->system ? 0 : V3D_CACHE_TEXT_ASCII);
2698         Mesh *me = ob->data;
2699         float v1[3], v2[3], v3[3], vmid[3], fvec[3];
2700         char numstr[32]; /* Stores the measurement display text here */
2701         const char *conv_float; /* Use a float conversion matching the grid size */
2702         unsigned char col[4] = {0, 0, 0, 255}; /* color of the text to draw */
2703         float area; /* area of the face */
2704         float grid = unit->system ? unit->scale_length : v3d->grid;
2705         const bool do_split = (unit->flag & USER_UNIT_OPT_SPLIT) != 0;
2706         const bool do_global = (v3d->flag & V3D_GLOBAL_STATS) != 0;
2707         const bool do_moving = (G.moving & G_TRANSFORM_EDIT) != 0;
2708         /* when 2 edge-info options are enabled, space apart */
2709         const bool do_edge_textpair = (me->drawflag & ME_DRAWEXTRA_EDGELEN) && (me->drawflag & ME_DRAWEXTRA_EDGEANG);
2710         const float edge_texpair_sep = 0.4f;
2711         float clip_planes[4][4];
2712         /* allow for displaying shape keys and deform mods */
2713         DerivedMesh *dm = EDBM_mesh_deform_dm_get(em);
2714         BMIter iter;
2715         int i;
2716
2717         /* make the precision of the display value proportionate to the gridsize */
2718
2719         if (grid <= 0.01f) conv_float = "%.6g";
2720         else if (grid <= 0.1f) conv_float = "%.5g";
2721         else if (grid <= 1.0f) conv_float = "%.4g";
2722         else if (grid <= 10.0f) conv_float = "%.3g";
2723         else conv_float = "%.2g";
2724
2725         if (me->drawflag & (ME_DRAWEXTRA_EDGELEN | ME_DRAWEXTRA_EDGEANG)) {
2726                 BoundBox bb;
2727                 bglMats mats = {{0}};
2728                 const rcti rect = {0, ar->winx, 0, ar->winy};
2729
2730                 view3d_get_transformation(ar, ar->regiondata, em->ob, &mats);
2731                 ED_view3d_clipping_calc(&bb, clip_planes, &mats, &rect);
2732         }
2733
2734         if (me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2735                 BMEdge *eed;
2736
2737                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2738
2739                 if (dm) {
2740                         BM_mesh_elem_index_ensure(em->bm, BM_VERT);
2741                 }
2742
2743                 BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
2744                         /* draw selected edges, or edges next to selected verts while draging */
2745                         if (BM_elem_flag_test(eed, BM_ELEM_SELECT) ||
2746                             (do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
2747                                            BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))))
2748                         {
2749                                 float v1_clip[3], v2_clip[3];
2750
2751                                 if (dm) {
2752                                         dm->getVertCo(dm, BM_elem_index_get(eed->v1), v1);
2753                                         dm->getVertCo(dm, BM_elem_index_get(eed->v2), v2);
2754                                 }
2755                                 else {
2756                                         copy_v3_v3(v1, eed->v1->co);
2757                                         copy_v3_v3(v2, eed->v2->co);
2758                                 }
2759
2760                                 copy_v3_v3(v1_clip, v1);
2761                                 copy_v3_v3(v2_clip, v2);
2762
2763                                 if (clip_segment_v3_plane_n(v1_clip, v2_clip, clip_planes, 4)) {
2764
2765                                         if (do_edge_textpair) {
2766                                                 interp_v3_v3v3(vmid, v1, v2, edge_texpair_sep);
2767                                         }
2768                                         else {
2769                                                 mid_v3_v3v3(vmid, v1_clip, v2_clip);
2770                                         }
2771
2772                                         if (do_global) {
2773                                                 mul_mat3_m4_v3(ob->obmat, v1);
2774                                                 mul_mat3_m4_v3(ob->obmat, v2);
2775                                         }
2776
2777                                         if (unit->system) {
2778                                                 bUnit_AsString(numstr, sizeof(numstr), len_v3v3(v1, v2) * unit->scale_length, 3,
2779                                                                unit->system, B_UNIT_LENGTH, do_split, false);
2780                                         }
2781                                         else {
2782                                                 BLI_snprintf(numstr, sizeof(numstr), conv_float, len_v3v3(v1, v2));
2783                                         }
2784
2785                                         view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col);
2786                                 }
2787                         }
2788                 }
2789         }
2790
2791         if (me->drawflag & ME_DRAWEXTRA_EDGEANG) {
2792                 const bool is_rad = (unit->system_rotation == USER_UNIT_ROT_RADIANS);
2793                 BMEdge *eed;
2794
2795                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGEANG, col);
2796
2797                 if (dm) {
2798                         BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE);
2799                 }
2800
2801                 // invert_m4_m4(ob->imat, ob->obmat);  // this is already called
2802
2803                 BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
2804                         BMLoop *l_a, *l_b;
2805                         if (BM_edge_loop_pair(eed, &l_a, &l_b)) {
2806                                 /* draw selected edges, or edges next to selected verts while draging */
2807                                 if (BM_elem_flag_test(eed, BM_ELEM_SELECT) ||
2808                                     (do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
2809                                                    BM_elem_flag_test(eed->v2, BM_ELEM_SELECT) ||
2810                                                    /* special case, this is useful to show when vertes connected to this edge via a
2811                                                     * face are being transformed */
2812                                                    BM_elem_flag_test(l_a->next->next->v, BM_ELEM_SELECT) ||
2813                                                    BM_elem_flag_test(l_a->prev->v, BM_ELEM_SELECT)       ||
2814                                                    BM_elem_flag_test(l_b->next->next->v, BM_ELEM_SELECT) ||
2815                                                    BM_elem_flag_test(l_b->prev->v, BM_ELEM_SELECT)
2816                                                    )))
2817                                 {
2818                                         float v1_clip[3], v2_clip[3];
2819
2820                                         if (dm) {
2821                                                 dm->getVertCo(dm, BM_elem_index_get(eed->v1), v1);
2822                                                 dm->getVertCo(dm, BM_elem_index_get(eed->v2), v2);
2823                                         }
2824                                         else {
2825                                                 copy_v3_v3(v1, eed->v1->co);
2826                                                 copy_v3_v3(v2, eed->v2->co);
2827                                         }
2828
2829                                         copy_v3_v3(v1_clip, v1);
2830                                         copy_v3_v3(v2_clip, v2);
2831
2832                                         if (clip_segment_v3_plane_n(v1_clip, v2_clip, clip_planes, 4)) {
2833                                                 float no_a[3], no_b[3];
2834                                                 float angle;
2835
2836                                                 if (do_edge_textpair) {
2837                                                         interp_v3_v3v3(vmid, v2_clip, v1_clip, edge_texpair_sep);
2838                                                 }
2839                                                 else {
2840                                                         mid_v3_v3v3(vmid, v1_clip, v2_clip);
2841                                                 }
2842
2843                                                 if (dm) {
2844                                                         dm->getPolyNo(dm, BM_elem_index_get(l_a->f), no_a);
2845                                                         dm->getPolyNo(dm, BM_elem_index_get(l_b->f), no_b);
2846                                                 }
2847                                                 else {
2848                                                         copy_v3_v3(no_a, l_a->f->no);
2849                                                         copy_v3_v3(no_b, l_b->f->no);
2850                                                 }
2851
2852                                                 if (do_global) {
2853                                                         mul_mat3_m4_v3(ob->imat, no_a);
2854                                                         mul_mat3_m4_v3(ob->imat, no_b);
2855                                                         normalize_v3(no_a);
2856                                                         normalize_v3(no_b);
2857                                                 }
2858
2859                                                 angle = angle_normalized_v3v3(no_a, no_b);
2860
2861                                                 BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle));
2862
2863                                                 view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col);
2864                                         }
2865                                 }
2866                         }
2867                 }
2868         }
2869
2870         if (me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2871                 /* would be nice to use BM_face_calc_area, but that is for 2d faces
2872                  * so instead add up tessellation triangle areas */
2873                 BMFace *f;
2874                 int n;
2875
2876 #define DRAW_EM_MEASURE_STATS_FACEAREA()                                                 \
2877         if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {                                          \
2878                 mul_v3_fl(vmid, 1.0f / (float)n);                                                \
2879                 if (unit->system) {                                                              \
2880                         bUnit_AsString(numstr, sizeof(numstr),                                       \
2881                                        (double)(area * unit->scale_length * unit->scale_length),     \
2882                                        3, unit->system, B_UNIT_AREA, do_split, false);               \
2883                 }                                                                                \
2884                 else {                                                                           \
2885                         BLI_snprintf(numstr, sizeof(numstr), conv_float, area);                      \
2886                 }                                                                                \
2887                 view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col);                     \
2888         } (void)0
2889
2890                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2891                 
2892                 if (dm) {
2893                         BM_mesh_elem_index_ensure(em->bm, BM_VERT);
2894                 }
2895
2896                 f = NULL;
2897                 area = 0.0;
2898                 zero_v3(vmid);
2899                 n = 0;
2900                 for (i = 0; i < em->tottri; i++) {
2901                         BMLoop **l = em->looptris[i];
2902                         if (f && l[0]->f != f) {
2903                                 DRAW_EM_MEASURE_STATS_FACEAREA();
2904                                 zero_v3(vmid);
2905                                 area = 0.0;
2906                                 n = 0;
2907                         }
2908
2909                         f = l[0]->f;
2910
2911                         if (dm) {
2912                                 dm->getVertCo(dm, BM_elem_index_get(l[0]->v), v1);
2913                                 dm->getVertCo(dm, BM_elem_index_get(l[1]->v), v2);
2914                                 dm->getVertCo(dm, BM_elem_index_get(l[2]->v), v3);
2915                         }
2916                         else {
2917                                 copy_v3_v3(v1, l[0]->v->co);
2918                                 copy_v3_v3(v2, l[1]->v->co);
2919                                 copy_v3_v3(v3, l[2]->v->co);
2920                         }
2921
2922                         add_v3_v3(vmid, v1);
2923                         add_v3_v3(vmid, v2);
2924                         add_v3_v3(vmid, v3);
2925                         n += 3;
2926                         if (do_global) {
2927                                 mul_mat3_m4_v3(ob->obmat, v1);
2928                                 mul_mat3_m4_v3(ob->obmat, v2);
2929                                 mul_mat3_m4_v3(ob->obmat, v3);
2930                         }
2931                         area += area_tri_v3(v1, v2, v3);
2932                 }
2933
2934                 if (f) {
2935                         DRAW_EM_MEASURE_STATS_FACEAREA();
2936                 }
2937 #undef DRAW_EM_MEASURE_STATS_FACEAREA
2938         }
2939
2940         if (me->drawflag & ME_DRAWEXTRA_FACEANG) {
2941                 BMFace *efa;
2942                 const bool is_rad = (unit->system_rotation == USER_UNIT_ROT_RADIANS);
2943
2944                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2945
2946                 if (dm) {
2947                         BM_mesh_elem_index_ensure(em->bm, BM_VERT);
2948                 }
2949
2950                 BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
2951                         const int is_face_sel = BM_elem_flag_test(efa, BM_ELEM_SELECT);
2952
2953                         if (is_face_sel || do_moving) {
2954                                 BMIter liter;
2955                                 BMLoop *loop;
2956                                 bool is_first = true;
2957
2958                                 BM_ITER_ELEM (loop, &liter, efa, BM_LOOPS_OF_FACE) {
2959                                         if (is_face_sel || (do_moving && BM_elem_flag_test(loop->v, BM_ELEM_SELECT))) {
2960                                                 float angle;
2961                                                 float v2_local[3];
2962
2963                                                 /* lazy init center calc */
2964                                                 if (is_first) {
2965                                                         if (dm) {
2966                                                                 BMLoop *l_iter, *l_first;
2967                                                                 float tvec[3];
2968                                                                 zero_v3(vmid);
2969                                                                 l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
2970                                                                 do {
2971                                                                         dm->getVertCo(dm, BM_elem_index_get(l_iter->v), tvec);
2972                                                                         add_v3_v3(vmid, tvec);
2973                                                                 } while ((l_iter = l_iter->next) != l_first);
2974                                                                 mul_v3_fl(vmid, 1.0f / (float)efa->len);
2975                                                         }
2976                                                         else {
2977                                                                 BM_face_calc_center_bounds(efa, vmid);
2978                                                         }
2979                                                         is_first = false;
2980                                                 }
2981
2982                                                 if (dm) {
2983                                                         dm->getVertCo(dm, BM_elem_index_get(loop->prev->v), v1);
2984                                                         dm->getVertCo(dm, BM_elem_index_get(loop->v),       v2);
2985                                                         dm->getVertCo(dm, BM_elem_index_get(loop->next->v), v3);
2986                                                 }
2987                                                 else {
2988                                                         copy_v3_v3(v1, loop->prev->v->co);
2989                                                         copy_v3_v3(v2, loop->v->co);
2990                                                         copy_v3_v3(v3, loop->next->v->co);
2991                                                 }
2992
2993                                                 copy_v3_v3(v2_local, v2);
2994
2995                                                 if (do_global) {
2996                                                         mul_mat3_m4_v3(ob->obmat, v1);
2997                                                         mul_mat3_m4_v3(ob->obmat, v2);
2998                                                         mul_mat3_m4_v3(ob->obmat, v3);
2999                                                 }
3000
3001                                                 angle = angle_v3v3v3(v1, v2, v3);
3002
3003                                                 BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle));
3004                                                 interp_v3_v3v3(fvec, vmid, v2_local, 0.8f);
3005                                                 view3d_cached_text_draw_add(fvec, numstr, 0, txt_flag, col);
3006                                         }
3007                                 }
3008                         }
3009                 }
3010         }
3011 }
3012
3013 static void draw_em_indices(BMEditMesh *em)
3014 {
3015         const short txt_flag = V3D_CACHE_TEXT_ASCII | V3D_CACHE_TEXT_LOCALCLIP;
3016         BMEdge *e;
3017         BMFace *f;
3018         BMVert *v;
3019         int i;
3020         char numstr[32];
3021         float pos[3];
3022         unsigned char col[4];
3023
3024         BMIter iter;
3025         BMesh *bm = em->bm;
3026
3027         /* For now, reuse appropriate theme colors from stats text colors */
3028         i = 0;
3029         if (em->selectmode & SCE_SELECT_VERTEX) {
3030                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
3031                 BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
3032                         if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
3033                                 BLI_snprintf(numstr, sizeof(numstr), "%d", i);
3034                                 view3d_cached_text_draw_add(v->co, numstr, 0, txt_flag, col);
3035                         }
3036                         i++;
3037                 }
3038         }
3039
3040         if (em->selectmode & SCE_SELECT_EDGE) {
3041                 i = 0;
3042                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
3043                 BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
3044                         if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
3045                                 BLI_snprintf(numstr, sizeof(numstr), "%d", i);
3046                                 mid_v3_v3v3(pos, e->v1->co, e->v2->co);
3047                                 view3d_cached_text_draw_add(pos, numstr, 0, txt_flag, col);
3048                         }
3049                         i++;
3050                 }
3051         }
3052
3053         if (em->selectmode & SCE_SELECT_FACE) {
3054                 i = 0;
3055                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
3056                 BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
3057                         if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
3058                                 BM_face_calc_center_mean(f, pos);
3059                                 BLI_snprintf(numstr, sizeof(numstr), "%d", i);
3060                                 view3d_cached_text_draw_add(pos, numstr, 0, txt_flag, col);
3061                         }
3062                         i++;
3063                 }
3064         }
3065 }
3066
3067 static DMDrawOption draw_em_fancy__setFaceOpts(void *userData, int index)
3068 {
3069         BMEditMesh *em = userData;
3070         BMFace *efa;
3071
3072         if (UNLIKELY(index >= em->bm->totface))
3073                 return DM_DRAW_OPTION_NORMAL;
3074
3075         efa = BM_face_at_index(em->bm, index);
3076         if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
3077                 GPU_enable_material(efa->mat_nr + 1, NULL);
3078                 return DM_DRAW_OPTION_NORMAL;
3079         }
3080         else {
3081                 return DM_DRAW_OPTION_SKIP;
3082         }
3083 }
3084
3085 static DMDrawOption draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
3086 {
3087         BMEditMesh *em = userData;
3088         BMFace *efa;
3089
3090         if (UNLIKELY(index >= em->bm->totface))
3091                 return DM_DRAW_OPTION_NORMAL;
3092
3093         efa = BM_face_at_index(em->bm, index);
3094
3095         if (!BM_elem_flag_test(efa, BM