Merged changes in the trunk up to revision 45133.
[blender-staging.git] / source / blender / editors / space_view3d / drawobject.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation, full recode and added functions
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/space_view3d/drawobject.c
27  *  \ingroup spview3d
28  */
29
30
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
113 /* this condition has been made more complex since editmode can draw textures */
114 #define CHECK_OB_DRAWTEXTURE(vd, dt)                                          \
115         ((ELEM(vd->drawtype, OB_TEXTURE, OB_MATERIAL) && dt>OB_SOLID) ||          \
116         (vd->drawtype==OB_SOLID && vd->flag2 & V3D_SOLID_TEX))
117
118 typedef enum eWireDrawMode {
119         OBDRAW_WIRE_OFF= 0,
120         OBDRAW_WIRE_ON= 1,
121         OBDRAW_WIRE_ON_DEPTH= 2
122 } eWireDrawMode;
123
124 /* user data structures for derived mesh callbacks */
125 typedef struct foreachScreenVert_userData {
126         void (*func)(void *userData, BMVert *eve, int x, int y, int index);
127         void *userData;
128         ViewContext vc;
129         eV3DClipTest clipVerts;
130 } foreachScreenVert_userData;
131
132 typedef struct foreachScreenEdge_userData {
133         void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index);
134         void *userData;
135         ViewContext vc;
136         eV3DClipTest clipVerts;
137 } foreachScreenEdge_userData;
138
139 typedef struct foreachScreenFace_userData {
140         void (*func)(void *userData, BMFace *efa, int x, int y, int index);
141         void *userData;
142         ViewContext vc;
143 } foreachScreenFace_userData;
144
145 typedef struct drawDMVerts_userData {
146         BMEditMesh *em; /* BMESH BRANCH ONLY */
147
148         int sel;
149         BMVert *eve_act;
150 } drawDMVerts_userData;
151
152 typedef struct drawDMEdgesSel_userData {
153         BMEditMesh *em; /* BMESH BRANCH ONLY */
154
155         unsigned char *baseCol, *selCol, *actCol;
156         BMEdge *eed_act;
157 } drawDMEdgesSel_userData;
158
159 typedef struct drawDMFacesSel_userData {
160         unsigned char *cols[4];
161
162         DerivedMesh *dm; /* BMESH BRANCH ONLY */
163         BMEditMesh *em;  /* BMESH BRANCH ONLY */
164
165         BMFace *efa_act;
166         int *orig_index;
167 } drawDMFacesSel_userData;
168
169 typedef struct drawDMNormal_userData {
170         BMEditMesh *em;
171         float normalsize;
172 } drawDMNormal_userData;
173
174 typedef struct bbsObmodeMeshVerts_userData {
175         void *offset;
176         MVert *mvert;
177 } bbsObmodeMeshVerts_userData;
178
179 static void draw_bounding_volume(Scene *scene, Object *ob, char type);
180
181 static void drawcube_size(float size);
182 static void drawcircle_size(float size);
183 static void draw_empty_sphere(float size);
184 static void draw_empty_cone(float size);
185
186 static int check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
187 {
188         if ((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0)
189                 return 0;
190
191         if (G.f & G_BACKBUFSEL)
192                 return 0;
193
194         if ((vd->flag & V3D_ZBUF_SELECT) == 0)
195                 return 1;
196
197         /* if its drawing textures with zbuf sel, then don't draw dots */
198         if (dt==OB_TEXTURE && vd->drawtype==OB_TEXTURE)
199                 return 0;
200
201         if ((vd->drawtype >= OB_SOLID) && (vd->flag2 & V3D_SOLID_TEX))
202                 return 0;
203
204         return 1;
205 }
206
207 /* ************* only use while object drawing **************
208  * or after running ED_view3d_init_mats_rv3d
209  * */
210 static void view3d_project_short_clip(ARegion *ar, const float vec[3], short adr[2], int is_local)
211 {
212         RegionView3D *rv3d= ar->regiondata;
213         float fx, fy, vec4[4];
214         
215         adr[0]= IS_CLIPPED;
216         
217         /* clipplanes in eye space */
218         if (rv3d->rflag & RV3D_CLIPPING) {
219                 if (ED_view3d_clipping_test(rv3d, vec, is_local))
220                         return;
221         }
222         
223         copy_v3_v3(vec4, vec);
224         vec4[3]= 1.0;
225         
226         mul_m4_v4(rv3d->persmatob, vec4);
227         
228         /* clipplanes in window space */
229         if ( vec4[3] > (float)BL_NEAR_CLIP ) {  /* is the NEAR clipping cutoff for picking */
230                 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
231                 
232                 if ( fx>0 && fx<ar->winx) {
233                         
234                         fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
235                         
236                         if (fy > 0.0f && fy < (float)ar->winy) {
237                                 adr[0]= (short)floorf(fx);
238                                 adr[1]= (short)floorf(fy);
239                         }
240                 }
241         }
242 }
243
244 /* BMESH NOTE: this function is unused in bmesh only */
245
246 /* only use while object drawing */
247 static void UNUSED_FUNCTION(view3d_project_short_noclip)(ARegion *ar, const float vec[3], short adr[2])
248 {
249         RegionView3D *rv3d= ar->regiondata;
250         float fx, fy, vec4[4];
251         
252         adr[0]= IS_CLIPPED;
253         
254         copy_v3_v3(vec4, vec);
255         vec4[3]= 1.0;
256         
257         mul_m4_v4(rv3d->persmatob, vec4);
258         
259         if ( vec4[3] > (float)BL_NEAR_CLIP ) {  /* is the NEAR clipping cutoff for picking */
260                 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
261                 
262                 if ( fx>-32700 && fx<32700) {
263                         
264                         fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
265                         
266                         if (fy > -32700.0f && fy < 32700.0f) {
267                                 adr[0]= (short)floorf(fx);
268                                 adr[1]= (short)floorf(fy);
269                         }
270                 }
271         }
272 }
273
274 /* same as view3d_project_short_clip but use persmat instead of persmatob for projection */
275 static void view3d_project_short_clip_persmat(ARegion *ar, const float vec[3], short adr[2], int is_local)
276 {
277         RegionView3D *rv3d= ar->regiondata;
278         float fx, fy, vec4[4];
279
280         adr[0]= IS_CLIPPED;
281
282         /* clipplanes in eye space */
283         if (rv3d->rflag & RV3D_CLIPPING) {
284                 if (ED_view3d_clipping_test(rv3d, vec, is_local))
285                         return;
286         }
287
288         copy_v3_v3(vec4, vec);
289         vec4[3]= 1.0;
290
291         mul_m4_v4(rv3d->persmat, vec4);
292
293         /* clipplanes in window space */
294         if ( vec4[3] > (float)BL_NEAR_CLIP ) {  /* is the NEAR clipping cutoff for picking */
295                 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
296
297                 if ( fx>0 && fx<ar->winx) {
298
299                         fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
300
301                         if (fy > 0.0f && fy < (float)ar->winy) {
302                                 adr[0]= (short)floorf(fx);
303                                 adr[1]= (short)floorf(fy);
304                         }
305                 }
306         }
307 }
308 /* ************************ */
309
310 /* check for glsl drawing */
311
312 int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt)
313 {
314         if (!GPU_glsl_support())
315                 return 0;
316         if (G.f & G_PICKSEL)
317                 return 0;
318         if (!CHECK_OB_DRAWTEXTURE(v3d, dt))
319                 return 0;
320         if (ob==OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
321                 return 0;
322         if (scene_use_new_shading_nodes(scene))
323                 return 0;
324         
325         return (scene->gm.matmode == GAME_MAT_GLSL) && (dt > OB_SOLID);
326 }
327
328 static int check_alpha_pass(Base *base)
329 {
330         if (base->flag & OB_FROMDUPLI)
331                 return 0;
332
333         if (G.f & G_PICKSEL)
334                 return 0;
335         
336         return (base->object->dtx & OB_DRAWTRANSP);
337 }
338
339         /***/
340 static unsigned int colortab[24]=
341         {0x0,           0xFF88FF, 0xFFBBFF, 
342          0x403000,      0xFFFF88, 0xFFFFBB, 
343          0x104040,      0x66CCCC, 0x77CCCC, 
344          0x104010,      0x55BB55, 0x66FF66, 
345          0xFFFFFF
346 };
347
348
349 static float cube[8][3] = {
350         {-1.0, -1.0, -1.0},
351         {-1.0, -1.0,  1.0},
352         {-1.0,  1.0,  1.0},
353         {-1.0,  1.0, -1.0},
354         { 1.0, -1.0, -1.0},
355         { 1.0, -1.0,  1.0},
356         { 1.0,  1.0,  1.0},
357         { 1.0,  1.0, -1.0},
358 };
359
360 /* ----------------- OpenGL Circle Drawing - Tables for Optimized Drawing Speed ------------------ */
361 /* 32 values of sin function (still same result!) */
362 #define CIRCLE_RESOL 32
363
364 static const float sinval[CIRCLE_RESOL] = {
365         0.00000000,
366         0.20129852,
367         0.39435585,
368         0.57126821,
369         0.72479278,
370         0.84864425,
371         0.93775213,
372         0.98846832,
373         0.99871650,
374         0.96807711,
375         0.89780453,
376         0.79077573,
377         0.65137248,
378         0.48530196,
379         0.29936312,
380         0.10116832,
381         -0.10116832,
382         -0.29936312,
383         -0.48530196,
384         -0.65137248,
385         -0.79077573,
386         -0.89780453,
387         -0.96807711,
388         -0.99871650,
389         -0.98846832,
390         -0.93775213,
391         -0.84864425,
392         -0.72479278,
393         -0.57126821,
394         -0.39435585,
395         -0.20129852,
396         0.00000000
397 };
398
399 /* 32 values of cos function (still same result!) */
400 static const float cosval[CIRCLE_RESOL] = {
401         1.00000000,
402         0.97952994,
403         0.91895781,
404         0.82076344,
405         0.68896691,
406         0.52896401,
407         0.34730525,
408         0.15142777,
409         -0.05064916,
410         -0.25065253,
411         -0.44039415,
412         -0.61210598,
413         -0.75875812,
414         -0.87434661,
415         -0.95413925,
416         -0.99486932,
417         -0.99486932,
418         -0.95413925,
419         -0.87434661,
420         -0.75875812,
421         -0.61210598,
422         -0.44039415,
423         -0.25065253,
424         -0.05064916,
425         0.15142777,
426         0.34730525,
427         0.52896401,
428         0.68896691,
429         0.82076344,
430         0.91895781,
431         0.97952994,
432         1.00000000
433 };
434
435 static void draw_xyz_wire(const float c[3], float size, int axis)
436 {
437         float v1[3]= {0.f, 0.f, 0.f}, v2[3] = {0.f, 0.f, 0.f};
438         float dim = size * 0.1f;
439         float dx[3], dy[3], dz[3];
440
441         dx[0]=dim; dx[1]=0.f; dx[2]=0.f;
442         dy[0]=0.f; dy[1]=dim; dy[2]=0.f;
443         dz[0]=0.f; dz[1]=0.f; dz[2]=dim;
444
445         switch(axis) {
446                 case 0:         /* x axis */
447                         glBegin(GL_LINES);
448                         
449                         /* bottom left to top right */
450                         sub_v3_v3v3(v1, c, dx);
451                         sub_v3_v3(v1, dy);
452                         add_v3_v3v3(v2, c, dx);
453                         add_v3_v3(v2, dy);
454                         
455                         glVertex3fv(v1);
456                         glVertex3fv(v2);
457                         
458                         /* top left to bottom right */
459                         mul_v3_fl(dy, 2.f);
460                         add_v3_v3(v1, dy);
461                         sub_v3_v3(v2, dy);
462                         
463                         glVertex3fv(v1);
464                         glVertex3fv(v2);
465                         
466                         glEnd();
467                         break;
468                 case 1:         /* y axis */
469                         glBegin(GL_LINES);
470                         
471                         /* bottom left to top right */
472                         mul_v3_fl(dx, 0.75f);
473                         sub_v3_v3v3(v1, c, dx);
474                         sub_v3_v3(v1, dy);
475                         add_v3_v3v3(v2, c, dx);
476                         add_v3_v3(v2, dy);
477                         
478                         glVertex3fv(v1);
479                         glVertex3fv(v2);
480                         
481                         /* top left to center */
482                         mul_v3_fl(dy, 2.f);
483                         add_v3_v3(v1, dy);
484                         copy_v3_v3(v2, c);
485                         
486                         glVertex3fv(v1);
487                         glVertex3fv(v2);
488                         
489                         glEnd();
490                         break;
491                 case 2:         /* z axis */
492                         glBegin(GL_LINE_STRIP);
493                         
494                         /* start at top left */
495                         sub_v3_v3v3(v1, c, dx);
496                         add_v3_v3v3(v1, c, dz);
497                         
498                         glVertex3fv(v1);
499                         
500                         mul_v3_fl(dx, 2.f);
501                         add_v3_v3(v1, dx);
502
503                         glVertex3fv(v1);
504                         
505                         mul_v3_fl(dz, 2.f);
506                         sub_v3_v3(v1, dx);
507                         sub_v3_v3(v1, dz);
508                         
509                         glVertex3fv(v1);
510                         
511                         add_v3_v3(v1, dx);
512                 
513                         glVertex3fv(v1);
514                         
515                         glEnd();
516                         break;
517         }
518         
519 }
520
521 void drawaxes(float size, char drawtype)
522 {
523         int axis;
524         float v1[3]= {0.0, 0.0, 0.0};
525         float v2[3]= {0.0, 0.0, 0.0};
526         float v3[3]= {0.0, 0.0, 0.0};
527         
528         switch(drawtype) {
529
530                 case OB_PLAINAXES:
531                         for (axis=0; axis<3; axis++) {
532                                 glBegin(GL_LINES);
533
534                                 v1[axis]= size;
535                                 v2[axis]= -size;
536                                 glVertex3fv(v1);
537                                 glVertex3fv(v2);
538
539                                 /* reset v1 & v2 to zero */
540                                 v1[axis]= v2[axis]= 0.0f;
541
542                                 glEnd();
543                         }
544                         break;
545                 case OB_SINGLE_ARROW:
546
547                         glBegin(GL_LINES);
548                         /* in positive z direction only */
549                         v1[2]= size;
550                         glVertex3fv(v1);
551                         glVertex3fv(v2);
552                         glEnd();
553
554                         /* square pyramid */
555                         glBegin(GL_TRIANGLES);
556
557                         v2[0]= size * 0.035f; v2[1] = size * 0.035f;
558                         v3[0]= size * -0.035f; v3[1] = size * 0.035f;
559                         v2[2]= v3[2]= size * 0.75f;
560
561                         for (axis=0; axis<4; axis++) {
562                                 if (axis % 2 == 1) {
563                                         v2[0] = -v2[0];
564                                         v3[1] = -v3[1];
565                                 }
566                                 else {
567                                         v2[1] = -v2[1];
568                                         v3[0] = -v3[0];
569                                 }
570
571                                 glVertex3fv(v1);
572                                 glVertex3fv(v2);
573                                 glVertex3fv(v3);
574
575                         }
576                         glEnd();
577
578                         break;
579                 case OB_CUBE:
580                         drawcube_size(size);
581                         break;
582
583                 case OB_CIRCLE:
584                         drawcircle_size(size);
585                         break;
586
587                 case OB_EMPTY_SPHERE:
588                         draw_empty_sphere(size);
589                         break;
590
591                 case OB_EMPTY_CONE:
592                         draw_empty_cone(size);
593                         break;
594
595                 case OB_ARROWS:
596                 default:
597                 {
598                         for (axis=0; axis<3; axis++) {
599                                 const int arrow_axis= (axis==0) ? 1:0;
600
601                                 glBegin(GL_LINES);
602
603                                 v2[axis]= size;
604                                 glVertex3fv(v1);
605                                 glVertex3fv(v2);
606                                 
607                                 v1[axis]= size*0.85f;
608                                 v1[arrow_axis]= -size*0.08f;
609                                 glVertex3fv(v1);
610                                 glVertex3fv(v2);
611                                 
612                                 v1[arrow_axis]= size*0.08f;
613                                 glVertex3fv(v1);
614                                 glVertex3fv(v2);
615
616                                 glEnd();
617                                 
618                                 v2[axis]+= size*0.125f;
619
620                                 draw_xyz_wire(v2, size, axis);
621
622
623                                 /* reset v1 & v2 to zero */
624                                 v1[arrow_axis]= v1[axis]= v2[axis]= 0.0f;
625                         }
626                         break;
627                 }
628         }
629 }
630
631
632 /* Function to draw an Image on a empty Object */
633 static void draw_empty_image(Object *ob)
634 {
635         Image *ima = (Image*)ob->data;
636         ImBuf *ibuf = ima ? BKE_image_get_ibuf(ima, NULL) : NULL;
637
638         float scale, ofs_x, ofs_y, sca_x, sca_y;
639         int ima_x, ima_y;
640
641         if (ibuf && (ibuf->rect == NULL) && (ibuf->rect_float != NULL)) {
642                 IMB_rect_from_float(ibuf);
643         }
644
645         /* Get the buffer dimensions so we can fallback to fake ones */
646         if (ibuf && ibuf->rect) {
647                 ima_x= ibuf->x;
648                 ima_y= ibuf->y;
649         }
650         else {
651                 ima_x= 1;
652                 ima_y= 1;
653         }
654
655         /* Get the image aspect even if the buffer is invalid */
656         if (ima) {
657                 if (ima->aspx > ima->aspy) {
658                         sca_x= 1.0f;
659                         sca_y= ima->aspy / ima->aspx;
660                 }
661                 else if (ima->aspx < ima->aspy) {
662                         sca_x= ima->aspx / ima->aspy;
663                         sca_y= 1.0f;
664                 }
665                 else {
666                         sca_x= 1.0f;
667                         sca_y= 1.0f;
668                 }
669         }
670         else {
671                 sca_x= 1.0f;
672                 sca_y= 1.0f;
673         }
674
675         /* Calculate the scale center based on objects origin */
676         ofs_x= ob->ima_ofs[0] * ima_x;
677         ofs_y= ob->ima_ofs[1] * ima_y;
678
679         glMatrixMode(GL_MODELVIEW);
680         glPushMatrix();
681
682         /* Make sure we are drawing at the origin */
683         glTranslatef(0.0f,  0.0f,  0.0f);
684
685         /* Calculate Image scale */
686         scale= (ob->empty_drawsize / (float)MAX2(ima_x * sca_x, ima_y * sca_y));
687
688         /* Set the object scale */
689         glScalef(scale * sca_x, scale * sca_y, 1.0f);
690
691         if (ibuf && ibuf->rect) {
692                 /* Setup GL params */
693                 glEnable(GL_BLEND);
694                 glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA);
695
696                 /* Use the object color and alpha */
697                 glColor4fv(ob->col);
698
699                 /* Draw the Image on the screen */
700                 glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_UNSIGNED_BYTE, ibuf->rect);
701                 glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
702
703                 glDisable(GL_BLEND);
704         }
705
706         UI_ThemeColor((ob->flag & SELECT) ? TH_SELECT : TH_WIRE);
707
708         /* Calculate the outline vertex positions */
709         glBegin(GL_LINE_LOOP);
710         glVertex2f(ofs_x, ofs_y);
711         glVertex2f(ofs_x + ima_x, ofs_y);
712         glVertex2f(ofs_x + ima_x, ofs_y + ima_y);
713         glVertex2f(ofs_x, ofs_y + ima_y);
714         glEnd();
715
716         /* Reset GL settings */
717         glMatrixMode(GL_MODELVIEW);
718         glPopMatrix();
719 }
720
721 static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3], float rad, float tmat[][4])
722 {
723         float vx[3], vy[3];
724         float *viter= (float *)verts;
725         unsigned int a;
726
727         mul_v3_v3fl(vx, tmat[0], rad);
728         mul_v3_v3fl(vy, tmat[1], rad);
729
730         for (a=0; a < CIRCLE_RESOL; a++, viter += 3) {
731                 viter[0]= cent[0] + sinval[a] * vx[0] + cosval[a] * vy[0];
732                 viter[1]= cent[1] + sinval[a] * vx[1] + cosval[a] * vy[1];
733                 viter[2]= cent[2] + sinval[a] * vx[2] + cosval[a] * vy[2];
734         }
735 }
736
737 void drawcircball(int mode, const float cent[3], float rad, float tmat[][4])
738 {
739         float verts[CIRCLE_RESOL][3];
740
741         circball_array_fill(verts, cent, rad, tmat);
742
743         glEnableClientState(GL_VERTEX_ARRAY);
744         glVertexPointer(3, GL_FLOAT, 0, verts);
745         glDrawArrays(mode, 0, CIRCLE_RESOL);
746         glDisableClientState(GL_VERTEX_ARRAY);
747 }
748
749 /* circle for object centers, special_color is for library or ob users */
750 static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], int selstate, int special_color)
751 {
752         const float size= ED_view3d_pixel_size(rv3d, co) * (float)U.obcenter_dia * 0.5f;
753         float verts[CIRCLE_RESOL][3];
754
755         /* using gldepthfunc guarantees that it does write z values,
756          * but not checks for it, so centers remain visible independent order of drawing */
757         if (v3d->zbuf)  glDepthFunc(GL_ALWAYS);
758         glEnable(GL_BLEND);
759         
760         if (special_color) {
761                 if (selstate==ACTIVE || selstate==SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
762
763                 else glColor4ub(0x55, 0xCC, 0xCC, 155);
764         }
765         else {
766                 if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
767                 else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
768                 else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
769         }
770
771         circball_array_fill(verts, co, size, rv3d->viewinv);
772
773         /* enable vertex array */
774         glEnableClientState(GL_VERTEX_ARRAY);
775         glVertexPointer(3, GL_FLOAT, 0, verts);
776
777         /* 1. draw filled, blended polygon */
778         glDrawArrays(GL_POLYGON, 0, CIRCLE_RESOL);
779
780         /* 2. draw outline */
781         UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
782         glDrawArrays(GL_LINE_LOOP, 0, CIRCLE_RESOL);
783
784         /* finish up */
785         glDisableClientState(GL_VERTEX_ARRAY);
786
787         glDisable(GL_BLEND);
788
789         if (v3d->zbuf)  glDepthFunc(GL_LEQUAL);
790 }
791
792 /* *********** text drawing for object/particles/armature ************* */
793 static ListBase CachedText[3];
794 static int CachedTextLevel= 0;
795
796 typedef struct ViewCachedString {
797         struct ViewCachedString *next, *prev;
798         float vec[3];
799         union {
800                 unsigned char ub[4];
801                 int pack;
802         } col;
803         short sco[2];
804         short xoffs;
805         short flag;
806         int str_len, pad;
807         /* str is allocated past the end */
808 } ViewCachedString;
809
810 void view3d_cached_text_draw_begin(void)
811 {
812         ListBase *strings= &CachedText[CachedTextLevel];
813         strings->first= strings->last= NULL;
814         CachedTextLevel++;
815 }
816
817 void view3d_cached_text_draw_add(const float co[3],
818                                  const char *str,
819                                  short xoffs, short flag,
820                                  const unsigned char col[4])
821 {
822         int alloc_len= strlen(str) + 1;
823         ListBase *strings= &CachedText[CachedTextLevel-1];
824         /* TODO, replace with more efficient malloc, perhaps memarena per draw? */
825         ViewCachedString *vos= MEM_callocN(sizeof(ViewCachedString) + alloc_len, "ViewCachedString");
826
827         BLI_addtail(strings, vos);
828         copy_v3_v3(vos->vec, co);
829         vos->col.pack= *((int *)col);
830         vos->xoffs= xoffs;
831         vos->flag= flag;
832         vos->str_len= alloc_len-1;
833
834         /* allocate past the end */
835         memcpy(++vos, str, alloc_len);
836 }
837
838 void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, float mat[][4])
839 {
840         RegionView3D *rv3d= ar->regiondata;
841         ListBase *strings= &CachedText[CachedTextLevel-1];
842         ViewCachedString *vos;
843         int tot= 0;
844         
845         /* project first and test */
846         for (vos= strings->first; vos; vos= vos->next) {
847                 if (mat && !(vos->flag & V3D_CACHE_TEXT_WORLDSPACE))
848                         mul_m4_v3(mat, vos->vec);
849
850                 if (vos->flag & V3D_CACHE_TEXT_GLOBALSPACE)
851                         view3d_project_short_clip_persmat(ar, vos->vec, vos->sco, (vos->flag & V3D_CACHE_TEXT_LOCALCLIP) != 0);
852                 else
853                         view3d_project_short_clip(ar, vos->vec, vos->sco, (vos->flag & V3D_CACHE_TEXT_LOCALCLIP) != 0);
854
855                 if (vos->sco[0]!=IS_CLIPPED)
856                         tot++;
857         }
858
859         if (tot) {
860                 int col_pack_prev= 0;
861
862 #if 0
863                 bglMats mats; /* ZBuffer depth vars */
864                 double ux, uy, uz;
865                 float depth;
866
867                 if (v3d->zbuf)
868                         bgl_get_mats(&mats);
869 #endif
870                 if (rv3d->rflag & RV3D_CLIPPING) {
871                         ED_view3d_clipping_disable();
872                 }
873
874                 glMatrixMode(GL_PROJECTION);
875                 glPushMatrix();
876                 glMatrixMode(GL_MODELVIEW);
877                 glPushMatrix();
878                 ED_region_pixelspace(ar);
879                 
880                 if (depth_write) {
881                         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
882                 }
883                 else {
884                         glDepthMask(0);
885                 }
886                 
887                 for (vos= strings->first; vos; vos= vos->next) {
888                         /* too slow, reading opengl info while drawing is very bad,
889                          * better to see if we can use the zbuffer while in pixel space - campbell */
890 #if 0
891                         if (v3d->zbuf && (vos->flag & V3D_CACHE_TEXT_ZBUF)) {
892                                 gluProject(vos->vec[0], vos->vec[1], vos->vec[2], mats.modelview, mats.projection, (GLint *)mats.viewport, &ux, &uy, &uz);
893                                 glReadPixels(ar->winrct.xmin+vos->mval[0]+vos->xoffs, ar->winrct.ymin+vos->mval[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
894
895                                 if (uz > depth)
896                                         continue;
897                         }
898 #endif
899                         if (vos->sco[0]!=IS_CLIPPED) {
900                                 const char *str= (char *)(vos+1);
901
902                                 if (col_pack_prev != vos->col.pack) {
903                                         glColor3ubv(vos->col.ub);
904                                         col_pack_prev= vos->col.pack;
905                                 }
906
907                                 ((vos->flag & V3D_CACHE_TEXT_ASCII) ?
908                                             BLF_draw_default_ascii :
909                                             BLF_draw_default
910                                             ) ( (float)vos->sco[0] + vos->xoffs,
911                                                 (float)vos->sco[1],
912                                                 (depth_write) ? 0.0f: 2.0f,
913                                                 str,
914                                                 vos->str_len);
915                         }
916                 }
917                 
918                 if (depth_write) {
919                         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
920                 }
921                 else glDepthMask(1);
922                 
923                 glMatrixMode(GL_PROJECTION);
924                 glPopMatrix();
925                 glMatrixMode(GL_MODELVIEW);
926                 glPopMatrix();
927
928                 if (rv3d->rflag & RV3D_CLIPPING) {
929                         ED_view3d_clipping_enable();
930                 }
931         }
932         
933         if (strings->first)
934                 BLI_freelistN(strings);
935         
936         CachedTextLevel--;
937 }
938
939 /* ******************** primitive drawing ******************* */
940
941 static void drawcube(void)
942 {
943
944         glBegin(GL_LINE_STRIP);
945         glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
946         glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
947         glVertex3fv(cube[7]); glVertex3fv(cube[4]);
948         glEnd();
949
950         glBegin(GL_LINE_STRIP);
951         glVertex3fv(cube[1]); glVertex3fv(cube[5]);
952         glEnd();
953
954         glBegin(GL_LINE_STRIP);
955         glVertex3fv(cube[2]); glVertex3fv(cube[6]);
956         glEnd();
957
958         glBegin(GL_LINE_STRIP);
959         glVertex3fv(cube[3]); glVertex3fv(cube[7]);
960         glEnd();
961 }
962
963 /* draws a cube on given the scaling of the cube, assuming that 
964  * all required matrices have been set (used for drawing empties)
965  */
966 static void drawcube_size(float size)
967 {
968         glBegin(GL_LINE_STRIP);
969         glVertex3f(-size,-size,-size); glVertex3f(-size,-size,size);
970         glVertex3f(-size,size,size); glVertex3f(-size,size,-size);
971
972         glVertex3f(-size,-size,-size); glVertex3f(size,-size,-size);
973         glVertex3f(size,-size,size); glVertex3f(size,size,size);
974
975         glVertex3f(size,size,-size); glVertex3f(size,-size,-size);
976         glEnd();
977
978         glBegin(GL_LINE_STRIP);
979         glVertex3f(-size,-size,size); glVertex3f(size,-size,size);
980         glEnd();
981
982         glBegin(GL_LINE_STRIP);
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
991 /* this is an unused (old) cube-drawing function based on a given size */
992 #if 0
993 static void drawcube_size(const float size[3])
994 {
995
996         glPushMatrix();
997         glScalef(size[0],  size[1],  size[2]);
998         
999
1000         glBegin(GL_LINE_STRIP);
1001         glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
1002         glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
1003         glVertex3fv(cube[7]); glVertex3fv(cube[4]);
1004         glEnd();
1005
1006         glBegin(GL_LINE_STRIP);
1007         glVertex3fv(cube[1]); glVertex3fv(cube[5]);
1008         glEnd();
1009
1010         glBegin(GL_LINE_STRIP);
1011         glVertex3fv(cube[2]); glVertex3fv(cube[6]);
1012         glEnd();
1013
1014         glBegin(GL_LINE_STRIP);
1015         glVertex3fv(cube[3]); glVertex3fv(cube[7]);
1016         glEnd();
1017         
1018         glPopMatrix();
1019 }
1020 #endif
1021
1022 static void drawshadbuflimits(Lamp *la, float mat[][4])
1023 {
1024         float sta[3], end[3], lavec[3];
1025
1026         negate_v3_v3(lavec, mat[2]);
1027         normalize_v3(lavec);
1028
1029         madd_v3_v3v3fl(sta, mat[3], lavec, la->clipsta);
1030         madd_v3_v3v3fl(end, mat[3], lavec, la->clipend);
1031
1032         glBegin(GL_LINE_STRIP);
1033         glVertex3fv(sta);
1034         glVertex3fv(end);
1035         glEnd();
1036
1037         glPointSize(3.0);
1038         bglBegin(GL_POINTS);
1039         bglVertex3fv(sta);
1040         bglVertex3fv(end);
1041         bglEnd();
1042         glPointSize(1.0);
1043 }
1044
1045
1046
1047 static void spotvolume(float lvec[3], float vvec[3], const float inp)
1048 {
1049         /* camera is at 0,0,0 */
1050         float temp[3],plane[3],mat1[3][3],mat2[3][3],mat3[3][3],mat4[3][3],q[4],co,si,angle;
1051
1052         normalize_v3(lvec);
1053         normalize_v3(vvec);                             /* is this the correct vector ? */
1054
1055         cross_v3_v3v3(temp,vvec,lvec);          /* equation for a plane through vvec en lvec */
1056         cross_v3_v3v3(plane,lvec,temp);         /* a plane perpendicular to this, parrallel with lvec */
1057
1058         /* vectors are exactly aligned, use the X axis, this is arbitrary */
1059         if (normalize_v3(plane) == 0.0f)
1060                 plane[1]= 1.0f;
1061
1062         /* now we've got two equations: one of a cone and one of a plane, but we have
1063          * three unknowns. We remove one unknown by rotating the plane to z=0 (the plane normal) */
1064
1065         /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
1066         /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
1067
1068         /* translating this comment to english didnt really help me understanding the math! :-) (ton) */
1069         
1070         q[1] =  plane[1];
1071         q[2] = -plane[0];
1072         q[3] =  0;
1073         normalize_v3(&q[1]);
1074
1075         angle = saacos(plane[2])/2.0f;
1076         co = cosf(angle);
1077         si = sqrtf(1-co*co);
1078
1079         q[0] =  co;
1080         q[1] *= si;
1081         q[2] *= si;
1082         q[3] =  0;
1083
1084         quat_to_mat3(mat1,q);
1085
1086         /* rotate lamp vector now over acos(inp) degrees */
1087         copy_v3_v3(vvec, lvec);
1088
1089         unit_m3(mat2);
1090         co = inp;
1091         si = sqrtf(1.0f-inp*inp);
1092
1093         mat2[0][0] =  co;
1094         mat2[1][0] = -si;
1095         mat2[0][1] =  si;
1096         mat2[1][1] =  co;
1097         mul_m3_m3m3(mat3,mat2,mat1);
1098
1099         mat2[1][0] =  si;
1100         mat2[0][1] = -si;
1101         mul_m3_m3m3(mat4,mat2,mat1);
1102         transpose_m3(mat1);
1103
1104         mul_m3_m3m3(mat2,mat1,mat3);
1105         mul_m3_v3(mat2,lvec);
1106         mul_m3_m3m3(mat2,mat1,mat4);
1107         mul_m3_v3(mat2,vvec);
1108
1109         return;
1110 }
1111
1112 static void draw_spot_cone(Lamp *la, float x, float z)
1113 {
1114         z= fabs(z);
1115
1116         glBegin(GL_TRIANGLE_FAN);
1117         glVertex3f(0.0f, 0.0f, -x);
1118
1119         if (la->mode & LA_SQUARE) {
1120                 glVertex3f(z, z, 0);
1121                 glVertex3f(-z, z, 0);
1122                 glVertex3f(-z, -z, 0);
1123                 glVertex3f(z, -z, 0);
1124                 glVertex3f(z, z, 0);
1125         }
1126         else {
1127                 float angle;
1128                 int a;
1129
1130                 for (a=0; a<33; a++) {
1131                         angle= a*M_PI*2/(33-1);
1132                         glVertex3f(z*cosf(angle), z*sinf(angle), 0);
1133                 }
1134         }
1135
1136         glEnd();
1137 }
1138
1139 static void draw_transp_spot_volume(Lamp *la, float x, float z)
1140 {
1141         glEnable(GL_CULL_FACE);
1142         glEnable(GL_BLEND);
1143         glDepthMask(0);
1144
1145         /* draw backside darkening */
1146         glCullFace(GL_FRONT);
1147
1148         glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
1149         glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
1150
1151         draw_spot_cone(la, x, z);
1152
1153         /* draw front side lighting */
1154         glCullFace(GL_BACK);
1155
1156         glBlendFunc(GL_ONE, GL_ONE);
1157         glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
1158
1159         draw_spot_cone(la, x, z);
1160
1161         /* restore state */
1162         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1163         glDisable(GL_BLEND);
1164         glDepthMask(1);
1165         glDisable(GL_CULL_FACE);
1166         glCullFace(GL_BACK);
1167 }
1168
1169 static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
1170 {
1171         Object *ob= base->object;
1172         const float pixsize= ED_view3d_pixel_size(rv3d, ob->obmat[3]);
1173         Lamp *la= ob->data;
1174         float vec[3], lvec[3], vvec[3], circrad, x,y,z;
1175         float lampsize;
1176         float imat[4][4], curcol[4];
1177         unsigned char col[4];
1178         /* cone can't be drawn for duplicated lamps, because duplilist would be freed to */
1179         /* the moment of view3d_draw_transp() call */
1180         const short is_view= (rv3d->persp==RV3D_CAMOB && v3d->camera == base->object);
1181         const short drawcone= ((dt > OB_WIRE) &&
1182                                !(G.f & G_PICKSEL) &&
1183                                (la->type == LA_SPOT) &&
1184                                (la->mode & LA_SHOW_CONE) &&
1185                                !(base->flag & OB_FROMDUPLI) &&
1186                                !is_view);
1187
1188         if (drawcone && !v3d->transp) {
1189                 /* in this case we need to draw delayed */
1190                 add_view3d_after(&v3d->afterdraw_transp, base, flag);
1191                 return;
1192         }
1193         
1194         /* we first draw only the screen aligned & fixed scale stuff */
1195         glPushMatrix();
1196         glLoadMatrixf(rv3d->viewmat);
1197
1198         /* lets calculate the scale: */
1199         lampsize= pixsize*((float)U.obcenter_dia*0.5f);
1200
1201         /* and view aligned matrix: */
1202         copy_m4_m4(imat, rv3d->viewinv);
1203         normalize_v3(imat[0]);
1204         normalize_v3(imat[1]);
1205
1206         /* lamp center */
1207         copy_v3_v3(vec, ob->obmat[3]);
1208         
1209         /* for AA effects */
1210         glGetFloatv(GL_CURRENT_COLOR, curcol);
1211         curcol[3]= 0.6;
1212         glColor4fv(curcol);
1213         
1214         if (lampsize > 0.0f) {
1215
1216                 if (ob->id.us>1) {
1217                         if (ob==OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155);
1218                         else glColor4ub(0x77, 0xCC, 0xCC, 155);
1219                 }
1220                 
1221                 /* Inner Circle */
1222                 glEnable(GL_BLEND);
1223                 drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
1224                 glDisable(GL_BLEND);
1225                 drawcircball(GL_POLYGON, vec, lampsize, imat);
1226                 
1227                 /* restore */
1228                 if (ob->id.us>1)
1229                         glColor4fv(curcol);
1230
1231                 /* Outer circle */
1232                 circrad = 3.0f*lampsize;
1233                 setlinestyle(3);
1234
1235                 drawcircball(GL_LINE_LOOP, vec, circrad, imat);
1236
1237                 /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
1238                 if (la->type!=LA_HEMI) {
1239                         if ((la->mode & LA_SHAD_RAY) || ((la->mode & LA_SHAD_BUF) && (la->type == LA_SPOT))) {
1240                                 drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f*pixsize, imat);
1241                         }
1242                 }
1243         }
1244         else {
1245                 setlinestyle(3);
1246                 circrad = 0.0f;
1247         }
1248         
1249         /* draw the pretty sun rays */
1250         if (la->type==LA_SUN) {
1251                 float v1[3], v2[3], mat[3][3];
1252                 short axis;
1253                 
1254                 /* setup a 45 degree rotation matrix */
1255                 vec_rot_to_mat3(mat, imat[2], (float)M_PI/4.0f);
1256                 
1257                 /* vectors */
1258                 mul_v3_v3fl(v1, imat[0], circrad * 1.2f);
1259                 mul_v3_v3fl(v2, imat[0], circrad * 2.5f);
1260                 
1261                 /* center */
1262                 glTranslatef(vec[0], vec[1], vec[2]);
1263                 
1264                 setlinestyle(3);
1265                 
1266                 glBegin(GL_LINES);
1267                 for (axis=0; axis<8; axis++) {
1268                         glVertex3fv(v1);
1269                         glVertex3fv(v2);
1270                         mul_m3_v3(mat, v1);
1271                         mul_m3_v3(mat, v2);
1272                 }
1273                 glEnd();
1274                 
1275                 glTranslatef(-vec[0], -vec[1], -vec[2]);
1276
1277         }
1278         
1279         if (la->type==LA_LOCAL) {
1280                 if (la->mode & LA_SPHERE) {
1281                         drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
1282                 }
1283                 /* yafray: for photonlight also draw lightcone as for spot */
1284         }
1285         
1286         glPopMatrix();  /* back in object space */
1287         zero_v3(vec);
1288         
1289         if (is_view) {
1290                 /* skip drawing extra info */
1291         }
1292         else if ((la->type==LA_SPOT) || (la->type==LA_YF_PHOTON)) {
1293                 lvec[0]=lvec[1]= 0.0;
1294                 lvec[2] = 1.0;
1295                 x = rv3d->persmat[0][2];
1296                 y = rv3d->persmat[1][2];
1297                 z = rv3d->persmat[2][2];
1298                 vvec[0]= x*ob->obmat[0][0] + y*ob->obmat[0][1] + z*ob->obmat[0][2];
1299                 vvec[1]= x*ob->obmat[1][0] + y*ob->obmat[1][1] + z*ob->obmat[1][2];
1300                 vvec[2]= x*ob->obmat[2][0] + y*ob->obmat[2][1] + z*ob->obmat[2][2];
1301
1302                 y = cosf(la->spotsize*(float)(M_PI/360.0));
1303                 spotvolume(lvec, vvec, y);
1304                 x = -la->dist;
1305                 mul_v3_fl(lvec, x);
1306                 mul_v3_fl(vvec, x);
1307
1308                 /* draw the angled sides of the cone */
1309                 glBegin(GL_LINE_STRIP);
1310                 glVertex3fv(vvec);
1311                 glVertex3fv(vec);
1312                 glVertex3fv(lvec);
1313                 glEnd();
1314                 
1315                 z = x*sqrtf(1.0f - y*y);
1316                 x *= y;
1317
1318                 /* draw the circle/square at the end of the cone */
1319                 glTranslatef(0.0, 0.0 ,  x);
1320                 if (la->mode & LA_SQUARE) {
1321                         float tvec[3];
1322                         float z_abs= fabs(z);
1323
1324                         tvec[0]= tvec[1]= z_abs;
1325                         tvec[2]= 0.0;
1326
1327                         glBegin(GL_LINE_LOOP);
1328                         glVertex3fv(tvec);
1329                         tvec[1]= -z_abs; /* neg */
1330                         glVertex3fv(tvec);
1331                         tvec[0]= -z_abs; /* neg */
1332                         glVertex3fv(tvec);
1333                         tvec[1]= z_abs; /* pos */
1334                         glVertex3fv(tvec);
1335                         glEnd();
1336                 }
1337                 else circ(0.0, 0.0, fabsf(z));
1338                 
1339                 /* draw the circle/square representing spotbl */
1340                 if (la->type==LA_SPOT) {
1341                         float spotblcirc = fabs(z)*(1 - pow(la->spotblend, 2));
1342                         /* hide line if it is zero size or overlaps with outer border,
1343                          * previously it adjusted to always to show it but that seems
1344                          * confusing because it doesn't show the actual blend size */
1345                         if (spotblcirc != 0 && spotblcirc != fabsf(z))
1346                                 circ(0.0, 0.0, spotblcirc);
1347                 }
1348
1349                 if (drawcone)
1350                         draw_transp_spot_volume(la, x, z);
1351
1352                 /* draw clip start, useful for wide cones where its not obvious where the start is */
1353                 glTranslatef(0.0, 0.0 , -x); /* reverse translation above */
1354                 if (la->type==LA_SPOT && (la->mode & LA_SHAD_BUF) ) {
1355                         float lvec_clip[3];
1356                         float vvec_clip[3];
1357                         float clipsta_fac= la->clipsta / -x;
1358
1359                         interp_v3_v3v3(lvec_clip, vec, lvec, clipsta_fac);
1360                         interp_v3_v3v3(vvec_clip, vec, vvec, clipsta_fac);
1361
1362                         glBegin(GL_LINE_STRIP);
1363                         glVertex3fv(lvec_clip);
1364                         glVertex3fv(vvec_clip);
1365                         glEnd();
1366                 }
1367         }
1368         else if ELEM(la->type, LA_HEMI, LA_SUN) {
1369                 
1370                 /* draw the line from the circle along the dist */
1371                 glBegin(GL_LINE_STRIP);
1372                 vec[2] = -circrad;
1373                 glVertex3fv(vec);
1374                 vec[2]= -la->dist;
1375                 glVertex3fv(vec);
1376                 glEnd();
1377                 
1378                 if (la->type==LA_HEMI) {
1379                         /* draw the hemisphere curves */
1380                         short axis, steps, dir;
1381                         float outdist, zdist, mul;
1382                         zero_v3(vec);
1383                         outdist = 0.14; mul = 1.4; dir = 1;
1384                         
1385                         setlinestyle(4);
1386                         /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
1387                         for (axis=0; axis<4; axis++) {
1388                                 float v[3]= {0.0, 0.0, 0.0};
1389                                 zdist = 0.02;
1390                                 
1391                                 glBegin(GL_LINE_STRIP);
1392                                 
1393                                 for (steps=0; steps<6; steps++) {
1394                                         if (axis == 0 || axis == 1) {           /* x axis up, x axis down */
1395                                                 /* make the arcs start at the edge of the energy circle */
1396                                                 if (steps == 0) v[0] = dir*circrad;
1397                                                 else v[0] = v[0] + dir*(steps*outdist);
1398                                         }
1399                                         else if (axis == 2 || axis == 3) {              /* y axis up, y axis down */
1400                                                 /* make the arcs start at the edge of the energy circle */
1401                                                 v[1] = (steps == 0) ? (dir * circrad) : (v[1] + dir * (steps * outdist));
1402                                         }
1403
1404                                         v[2] = v[2] - steps*zdist;
1405                                         
1406                                         glVertex3fv(v);
1407                                         
1408                                         zdist = zdist * mul;
1409                                 }
1410                                 
1411                                 glEnd();
1412                                 /* flip the direction */
1413                                 dir = -dir;
1414                         }
1415                 }
1416         }
1417         else if (la->type==LA_AREA) {
1418                 setlinestyle(3);
1419                 if (la->area_shape==LA_AREA_SQUARE)
1420                         fdrawbox(-la->area_size*0.5f, -la->area_size*0.5f, la->area_size*0.5f, la->area_size*0.5f);
1421                 else if (la->area_shape==LA_AREA_RECT)
1422                         fdrawbox(-la->area_size*0.5f, -la->area_sizey*0.5f, la->area_size*0.5f, la->area_sizey*0.5f);
1423
1424                 glBegin(GL_LINE_STRIP);
1425                 glVertex3f(0.0,0.0,-circrad);
1426                 glVertex3f(0.0,0.0,-la->dist);
1427                 glEnd();
1428         }
1429         
1430         /* and back to viewspace */
1431         glLoadMatrixf(rv3d->viewmat);
1432         copy_v3_v3(vec, ob->obmat[3]);
1433
1434         setlinestyle(0);
1435         
1436         if ((la->type == LA_SPOT) && (la->mode & LA_SHAD_BUF) && (is_view == FALSE)) {
1437                 drawshadbuflimits(la, ob->obmat);
1438         }
1439         
1440         UI_GetThemeColor4ubv(TH_LAMP, col);
1441         glColor4ubv(col);
1442
1443         glEnable(GL_BLEND);
1444         
1445         if (vec[2]>0) vec[2] -= circrad;
1446         else vec[2] += circrad;
1447         
1448         glBegin(GL_LINE_STRIP);
1449         glVertex3fv(vec);
1450         vec[2]= 0;
1451         glVertex3fv(vec);
1452         glEnd();
1453         
1454         glPointSize(2.0);
1455         glBegin(GL_POINTS);
1456         glVertex3fv(vec);
1457         glEnd();
1458         glPointSize(1.0);
1459         
1460         glDisable(GL_BLEND);
1461         
1462         /* restore for drawing extra stuff */
1463         glColor3fv(curcol);
1464
1465 }
1466
1467 static void draw_limit_line(float sta, float end, unsigned int col)
1468 {
1469         glBegin(GL_LINES);
1470         glVertex3f(0.0, 0.0, -sta);
1471         glVertex3f(0.0, 0.0, -end);
1472         glEnd();
1473
1474         glPointSize(3.0);
1475         glBegin(GL_POINTS);
1476         cpack(col);
1477         glVertex3f(0.0, 0.0, -sta);
1478         glVertex3f(0.0, 0.0, -end);
1479         glEnd();
1480         glPointSize(1.0);
1481 }               
1482
1483
1484 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
1485 /* qdn: now also enabled for Blender to set focus point for defocus composite node */
1486 static void draw_focus_cross(float dist, float size)
1487 {
1488         glBegin(GL_LINES);
1489         glVertex3f(-size, 0.f, -dist);
1490         glVertex3f(size, 0.f, -dist);
1491         glVertex3f(0.f, -size, -dist);
1492         glVertex3f(0.f, size, -dist);
1493         glEnd();
1494 }
1495
1496 #ifdef VIEW3D_CAMERA_BORDER_HACK
1497 float view3d_camera_border_hack_col[4];
1498 short view3d_camera_border_hack_test= FALSE;
1499 #endif
1500
1501 /* ****************** draw clip data *************** */
1502
1503 static void draw_bundle_sphere(void)
1504 {
1505         static GLuint displist= 0;
1506
1507         if (displist == 0) {
1508                 GLUquadricObj *qobj;
1509
1510                 displist= glGenLists(1);
1511                 glNewList(displist, GL_COMPILE);
1512
1513                 qobj= gluNewQuadric();
1514                 gluQuadricDrawStyle(qobj, GLU_FILL);
1515                 glShadeModel(GL_SMOOTH);
1516                 gluSphere(qobj, 0.05, 8, 8);
1517                 glShadeModel(GL_FLAT);
1518                 gluDeleteQuadric(qobj);
1519
1520                 glEndList();
1521         }
1522
1523         glCallList(displist);
1524 }
1525
1526 static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D *v3d,
1527                                                 MovieClip *clip, MovieTrackingObject *tracking_object, int flag,
1528                                                 int *global_track_index, int draw_selected)
1529 {
1530         MovieTracking *tracking= &clip->tracking;
1531         MovieTrackingTrack *track;
1532         float mat[4][4], imat[4][4];
1533         unsigned char col[4], scol[4];
1534         int tracknr= *global_track_index;
1535         ListBase *tracksbase= BKE_tracking_object_tracks(tracking, tracking_object);
1536
1537         UI_GetThemeColor4ubv(TH_TEXT, col);
1538         UI_GetThemeColor4ubv(TH_SELECT, scol);
1539
1540         BKE_get_tracking_mat(scene, base->object, mat);
1541
1542         glPushMatrix();
1543
1544         if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
1545                 /* current ogl matrix is translated in camera space, bundles should
1546                  * be rendered in world space, so camera matrix should be "removed"
1547                  * from current ogl matrix */
1548                 invert_m4_m4(imat, base->object->obmat);
1549
1550                 glMultMatrixf(imat);
1551                 glMultMatrixf(mat);
1552         }
1553         else {
1554                 float obmat[4][4];
1555
1556                 BKE_tracking_get_interpolated_camera(tracking, tracking_object, scene->r.cfra, obmat);
1557
1558                 invert_m4_m4(imat, obmat);
1559                 glMultMatrixf(imat);
1560         }
1561
1562         for (track= tracksbase->first; track; track= track->next) {
1563                 int selected= TRACK_SELECTED(track);
1564
1565                 if (draw_selected && !selected)
1566                         continue;
1567
1568                 if ((track->flag&TRACK_HAS_BUNDLE)==0)
1569                         continue;
1570
1571                 if (flag&DRAW_PICKING)
1572                         glLoadName(base->selcol + (tracknr<<16));
1573
1574                 glPushMatrix();
1575                 glTranslatef(track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]);
1576                 glScalef(v3d->bundle_size/0.05f, v3d->bundle_size/0.05f, v3d->bundle_size/0.05f);
1577
1578                 if (v3d->drawtype==OB_WIRE) {
1579                         glDisable(GL_LIGHTING);
1580
1581                         if (selected) {
1582                                 if (base==BASACT) UI_ThemeColor(TH_ACTIVE);
1583                                 else UI_ThemeColor(TH_SELECT);
1584                         }
1585                         else {
1586                                 if (track->flag&TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1587                                 else UI_ThemeColor(TH_WIRE);
1588                         }
1589
1590                         drawaxes(0.05f, v3d->bundle_drawtype);
1591
1592                         glEnable(GL_LIGHTING);
1593                 }
1594                 else if (v3d->drawtype>OB_WIRE) {
1595                         if (v3d->bundle_drawtype==OB_EMPTY_SPHERE) {
1596                                 /* selection outline */
1597                                 if (selected) {
1598                                         if (base==BASACT) UI_ThemeColor(TH_ACTIVE);
1599                                         else UI_ThemeColor(TH_SELECT);
1600
1601                                         glLineWidth(2.f);
1602                                         glDisable(GL_LIGHTING);
1603                                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1604
1605                                         draw_bundle_sphere();
1606
1607                                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1608                                         glEnable(GL_LIGHTING);
1609                                         glLineWidth(1.f);
1610                                 }
1611
1612                                 if (track->flag&TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1613                                 else UI_ThemeColor(TH_BUNDLE_SOLID);
1614
1615                                 draw_bundle_sphere();
1616                         }
1617                         else {
1618                                 glDisable(GL_LIGHTING);
1619
1620                                 if (selected) {
1621                                         if (base==BASACT) UI_ThemeColor(TH_ACTIVE);
1622                                         else UI_ThemeColor(TH_SELECT);
1623                                 }
1624                                 else {
1625                                         if (track->flag&TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1626                                         else UI_ThemeColor(TH_WIRE);
1627                                 }
1628
1629                                 drawaxes(0.05f, v3d->bundle_drawtype);
1630
1631                                 glEnable(GL_LIGHTING);
1632                         }
1633                 }
1634
1635                 glPopMatrix();
1636
1637                 if ((flag & DRAW_PICKING)==0 && (v3d->flag2&V3D_SHOW_BUNDLENAME)) {
1638                         float pos[3];
1639                         unsigned char tcol[4];
1640
1641                         if (selected) memcpy(tcol, scol, sizeof(tcol));
1642                         else memcpy(tcol, col, sizeof(tcol));
1643
1644                         mul_v3_m4v3(pos, mat, track->bundle_pos);
1645                         view3d_cached_text_draw_add(pos, track->name, 10, V3D_CACHE_TEXT_GLOBALSPACE, tcol);
1646                 }
1647
1648                 tracknr++;
1649         }
1650
1651         if ((flag & DRAW_PICKING)==0) {
1652                 if ((v3d->flag2&V3D_SHOW_CAMERAPATH) && (tracking_object->flag&TRACKING_OBJECT_CAMERA)) {
1653                         MovieTrackingReconstruction *reconstruction;
1654                         reconstruction= BKE_tracking_object_reconstruction(tracking, tracking_object);
1655
1656                         if (reconstruction->camnr) {
1657                                 MovieReconstructedCamera *camera= reconstruction->cameras;
1658                                 int a= 0;
1659
1660                                 glDisable(GL_LIGHTING);
1661                                 UI_ThemeColor(TH_CAMERA_PATH);
1662                                 glLineWidth(2.0f);
1663
1664                                 glBegin(GL_LINE_STRIP);
1665                                 for (a= 0; a<reconstruction->camnr; a++, camera++) {
1666                                         glVertex3fv(camera->mat[3]);
1667                                 }
1668                                 glEnd();
1669
1670                                 glLineWidth(1.0f);
1671                                 glEnable(GL_LIGHTING);
1672                         }
1673                 }
1674         }
1675
1676         glPopMatrix();
1677
1678         *global_track_index= tracknr;
1679 }
1680
1681 static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, MovieClip *clip,
1682                                          int flag, int draw_selected)
1683 {
1684         MovieTracking *tracking= &clip->tracking;
1685         MovieTrackingObject *tracking_object;
1686         float curcol[4];
1687         int global_track_index= 1;
1688
1689         if ((v3d->flag2&V3D_SHOW_RECONSTRUCTION)==0)
1690                 return;
1691
1692         if (v3d->flag2&V3D_RENDER_OVERRIDE)
1693                 return;
1694
1695         glGetFloatv(GL_CURRENT_COLOR, curcol);
1696
1697         glEnable(GL_LIGHTING);
1698         glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1699         glEnable(GL_COLOR_MATERIAL);
1700         glShadeModel(GL_SMOOTH);
1701
1702         tracking_object= tracking->objects.first;
1703         while (tracking_object) {
1704                 draw_viewport_object_reconstruction(scene, base, v3d, clip, tracking_object,
1705                                                     flag, &global_track_index, draw_selected);
1706
1707                 tracking_object= tracking_object->next;
1708         }
1709
1710         /* restore */
1711         glShadeModel(GL_FLAT);
1712         glDisable(GL_COLOR_MATERIAL);
1713         glDisable(GL_LIGHTING);
1714
1715         glColor4fv(curcol);
1716
1717         if (flag&DRAW_PICKING)
1718                 glLoadName(base->selcol);
1719 }
1720
1721 /* flag similar to draw_object() */
1722 static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int flag)
1723 {
1724         /* a standing up pyramid with (0,0,0) as top */
1725         Camera *cam;
1726         Object *ob= base->object;
1727         float tvec[3];
1728         float vec[4][3], asp[2], shift[2], scale[3];
1729         int i;
1730         float drawsize;
1731         const short is_view= (rv3d->persp==RV3D_CAMOB && ob==v3d->camera);
1732         MovieClip *clip= object_get_movieclip(scene, base->object, 0);
1733
1734         /* draw data for movie clip set as active for scene */
1735         if (clip) {
1736                 draw_viewport_reconstruction(scene, base, v3d, clip, flag, FALSE);
1737                 draw_viewport_reconstruction(scene, base, v3d, clip, flag, TRUE);
1738         }
1739
1740 #ifdef VIEW3D_CAMERA_BORDER_HACK
1741         if (is_view && !(G.f & G_PICKSEL)) {
1742                 glGetFloatv(GL_CURRENT_COLOR, view3d_camera_border_hack_col);
1743                 view3d_camera_border_hack_test= TRUE;
1744                 return;
1745         }
1746 #endif
1747
1748         cam= ob->data;
1749
1750         scale[0]= 1.0f / len_v3(ob->obmat[0]);
1751         scale[1]= 1.0f / len_v3(ob->obmat[1]);
1752         scale[2]= 1.0f / len_v3(ob->obmat[2]);
1753
1754         camera_view_frame_ex(scene, cam, cam->drawsize, is_view, scale,
1755                              asp, shift, &drawsize, vec);
1756
1757         glDisable(GL_LIGHTING);
1758         glDisable(GL_CULL_FACE);
1759
1760         /* camera frame */
1761         glBegin(GL_LINE_LOOP);
1762         glVertex3fv(vec[0]);
1763         glVertex3fv(vec[1]);
1764         glVertex3fv(vec[2]);
1765         glVertex3fv(vec[3]);
1766         glEnd();
1767
1768         if (is_view)
1769                 return;
1770
1771         zero_v3(tvec);
1772
1773         /* center point to camera frame */
1774         glBegin(GL_LINE_STRIP);
1775         glVertex3fv(vec[1]);
1776         glVertex3fv(tvec);
1777         glVertex3fv(vec[0]);
1778         glVertex3fv(vec[3]);
1779         glVertex3fv(tvec);
1780         glVertex3fv(vec[2]);
1781         glEnd();
1782
1783
1784         /* arrow on top */
1785         tvec[2]= vec[1][2]; /* copy the depth */
1786
1787
1788         /* draw an outline arrow for inactive cameras and filled
1789          * for active cameras. We actually draw both outline+filled
1790          * for active cameras so the wire can be seen side-on */
1791         for (i=0;i<2;i++) {
1792                 if (i==0) glBegin(GL_LINE_LOOP);
1793                 else if (i==1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1794                 else break;
1795
1796                 tvec[0]= shift[0] + ((-0.7f * drawsize) * scale[0]);
1797                 tvec[1]= shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]);
1798                 glVertex3fv(tvec); /* left */
1799                 
1800                 tvec[0]= shift[0] + ((0.7f * drawsize) * scale[0]);
1801                 glVertex3fv(tvec); /* right */
1802                 
1803                 tvec[0]= shift[0];
1804                 tvec[1]= shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]);
1805                 glVertex3fv(tvec); /* top */
1806
1807                 glEnd();
1808         }
1809
1810         if (flag==0) {
1811                 if (cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
1812                         float nobmat[4][4];
1813                         World *wrld;
1814
1815                         /* draw in normalized object matrix space */
1816                         copy_m4_m4(nobmat, ob->obmat);
1817                         normalize_m4(nobmat);
1818
1819                         glPushMatrix();
1820                         glLoadMatrixf(rv3d->viewmat);
1821                         glMultMatrixf(nobmat);
1822
1823                         if (cam->flag & CAM_SHOWLIMITS) {
1824                                 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
1825                                 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composite node */
1826                                 draw_focus_cross(object_camera_dof_distance(ob), cam->drawsize);
1827                         }
1828
1829                         wrld= scene->world;
1830                         if (cam->flag & CAM_SHOWMIST)
1831                                 if (wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
1832
1833                         glPopMatrix();
1834                 }
1835         }
1836 }
1837
1838 /* flag similar to draw_object() */
1839 static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D *UNUSED(rv3d),
1840                         Object *UNUSED(ob), int UNUSED(flag))
1841 {
1842         //Speaker *spk = ob->data;
1843
1844         float vec[3];
1845         int i, j;
1846
1847         glEnable(GL_BLEND);
1848
1849         for (j = 0; j < 3; j++) {
1850                 vec[2] = 0.25f * j -0.125f;
1851
1852                 glBegin(GL_LINE_LOOP);
1853                 for (i = 0; i < 16; i++) {
1854                         vec[0] = cosf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1855                         vec[1] = sinf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1856                         glVertex3fv(vec);
1857                 }
1858                 glEnd();
1859         }
1860
1861         for (j = 0; j < 4; j++) {
1862                 vec[0] = (((j + 1) % 2) * (j - 1)) * 0.5f;
1863                 vec[1] = ((j % 2) * (j - 2)) * 0.5f;
1864                 glBegin(GL_LINE_STRIP);
1865                 for (i = 0; i < 3; i++) {
1866                         if (i == 1) {
1867                                 vec[0] *= 0.5f;
1868                                 vec[1] *= 0.5f;
1869                         }
1870
1871                         vec[2] = 0.25f * i -0.125f;
1872                         glVertex3fv(vec);
1873                 }
1874                 glEnd();
1875         }
1876
1877         glDisable(GL_BLEND);
1878 }
1879
1880 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1881 {
1882         BPoint *bp = lt->def;
1883         float *co = dl?dl->verts:NULL;
1884         int u, v, w;
1885
1886         UI_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
1887         glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1888         bglBegin(GL_POINTS);
1889
1890         for (w=0; w<lt->pntsw; w++) {
1891                 int wxt = (w==0 || w==lt->pntsw-1);
1892                 for (v=0; v<lt->pntsv; v++) {
1893                         int vxt = (v==0 || v==lt->pntsv-1);
1894                         for (u=0; u<lt->pntsu; u++, bp++, co+=3) {
1895                                 int uxt = (u==0 || u==lt->pntsu-1);
1896                                 if (!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1897                                         if (bp->hide==0) {
1898                                                 if ((bp->f1 & SELECT)==sel) {
1899                                                         bglVertex3fv(dl?co:bp->vec);
1900                                                 }
1901                                         }
1902                                 }
1903                         }
1904                 }
1905         }
1906         
1907         glPointSize(1.0);
1908         bglEnd();
1909 }
1910
1911 void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
1912 {
1913         Object *obedit= vc->obedit;
1914         Lattice *lt= obedit->data;
1915         BPoint *bp = lt->editlatt->latt->def;
1916         DispList *dl = find_displist(&obedit->disp, DL_VERTS);
1917         float *co = dl?dl->verts:NULL;
1918         int i, N = lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
1919         short s[2] = {IS_CLIPPED, 0};
1920
1921         ED_view3d_clipping_local(vc->rv3d, obedit->obmat); /* for local clipping lookups */
1922
1923         for (i=0; i<N; i++, bp++, co+=3) {
1924                 if (bp->hide==0) {
1925                         view3d_project_short_clip(vc->ar, dl?co:bp->vec, s, TRUE);
1926                         if (s[0] != IS_CLIPPED)
1927                                 func(userData, bp, s[0], s[1]);
1928                 }
1929         }
1930 }
1931
1932 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1933 {
1934         int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
1935
1936         if (use_wcol) {
1937                 float col[3];
1938                 MDeformWeight *mdw= defvert_find_index (lt->dvert+index, use_wcol-1);
1939                 
1940                 weight_to_rgb(col, mdw?mdw->weight:0.0f);
1941                 glColor3fv(col);
1942
1943         }
1944         
1945         if (dl) {
1946                 glVertex3fv(&dl->verts[index*3]);
1947         }
1948         else {
1949                 glVertex3fv(lt->def[index].vec);
1950         }
1951 }
1952
1953 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1954 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1955 {
1956         Lattice *lt= ob->data;
1957         DispList *dl;
1958         int u, v, w;
1959         int use_wcol= 0, is_edit= (lt->editlatt != NULL);
1960
1961         /* now we default make displist, this will modifiers work for non animated case */
1962         if (ob->disp.first==NULL)
1963                 lattice_calc_modifiers(scene, ob);
1964         dl= find_displist(&ob->disp, DL_VERTS);
1965         
1966         if (is_edit) {
1967                 lt= lt->editlatt->latt;
1968
1969                 cpack(0x004000);
1970                 
1971                 if (ob->defbase.first && lt->dvert) {
1972                         use_wcol= ob->actdef;
1973                         glShadeModel(GL_SMOOTH);
1974                 }
1975         }
1976         
1977         glBegin(GL_LINES);
1978         for (w=0; w<lt->pntsw; w++) {
1979                 int wxt = (w==0 || w==lt->pntsw-1);
1980                 for (v=0; v<lt->pntsv; v++) {
1981                         int vxt = (v==0 || v==lt->pntsv-1);
1982                         for (u=0; u<lt->pntsu; u++) {
1983                                 int uxt = (u==0 || u==lt->pntsu-1);
1984
1985                                 if (w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1986                                         drawlattice__point(lt, dl, u, v, w-1, use_wcol);
1987                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1988                                 }
1989                                 if (v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1990                                         drawlattice__point(lt, dl, u, v-1, w, use_wcol);
1991                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1992                                 }
1993                                 if (u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1994                                         drawlattice__point(lt, dl, u-1, v, w, use_wcol);
1995                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1996                                 }
1997                         }
1998                 }
1999         }
2000         glEnd();
2001         
2002         /* restoration for weight colors */
2003         if (use_wcol)
2004                 glShadeModel(GL_FLAT);
2005
2006         if (is_edit) {
2007                 if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
2008                 
2009                 lattice_draw_verts(lt, dl, 0);
2010                 lattice_draw_verts(lt, dl, 1);
2011                 
2012                 if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
2013         }
2014 }
2015
2016 /* ***************** ******************** */
2017
2018 /* Note! - foreach funcs should be called while drawing or directly after
2019  * if not, ED_view3d_init_mats_rv3d() can be used for selection tools
2020  * but would not give correct results with dupli's for eg. which don't
2021  * use the object matrix in the usual way */
2022 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2023 {
2024         foreachScreenVert_userData *data = userData;
2025         BMVert *eve = EDBM_get_vert_for_index(data->vc.em, index);
2026
2027         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
2028                 short s[2]= {IS_CLIPPED, 0};
2029
2030                 if (data->clipVerts != V3D_CLIP_TEST_OFF) {
2031                         view3d_project_short_clip(data->vc.ar, co, s, TRUE);
2032                 }
2033                 else {
2034                         float co2[2];
2035                         mul_v3_m4v3(co2, data->vc.obedit->obmat, co);
2036                         project_short_noclip(data->vc.ar, co2, s);
2037                 }
2038
2039                 if (s[0]!=IS_CLIPPED)
2040                         data->func(data->userData, eve, s[0], s[1], index);
2041         }
2042 }
2043
2044 void mesh_foreachScreenVert(
2045         ViewContext *vc,
2046         void (*func)(void *userData, BMVert *eve, int x, int y, int index),
2047         void *userData, eV3DClipTest clipVerts)
2048 {
2049         foreachScreenVert_userData data;
2050         DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
2051         
2052         data.vc= *vc;
2053         data.func = func;
2054         data.userData = userData;
2055         data.clipVerts = clipVerts;
2056
2057         if (clipVerts != V3D_CLIP_TEST_OFF)
2058                 ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2059
2060         EDBM_init_index_arrays(vc->em, 1, 0, 0);
2061         dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
2062         EDBM_free_index_arrays(vc->em);
2063
2064         dm->release(dm);
2065 }
2066
2067 /*  draw callback */
2068 static void drawSelectedVertices__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2069 {
2070         MVert *mv = &((MVert *)userData)[index];
2071
2072         if (!(mv->flag & ME_HIDE)) {
2073                 const char sel= mv->flag & SELECT;
2074
2075                 // TODO define selected color
2076                 if (sel) {
2077                         glColor3f(1.0f, 1.0f, 0.0f);
2078                 }
2079                 else {
2080                         glColor3f(0.0f, 0.0f, 0.0f);
2081                 }
2082
2083                 glVertex3fv(co);
2084         }
2085 }
2086
2087 static void drawSelectedVertices(DerivedMesh *dm, Mesh *me)
2088 {
2089         glBegin(GL_POINTS);
2090         dm->foreachMappedVert(dm, drawSelectedVertices__mapFunc, me->mvert);
2091         glEnd();
2092 }
2093 static int is_co_in_region(ARegion *ar, const short co[2])
2094 {
2095         return ((co[0] != IS_CLIPPED) && /* may be the only initialized value, check first */
2096                 (co[0] >= 0)          &&
2097                 (co[0] <  ar->winx)   &&
2098                 (co[1] >= 0)          &&
2099                 (co[1] <  ar->winy));
2100 }
2101 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
2102 {
2103         foreachScreenEdge_userData *data = userData;
2104         BMEdge *eed = EDBM_get_edge_for_index(data->vc.em, index);
2105
2106         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
2107                 short s[2][2];
2108
2109                 if (data->clipVerts == V3D_CLIP_TEST_RV3D_CLIPPING) {
2110                         view3d_project_short_clip(data->vc.ar, v0co, s[0], TRUE);
2111                         view3d_project_short_clip(data->vc.ar, v1co, s[1], TRUE);
2112                 }
2113                 else {
2114                         float v1_co[3], v2_co[3];
2115
2116                         mul_v3_m4v3(v1_co, data->vc.obedit->obmat, v0co);
2117                         mul_v3_m4v3(v2_co, data->vc.obedit->obmat, v1co);
2118
2119                         project_short_noclip(data->vc.ar, v1_co, s[0]);
2120                         project_short_noclip(data->vc.ar, v2_co, s[1]);
2121
2122                         if (data->clipVerts == V3D_CLIP_TEST_REGION) {
2123                                 if ( !is_co_in_region(data->vc.ar, s[0]) &&
2124                                      !is_co_in_region(data->vc.ar, s[1]))
2125                                 {
2126                                         return;
2127                                 }
2128                         }
2129                 }
2130
2131                 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
2132         }
2133 }
2134
2135 void mesh_foreachScreenEdge(
2136         ViewContext *vc,
2137         void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index),
2138         void *userData, eV3DClipTest clipVerts)
2139 {
2140         foreachScreenEdge_userData data;
2141         DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
2142
2143         data.vc= *vc;
2144         data.func = func;
2145         data.userData = userData;
2146         data.clipVerts = clipVerts;
2147
2148         if (clipVerts != V3D_CLIP_TEST_OFF)
2149                 ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2150
2151         EDBM_init_index_arrays(vc->em, 0, 1, 0);
2152         dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
2153         EDBM_free_index_arrays(vc->em);
2154
2155         dm->release(dm);
2156 }
2157
2158 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
2159 {
2160         foreachScreenFace_userData *data = userData;
2161         BMFace *efa = EDBM_get_face_for_index(data->vc.em, index);
2162
2163         if (efa && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
2164                 float cent2[3];
2165                 short s[2];
2166
2167                 mul_v3_m4v3(cent2, data->vc.obedit->obmat, cent);
2168                 project_short(data->vc.ar, cent2, s);
2169
2170                 if (s[0] != IS_CLIPPED) {
2171                         data->func(data->userData, efa, s[0], s[1], index);
2172                 }
2173         }
2174 }
2175
2176 void mesh_foreachScreenFace(
2177         ViewContext *vc,
2178         void (*func)(void *userData, BMFace *efa, int x, int y, int index),
2179         void *userData)
2180 {
2181         foreachScreenFace_userData data;
2182         DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
2183
2184         data.vc= *vc;
2185         data.func = func;
2186         data.userData = userData;
2187
2188         //if (clipVerts)
2189         ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2190
2191         EDBM_init_index_arrays(vc->em, 0, 0, 1);
2192         dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
2193         EDBM_free_index_arrays(vc->em);
2194
2195         dm->release(dm);
2196 }
2197
2198 void nurbs_foreachScreenVert(
2199         ViewContext *vc,
2200         void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y),
2201         void *userData)
2202 {
2203         Curve *cu= vc->obedit->data;
2204         short s[2] = {IS_CLIPPED, 0};
2205         Nurb *nu;
2206         int i;
2207         ListBase *nurbs= curve_editnurbs(cu);
2208
2209         ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2210
2211         for (nu= nurbs->first; nu; nu=nu->next) {
2212                 if (nu->type == CU_BEZIER) {
2213                         for (i=0; i<nu->pntsu; i++) {
2214                                 BezTriple *bezt = &nu->bezt[i];
2215
2216                                 if (bezt->hide==0) {
2217                                         
2218                                         if (cu->drawflag & CU_HIDE_HANDLES) {
2219                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, TRUE);
2220                                                 if (s[0] != IS_CLIPPED)
2221                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
2222                                         }
2223                                         else {
2224                                                 view3d_project_short_clip(vc->ar, bezt->vec[0], s, TRUE);
2225                                                 if (s[0] != IS_CLIPPED)
2226                                                         func(userData, nu, NULL, bezt, 0, s[0], s[1]);
2227                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, TRUE);
2228                                                 if (s[0] != IS_CLIPPED)
2229                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
2230                                                 view3d_project_short_clip(vc->ar, bezt->vec[2], s, TRUE);
2231                                                 if (s[0] != IS_CLIPPED)
2232                                                         func(userData, nu, NULL, bezt, 2, s[0], s[1]);
2233                                         }
2234                                 }
2235                         }
2236                 }
2237                 else {
2238                         for (i=0; i<nu->pntsu*nu->pntsv; i++) {
2239                                 BPoint *bp = &nu->bp[i];
2240
2241                                 if (bp->hide==0) {
2242                                         view3d_project_short_clip(vc->ar, bp->vec, s, TRUE);
2243                                         if (s[0] != IS_CLIPPED)
2244                                                 func(userData, nu, bp, NULL, -1, s[0], s[1]);
2245                                 }
2246                         }
2247                 }
2248         }
2249 }
2250
2251 /* ************** DRAW MESH ****************** */
2252
2253 /* First section is all the "simple" draw routines, 
2254  * ones that just pass some sort of primitive to GL,
2255  * with perhaps various options to control lighting,
2256  * color, etc.
2257  *
2258  * These routines should not have user interface related
2259  * logic!!!
2260  */
2261
2262 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
2263 {
2264         drawDMNormal_userData *data = userData;
2265         BMFace *efa = EDBM_get_face_for_index(data->em, index);
2266
2267         if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
2268                 glVertex3fv(cent);
2269                 glVertex3f(cent[0] + no[0] * data->normalsize,
2270                            cent[1] + no[1] * data->normalsize,
2271                            cent[2] + no[2] * data->normalsize);
2272         }
2273 }
2274 static void draw_dm_face_normals(BMEditMesh *em, Scene *scene, DerivedMesh *dm) 
2275 {
2276         drawDMNormal_userData data;
2277
2278         data.em = em;
2279         data.normalsize = scene->toolsettings->normalsize;
2280
2281         glBegin(GL_LINES);
2282         dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, &data);
2283         glEnd();
2284 }
2285
2286 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
2287 {
2288         BMFace *efa = EDBM_get_face_for_index(((void **)userData)[0], index);
2289         int sel = *(((int **)userData)[1]);
2290         
2291         if (efa && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && BM_elem_flag_test(efa, BM_ELEM_SELECT)==sel) {
2292                 bglVertex3fv(cent);
2293         }
2294 }
2295 static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, int sel)
2296 {
2297         void *ptrs[2] = {em, &sel};
2298
2299         bglBegin(GL_POINTS);
2300         dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, ptrs);
2301         bglEnd();
2302 }
2303
2304 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
2305 {
2306         drawDMNormal_userData *data = userData;
2307         BMVert *eve = EDBM_get_vert_for_index(data->em, index);
2308
2309         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
2310                 glVertex3fv(co);
2311
2312                 if (no_f) {
2313                         glVertex3f(co[0] + no_f[0] * data->normalsize,
2314                                    co[1] + no_f[1] * data->normalsize,
2315                                    co[2] + no_f[2] * data->normalsize);
2316                 }
2317                 else {
2318                         glVertex3f(co[0] + no_s[0] * (data->normalsize / 32767.0f),
2319                                    co[1] + no_s[1] * (data->normalsize / 32767.0f),
2320                                    co[2] + no_s[2] * (data->normalsize / 32767.0f));
2321                 }
2322         }
2323 }
2324 static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, DerivedMesh *dm) 
2325 {
2326         drawDMNormal_userData data;
2327
2328         data.em = em;
2329         data.normalsize = scene->toolsettings->normalsize;
2330
2331         glBegin(GL_LINES);
2332         dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, &data);
2333         glEnd();
2334 }
2335
2336 /* Draw verts with color set based on selection */
2337 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2338 {
2339         drawDMVerts_userData * data = userData;
2340         BMVert *eve = EDBM_get_vert_for_index(data->em, index);
2341
2342         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT)==data->sel) {
2343                 /* draw active larger - need to stop/start point drawing for this :/ */
2344                 if (eve==data->eve_act) {
2345                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2346                         UI_ThemeColor4(TH_EDITMESH_ACTIVE);
2347                         
2348                         bglEnd();
2349                         
2350                         glPointSize(size);
2351                         bglBegin(GL_POINTS);
2352                         bglVertex3fv(co);
2353                         bglEnd();
2354                         
2355                         UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
2356                         glPointSize(size);
2357                         bglBegin(GL_POINTS);
2358                 }
2359                 else {
2360                         bglVertex3fv(co);
2361                 }
2362         }
2363 }
2364
2365 static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, int sel, BMVert *eve_act)
2366 {
2367         drawDMVerts_userData data;
2368         data.sel = sel;
2369         data.eve_act = eve_act;
2370         data.em = em;
2371
2372         bglBegin(GL_POINTS);
2373         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
2374         bglEnd();
2375 }
2376
2377 /* Draw edges with color set based on selection */
2378 static DMDrawOption draw_dm_edges_sel__setDrawOptions(void *userData, int index)
2379 {
2380         BMEdge *eed;
2381         //unsigned char **cols = userData, *col;
2382         drawDMEdgesSel_userData * data = userData;
2383         unsigned char *col;
2384
2385         eed = EDBM_get_edge_for_index(data->em, index);
2386
2387         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
2388                 if (eed==data->eed_act) {
2389                         glColor4ubv(data->actCol);
2390                 }
2391                 else {
2392                         if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
2393                                 col = data->selCol;
2394                         }
2395                         else {
2396                                 col = data->baseCol;
2397                         }
2398                         /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode  */
2399                         if (col[3]==0)
2400                                 return DM_DRAW_OPTION_SKIP;
2401                         
2402                         glColor4ubv(col);
2403                 }
2404                 return DM_DRAW_OPTION_NORMAL;
2405         }
2406         else {
2407                 return DM_DRAW_OPTION_SKIP;
2408         }
2409 }
2410 static void draw_dm_edges_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, 
2411                               unsigned char *selCol, unsigned char *actCol, BMEdge *eed_act)
2412 {
2413         drawDMEdgesSel_userData data;
2414         
2415         data.baseCol = baseCol;
2416         data.selCol = selCol;
2417         data.actCol = actCol;
2418         data.em = em;
2419         data.eed_act = eed_act;
2420         dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
2421 }
2422
2423 /* Draw edges */
2424 static DMDrawOption draw_dm_edges__setDrawOptions(void *userData, int index)
2425 {
2426         if (BM_elem_flag_test(EDBM_get_edge_for_index(userData, index), BM_ELEM_HIDDEN))
2427                 return DM_DRAW_OPTION_SKIP;
2428         else
2429                 return DM_DRAW_OPTION_NORMAL;
2430 }
2431
2432 static void draw_dm_edges(BMEditMesh *em, DerivedMesh *dm) 
2433 {
2434         dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, em);
2435 }
2436
2437 /* Draw edges with color interpolated based on selection */
2438 static DMDrawOption draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
2439 {
2440         if (BM_elem_flag_test(EDBM_get_edge_for_index(((void**)userData)[0], index), BM_ELEM_HIDDEN))
2441                 return DM_DRAW_OPTION_SKIP;
2442         else
2443                 return DM_DRAW_OPTION_NORMAL;
2444 }
2445 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
2446 {
2447         BMEdge *eed = EDBM_get_edge_for_index(((void**)userData)[0], index);
2448         unsigned char **cols = userData;
2449         unsigned char *col0 = cols[(BM_elem_flag_test(eed->v1, BM_ELEM_SELECT))?2:1];
2450         unsigned char *col1 = cols[(BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))?2:1];
2451
2452         glColor4ub(col0[0] + (col1[0] - col0[0]) * t,
2453                    col0[1] + (col1[1] - col0[1]) * t,
2454                    col0[2] + (col1[2] - col0[2]) * t,
2455                    col0[3] + (col1[3] - col0[3]) * t);
2456 }
2457
2458 static void draw_dm_edges_sel_interp(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
2459 {
2460         void *cols[3] = {em, baseCol, selCol};
2461
2462         dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
2463 }
2464
2465 /* Draw only seam edges */
2466 static DMDrawOption draw_dm_edges_seams__setDrawOptions(void *userData, int index)
2467 {
2468         BMEdge *eed = EDBM_get_edge_for_index(userData, index);
2469
2470         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BM_elem_flag_test(eed, BM_ELEM_SEAM))
2471                 return DM_DRAW_OPTION_NORMAL;
2472         else
2473                 return DM_DRAW_OPTION_SKIP;
2474 }
2475
2476 static void draw_dm_edges_seams(BMEditMesh *em, DerivedMesh *dm)
2477 {
2478         dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, em);
2479 }
2480
2481 /* Draw only sharp edges */
2482 static DMDrawOption draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
2483 {
2484         BMEdge *eed = EDBM_get_edge_for_index(userData, index);
2485
2486         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && !BM_elem_flag_test(eed, BM_ELEM_SMOOTH))
2487                 return DM_DRAW_OPTION_NORMAL;
2488         else
2489                 return DM_DRAW_OPTION_SKIP;
2490 }
2491
2492 static void draw_dm_edges_sharp(BMEditMesh *em, DerivedMesh *dm)
2493 {
2494         dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, em);
2495 }
2496
2497 /* Draw only Freestyle feature edges */
2498 static int draw_dm_edges_freestyle__setDrawOptions(void *userData, int index)
2499 {
2500         BMEdge *eed = EDBM_get_edge_for_index(userData, index);
2501
2502         return !BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BM_elem_flag_test(eed, BM_ELEM_FREESTYLE);
2503 }
2504 static void draw_dm_edges_freestyle(BMEditMesh *em, DerivedMesh *dm)
2505 {
2506         dm->drawMappedEdges(dm, draw_dm_edges_freestyle__setDrawOptions, em);
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_get_face_for_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[3]);
2523                         return DM_DRAW_OPTION_STIPPLE;
2524                 }
2525                 else {
2526                         col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT)?1:BM_elem_flag_test(efa, BM_ELEM_FREESTYLE)?2: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_get_face_for_index(data->em, data->orig_index[index]);
2549         next_efa= EDBM_get_face_for_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:BM_elem_flag_test(efa, BM_ELEM_FREESTYLE)?2:0];
2558         next_col = data->cols[BM_elem_flag_test(next_efa, BM_ELEM_SELECT)?1:BM_elem_flag_test(next_efa, BM_ELEM_FREESTYLE)?2:0];
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 *markCol, 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] = markCol;
2576         data.cols[3] = actCol;
2577         data.efa_act = efa_act;
2578         data.orig_index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
2579
2580         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions, &data, 0);
2581 }
2582
2583 static DMDrawOption draw_dm_creases__setDrawOptions(void *userData, int index)
2584 {
2585         BMEditMesh *em = userData;
2586         BMEdge *eed = EDBM_get_edge_for_index(userData, index);
2587         float *crease = eed ? (float *)CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_CREASE) : NULL;
2588         
2589         if (!crease)
2590                 return DM_DRAW_OPTION_SKIP;
2591         
2592         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && *crease!=0.0f) {
2593                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, *crease);
2594                 return DM_DRAW_OPTION_NORMAL;
2595         }
2596         else {
2597                 return DM_DRAW_OPTION_SKIP;
2598         }
2599 }
2600 static void draw_dm_creases(BMEditMesh *em, DerivedMesh *dm)
2601 {
2602         glLineWidth(3.0);
2603         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, em);
2604         glLineWidth(1.0);
2605 }
2606
2607 static DMDrawOption draw_dm_bweights__setDrawOptions(void *userData, int index)
2608 {
2609         BMEditMesh *em = userData;
2610         BMEdge *eed = EDBM_get_edge_for_index(userData, index);
2611         float *bweight = (float *)CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_BWEIGHT);
2612
2613         if (!bweight)
2614                 return DM_DRAW_OPTION_SKIP;
2615         
2616         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && *bweight!=0.0f) {
2617                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, *bweight);
2618                 return DM_DRAW_OPTION_NORMAL;
2619         }
2620         else {
2621                 return DM_DRAW_OPTION_SKIP;
2622         }
2623 }
2624 static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2625 {
2626         BMEditMesh *em = userData;
2627         BMVert *eve = EDBM_get_vert_for_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_get_face_for_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_get_face_for_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_init_index_arrays(em, 1, 1, 1);
3046
3047         if (dt>OB_WIRE) {
3048                 if (CHECK_OB_DRAWTEXTURE(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], col4[4];
3092
3093                 UI_GetThemeColor4ubv(TH_FACE, col1);
3094                 UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
3095                 UI_GetThemeColor4ubv(TH_FREESTYLE_FACE_MARK, col3);
3096                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col4);
3097                 
3098                 glEnable(GL_BLEND);
3099                 glDepthMask(0);       &nbs