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