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