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