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