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