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