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