style cleanup: add braces around checks - 'if ELEM() {...}', confuses some parsers...
[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[3];
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
2498 /* Draw faces with color set based on selection
2499          * return 2 for the active face so it renders with stipple enabled */
2500 static DMDrawOption draw_dm_faces_sel__setDrawOptions(void *userData, int index)
2501 {
2502         drawDMFacesSel_userData * data = userData;
2503         BMFace *efa = EDBM_get_face_for_index(data->em, index);
2504         unsigned char *col;
2505         
2506         if (!efa)
2507                 return DM_DRAW_OPTION_SKIP;
2508         
2509         if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
2510                 if (efa == data->efa_act) {
2511                         glColor4ubv(data->cols[2]);
2512                         return DM_DRAW_OPTION_STIPPLE;
2513                 }
2514                 else {
2515                         col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT)?1:0];
2516                         if (col[3]==0)
2517                                 return DM_DRAW_OPTION_SKIP;
2518                         glColor4ubv(col);
2519                         return DM_DRAW_OPTION_NORMAL;
2520                 }
2521         }
2522         return DM_DRAW_OPTION_SKIP;
2523 }
2524
2525 static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index)
2526 {
2527
2528         drawDMFacesSel_userData *data = userData;
2529         BMFace *efa;
2530         BMFace *next_efa;
2531
2532         unsigned char *col, *next_col;
2533
2534         if (!data->orig_index)
2535                 return 0;
2536
2537         efa= EDBM_get_face_for_index(data->em, data->orig_index[index]);
2538         next_efa= EDBM_get_face_for_index(data->em, data->orig_index[next_index]);
2539
2540         if (efa == next_efa)
2541                 return 1;
2542
2543         if (efa == data->efa_act || next_efa == data->efa_act)
2544                 return 0;
2545
2546         col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT)?1:0];
2547         next_col = data->cols[BM_elem_flag_test(next_efa, BM_ELEM_SELECT)?1:0];
2548
2549         if (col[3]==0 || next_col[3]==0)
2550                 return 0;
2551
2552         return col == next_col;
2553 }
2554
2555 /* also draws the active face */
2556 static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, 
2557                               unsigned char *selCol, unsigned char *actCol, BMFace *efa_act)
2558 {
2559         drawDMFacesSel_userData data;
2560         data.dm= dm;
2561         data.cols[0] = baseCol;
2562         data.em = em;
2563         data.cols[1] = selCol;
2564         data.cols[2] = actCol;
2565         data.efa_act = efa_act;
2566         data.orig_index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
2567
2568         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions, &data, 0);
2569 }
2570
2571 static DMDrawOption draw_dm_creases__setDrawOptions(void *userData, int index)
2572 {
2573         BMEditMesh *em = userData;
2574         BMEdge *eed = EDBM_get_edge_for_index(userData, index);
2575         float *crease = eed ? (float *)CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_CREASE) : NULL;
2576         
2577         if (!crease)
2578                 return DM_DRAW_OPTION_SKIP;
2579         
2580         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && *crease!=0.0f) {
2581                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, *crease);
2582                 return DM_DRAW_OPTION_NORMAL;
2583         }
2584         else {
2585                 return DM_DRAW_OPTION_SKIP;
2586         }
2587 }
2588 static void draw_dm_creases(BMEditMesh *em, DerivedMesh *dm)
2589 {
2590         glLineWidth(3.0);
2591         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, em);
2592         glLineWidth(1.0);
2593 }
2594
2595 static DMDrawOption draw_dm_bweights__setDrawOptions(void *userData, int index)
2596 {
2597         BMEditMesh *em = userData;
2598         BMEdge *eed = EDBM_get_edge_for_index(userData, index);
2599         float *bweight = (float *)CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_BWEIGHT);
2600
2601         if (!bweight)
2602                 return DM_DRAW_OPTION_SKIP;
2603         
2604         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && *bweight!=0.0f) {
2605                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, *bweight);
2606                 return DM_DRAW_OPTION_NORMAL;
2607         }
2608         else {
2609                 return DM_DRAW_OPTION_SKIP;
2610         }
2611 }
2612 static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2613 {
2614         BMEditMesh *em = userData;
2615         BMVert *eve = EDBM_get_vert_for_index(userData, index);
2616         float *bweight = (float *)CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_BWEIGHT);
2617         
2618         if (!bweight)
2619                 return;
2620         
2621         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && *bweight!=0.0f) {
2622                 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, *bweight);
2623                 bglVertex3fv(co);
2624         }
2625 }
2626 static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
2627 {
2628         ToolSettings *ts= scene->toolsettings;
2629
2630         if (ts->selectmode & SCE_SELECT_VERTEX) {
2631                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2632                 bglBegin(GL_POINTS);
2633                 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, em);
2634                 bglEnd();
2635         }
2636         else {
2637                 glLineWidth(3.0);
2638                 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, em);
2639                 glLineWidth(1.0);
2640         }
2641 }
2642
2643 /* Second section of routines: Combine first sets to form fancy
2644  * drawing routines (for example rendering twice to get overlays).
2645  *
2646  * Also includes routines that are basic drawing but are too
2647  * specialized to be split out (like drawing creases or measurements).
2648  */
2649
2650 /* EditMesh drawing routines*/
2651
2652 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, 
2653                                 BMEditMesh *em, DerivedMesh *cageDM, BMVert *eve_act)
2654 {
2655         ToolSettings *ts= scene->toolsettings;
2656         int sel;
2657
2658         if (v3d->zbuf) glDepthMask(0);          // disable write in zbuffer, zbuf select
2659
2660         for (sel=0; sel<2; sel++) {
2661                 unsigned char col[4], fcol[4];
2662                 int pass;
2663
2664                 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
2665                 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
2666
2667                 for (pass=0; pass<2; pass++) {
2668                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2669                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2670
2671                         if (pass==0) {
2672                                 if (v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
2673                                         glDisable(GL_DEPTH_TEST);
2674
2675                                         glEnable(GL_BLEND);
2676                                 }
2677                                 else {
2678                                         continue;
2679                                 }
2680
2681                                 size = (size > 2.1f ? size/2.0f:size);
2682                                 fsize = (fsize > 2.1f ? fsize/2.0f:fsize);
2683                                 col[3] = fcol[3] = 100;
2684                         }
2685                         else {
2686                                 col[3] = fcol[3] = 255;
2687                         }
2688
2689                         if (ts->selectmode & SCE_SELECT_VERTEX) {
2690                                 glPointSize(size);
2691                                 glColor4ubv(col);
2692                                 draw_dm_verts(em, cageDM, sel, eve_act);
2693                         }
2694                         
2695                         if (check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2696                                 glPointSize(fsize);
2697                                 glColor4ubv(fcol);
2698                                 draw_dm_face_centers(em, cageDM, sel);
2699                         }
2700                         
2701                         if (pass==0) {
2702                                 glDisable(GL_BLEND);
2703                                 glEnable(GL_DEPTH_TEST);
2704                         }
2705                 }
2706         }
2707
2708         if (v3d->zbuf) glDepthMask(1);
2709         glPointSize(1.0);
2710 }
2711
2712 static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d,
2713                                 Mesh *me, DerivedMesh *cageDM, short sel_only,
2714                                 BMEdge *eed_act)
2715 {
2716         ToolSettings *ts= scene->toolsettings;
2717         int pass;
2718         unsigned char wireCol[4], selCol[4], actCol[4];
2719
2720         /* since this function does transparant... */
2721         UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2722         UI_GetThemeColor4ubv(TH_WIRE, wireCol);
2723         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2724         
2725         /* when sel only is used, don't render wire, only selected, this is used for
2726          * textured draw mode when the 'edges' option is disabled */
2727         if (sel_only)
2728                 wireCol[3] = 0;
2729
2730         for (pass=0; pass<2; pass++) {
2731                 /* show wires in transparant when no zbuf clipping for select */
2732                 if (pass==0) {
2733                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
2734                                 glEnable(GL_BLEND);
2735                                 glDisable(GL_DEPTH_TEST);
2736                                 selCol[3] = 85;
2737                                 if (!sel_only) wireCol[3] = 85;
2738                         }
2739                         else {
2740                                 continue;
2741                         }
2742                 }
2743                 else {
2744                         selCol[3] = 255;
2745                         if (!sel_only) wireCol[3] = 255;
2746                 }
2747
2748                 if (ts->selectmode == SCE_SELECT_FACE) {
2749                         draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
2750                 }
2751                 else if ( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {
2752                         if (cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2753                                 glShadeModel(GL_SMOOTH);
2754                                 draw_dm_edges_sel_interp(em, cageDM, wireCol, selCol);
2755                                 glShadeModel(GL_FLAT);
2756                         }
2757                         else {
2758                                 draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
2759                         }
2760                 }
2761                 else {
2762                         if (!sel_only) {
2763                                 glColor4ubv(wireCol);
2764                                 draw_dm_edges(em, cageDM);
2765                         }
2766                 }
2767
2768                 if (pass==0) {
2769                         glDisable(GL_BLEND);
2770                         glEnable(GL_DEPTH_TEST);
2771                 }
2772         }
2773 }       
2774
2775 static void draw_em_measure_stats(View3D *v3d, Object *ob, BMEditMesh *em, UnitSettings *unit)
2776 {
2777         const short txt_flag = V3D_CACHE_TEXT_ASCII | V3D_CACHE_TEXT_LOCALCLIP;
2778         Mesh *me= ob->data;
2779         float v1[3], v2[3], v3[3], vmid[3], fvec[3];
2780         char numstr[32]; /* Stores the measurement display text here */
2781         const char *conv_float; /* Use a float conversion matching the grid size */
2782         unsigned char col[4]= {0, 0, 0, 255}; /* color of the text to draw */
2783         float area; /* area of the face */
2784         float grid= unit->system ? unit->scale_length : v3d->grid;
2785         const int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
2786         const int do_global= v3d->flag & V3D_GLOBAL_STATS;
2787         const int do_moving= G.moving;
2788
2789         BMIter iter;
2790         int i;
2791
2792         /* make the precision of the pronted value proportionate to the gridsize */
2793
2794         if (grid < 0.01f)               conv_float= "%.6g";
2795         else if (grid < 0.1f)   conv_float= "%.5g";
2796         else if (grid < 1.0f)   conv_float= "%.4g";
2797         else if (grid < 10.0f)  conv_float= "%.3g";
2798         else                                    conv_float= "%.2g";
2799         
2800         if (me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2801                 BMEdge *eed;
2802
2803                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2804
2805                 eed = BM_iter_new(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
2806                 for (; eed; eed=BM_iter_step(&iter)) {
2807                         /* draw selected edges, or edges next to selected verts while draging */
2808                         if (BM_elem_flag_test(eed, BM_ELEM_SELECT) ||
2809                             (do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
2810                                            BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))))
2811                         {
2812
2813                                 copy_v3_v3(v1, eed->v1->co);
2814                                 copy_v3_v3(v2, eed->v2->co);
2815
2816                                 mid_v3_v3v3(vmid, v1, v2);
2817
2818                                 if (do_global) {
2819                                         mul_mat3_m4_v3(ob->obmat, v1);
2820                                         mul_mat3_m4_v3(ob->obmat, v2);
2821                                 }
2822
2823                                 if (unit->system) {
2824                                         bUnit_AsString(numstr, sizeof(numstr), len_v3v3(v1, v2) * unit->scale_length, 3,
2825                                                        unit->system, B_UNIT_LENGTH, do_split, FALSE);
2826                                 }
2827                                 else {
2828                                         sprintf(numstr, conv_float, len_v3v3(v1, v2));
2829                                 }
2830
2831                                 view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col);
2832                         }
2833                 }
2834         }
2835
2836         if (me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2837                 /* would be nice to use BM_face_area_calc, but that is for 2d faces
2838                  * so instead add up tessellation triangle areas */
2839                 BMFace *f;
2840                 int n;
2841
2842 #define DRAW_EM_MEASURE_STATS_FACEAREA()                                             \
2843                 if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {                                  \
2844                         mul_v3_fl(vmid, 1.0/n);                                                  \
2845                         if (unit->system)                                                        \
2846                                 bUnit_AsString(numstr, sizeof(numstr), area*unit->scale_length,      \
2847                                         3, unit->system, B_UNIT_LENGTH, do_split, FALSE);                \
2848                         else                                                                     \
2849                                 BLI_snprintf(numstr, sizeof(numstr), conv_float, area);              \
2850                         view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col);             \
2851                 }
2852
2853                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2854                 
2855                 f = NULL;
2856                 area = 0.0;
2857                 zero_v3(vmid);
2858                 n = 0;
2859                 for (i = 0; i < em->tottri; i++) {
2860                         BMLoop **l = em->looptris[i];
2861                         if (f && l[0]->f != f) {
2862                                 DRAW_EM_MEASURE_STATS_FACEAREA();
2863                                 zero_v3(vmid);
2864                                 area = 0.0;
2865                                 n = 0;
2866                         }
2867
2868                         f = l[0]->f;
2869                         copy_v3_v3(v1, l[0]->v->co);
2870                         copy_v3_v3(v2, l[1]->v->co);
2871                         copy_v3_v3(v3, l[2]->v->co);
2872                         if (do_global) {
2873                                 mul_mat3_m4_v3(ob->obmat, v1);
2874                                 mul_mat3_m4_v3(ob->obmat, v2);
2875                                 mul_mat3_m4_v3(ob->obmat, v3);
2876                         }
2877                         area += area_tri_v3(v1, v2, v3);
2878                         add_v3_v3(vmid, v1);
2879                         add_v3_v3(vmid, v2);
2880                         add_v3_v3(vmid, v3);
2881                         n += 3;
2882                 }
2883
2884                 if (f) {
2885                         DRAW_EM_MEASURE_STATS_FACEAREA();
2886                 }
2887 #undef DRAW_EM_MEASURE_STATS_FACEAREA
2888         }
2889
2890         if (me->drawflag & ME_DRAWEXTRA_FACEANG) {
2891                 BMFace *efa;
2892
2893                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2894
2895
2896                 for (efa = BM_iter_new(&iter, em->bm, BM_FACES_OF_MESH, NULL);
2897                      efa; efa=BM_iter_step(&iter))
2898                 {
2899                         BMIter liter;
2900                         BMLoop *loop;
2901
2902                         BM_face_center_bounds_calc(em->bm, efa, vmid);
2903
2904                         for (loop = BM_iter_new(&liter, em->bm, BM_LOOPS_OF_FACE, efa);
2905                              loop; loop = BM_iter_step(&liter))
2906                         {
2907                                 float v1[3], v2[3], v3[3];
2908
2909                                 copy_v3_v3(v1, loop->prev->v->co);
2910                                 copy_v3_v3(v2, loop->v->co);
2911                                 copy_v3_v3(v3, loop->next->v->co);
2912
2913                                 if (do_global) {
2914                                         mul_mat3_m4_v3(ob->obmat, v1);
2915                                         mul_mat3_m4_v3(ob->obmat, v2);
2916                                         mul_mat3_m4_v3(ob->obmat, v3);
2917                                 }
2918
2919                                 if ( (BM_elem_flag_test(efa, BM_ELEM_SELECT)) ||
2920                                      (do_moving && BM_elem_flag_test(loop->v, BM_ELEM_SELECT)))
2921                                 {
2922                                         BLI_snprintf(numstr, sizeof(numstr), "%.3g", RAD2DEGF(angle_v3v3v3(v1, v2, v3)));
2923                                         interp_v3_v3v3(fvec, vmid, v2, 0.8f);
2924                                         view3d_cached_text_draw_add(fvec, numstr, 0, txt_flag, col);
2925                                 }
2926                         }
2927                 }
2928         }
2929 }
2930
2931 static void draw_em_indices(BMEditMesh *em)
2932 {
2933         const short txt_flag = V3D_CACHE_TEXT_ASCII | V3D_CACHE_TEXT_LOCALCLIP;
2934         BMEdge *e;
2935         BMFace *f;
2936         BMVert *v;
2937         int i;
2938         char numstr[32];
2939         float pos[3];
2940         unsigned char col[4];
2941
2942         BMIter iter;
2943         BMesh *bm= em->bm;
2944
2945         /* For now, reuse appropriate theme colors from stats text colors */
2946         i= 0;
2947         if (em->selectmode & SCE_SELECT_VERTEX) {
2948                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2949                 BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
2950                         if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
2951                                 sprintf(numstr, "%d", i);
2952                                 view3d_cached_text_draw_add(v->co, numstr, 0, txt_flag, col);
2953                         }
2954                         i++;
2955                 }
2956         }
2957
2958         if (em->selectmode & SCE_SELECT_EDGE) {
2959                 i= 0;
2960                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2961                 BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
2962                         if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
2963                                 sprintf(numstr, "%d", i);
2964                                 mid_v3_v3v3(pos, e->v1->co, e->v2->co);
2965                                 view3d_cached_text_draw_add(pos, numstr, 0, txt_flag, col);
2966                         }
2967                         i++;
2968                 }
2969         }
2970
2971         if (em->selectmode & SCE_SELECT_FACE) {
2972                 i= 0;
2973                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2974                 BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
2975                         if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
2976                                 BM_face_center_mean_calc(bm, f, pos);
2977                                 sprintf(numstr, "%d", i);
2978                                 view3d_cached_text_draw_add(pos, numstr, 0, txt_flag, col);
2979                         }
2980                         i++;
2981                 }
2982         }
2983 }
2984
2985 static DMDrawOption draw_em_fancy__setFaceOpts(void *userData, int index)
2986 {
2987         BMFace *efa = EDBM_get_face_for_index(userData, index);
2988
2989         if (efa && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
2990                 GPU_enable_material(efa->mat_nr+1, NULL);
2991                 return DM_DRAW_OPTION_NORMAL;
2992         }
2993         else
2994                 return DM_DRAW_OPTION_SKIP;
2995 }
2996
2997 static DMDrawOption draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
2998 {
2999         BMFace *efa = EDBM_get_face_for_index(userData, index);
3000
3001         if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
3002                 return DM_DRAW_OPTION_SKIP;
3003         else
3004                 return DM_DRAW_OPTION_NORMAL;
3005 }
3006
3007 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
3008                           Object *ob, BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
3009
3010 {
3011         Mesh *me = ob->data;
3012         BMFace *efa_act = BM_active_face_get(em->bm, FALSE); /* annoying but active faces is stored differently */
3013         BMEdge *eed_act = NULL;
3014         BMVert *eve_act = NULL;
3015         
3016         if (em->bm->selected.last) {
3017                 BMEditSelection *ese= em->bm->selected.last;
3018                 /* face is handeled above */
3019 #if 0
3020                 if (ese->type == BM_FACE ) {
3021                         efa_act = (BMFace *)ese->data;
3022                 }
3023                 else 
3024 #endif
3025                 if ( ese->htype == BM_EDGE ) {
3026                         eed_act = (BMEdge *)ese->ele;
3027                 }
3028                 else if ( ese->htype == BM_VERT ) {
3029                         eve_act = (BMVert *)ese->ele;
3030                 }
3031         }
3032         
3033         EDBM_init_index_arrays(em, 1, 1, 1);
3034
3035         if (dt>OB_WIRE) {
3036                 if (CHECK_OB_DRAWTEXTURE(v3d, dt)) {
3037                         if (draw_glsl_material(scene, ob, v3d, dt)) {
3038                                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
3039
3040                                 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
3041                                                              draw_em_fancy__setGLSLFaceOpts, em);
3042                                 GPU_disable_material();
3043
3044                                 glFrontFace(GL_CCW);
3045                         }
3046                         else {
3047                                 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
3048                         }
3049                 }
3050                 else {
3051                         /* 3 floats for position,
3052                          * 3 for normal and times two because the faces may actually be quads instead of triangles */
3053                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, (me->flag & ME_TWOSIDED) ? GL_TRUE : GL_FALSE);
3054
3055                         glEnable(GL_LIGHTING);
3056                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
3057                         finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, GPU_enable_material, NULL, me->edit_btmesh, 0);
3058
3059                         glFrontFace(GL_CCW);
3060                         glDisable(GL_LIGHTING);
3061                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
3062                 }
3063
3064                 // Setup for drawing wire over, disable zbuffer
3065                 // write to show selected edge wires better
3066                 UI_ThemeColor(TH_WIRE);
3067
3068                 bglPolygonOffset(rv3d->dist, 1.0);
3069                 glDepthMask(0);
3070         }
3071         else {
3072                 if (cageDM!=finalDM) {
3073                         UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
3074                         finalDM->drawEdges(finalDM, 1, 0);
3075                 }
3076         }
3077         
3078         if (me->drawflag & ME_DRAWFACES) {      /* transp faces */
3079                 unsigned char col1[4], col2[4], col3[4];
3080
3081                 UI_GetThemeColor4ubv(TH_FACE, col1);
3082                 UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
3083                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
3084                 
3085                 glEnable(GL_BLEND);
3086                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
3087                 
3088                 /* don't draw unselected faces, only selected, this is MUCH nicer when texturing */
3089                 if (CHECK_OB_DRAWTEXTURE(v3d, dt))
3090                         col1[3] = 0;
3091                 
3092                 draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act);
3093
3094                 glDisable(GL_BLEND);
3095                 glDepthMask(1);         // restore write in zbuffer
3096         }
3097         else if (efa_act) {