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