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