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