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