style cleanup - comment spelling + translate some dutch.
[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 dont 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                 for (axis=0; axis<3; axis++) {
597                         const int arrow_axis= (axis==0) ? 1:0;
598
599                         glBegin(GL_LINES);
600                         
601                         v2[axis]= size;
602                         glVertex3fv(v1);
603                         glVertex3fv(v2);
604                                 
605                         v1[axis]= size*0.85f;
606                         v1[arrow_axis]= -size*0.08f;
607                         glVertex3fv(v1);
608                         glVertex3fv(v2);
609                                 
610                         v1[arrow_axis]= size*0.08f;
611                         glVertex3fv(v1);
612                         glVertex3fv(v2);
613                         
614                         glEnd();
615                                 
616                         v2[axis]+= size*0.125f;
617                         
618                         draw_xyz_wire(v2, size, axis);
619                         
620                         
621                         /* reset v1 & v2 to zero */
622                         v1[arrow_axis]= v1[axis]= v2[axis]= 0.0f;
623                 }
624                 break;
625         }
626 }
627
628
629 /* Function to draw an Image on a empty Object */
630 static void draw_empty_image(Object *ob)
631 {
632         Image *ima = (Image*)ob->data;
633         ImBuf *ibuf = ima ? BKE_image_get_ibuf(ima, NULL) : NULL;
634
635         float scale, ofs_x, ofs_y, sca_x, sca_y;
636         int ima_x, ima_y;
637
638         if (ibuf && (ibuf->rect == NULL) && (ibuf->rect_float != NULL)) {
639                 IMB_rect_from_float(ibuf);
640         }
641
642         /* Get the buffer dimensions so we can fallback to fake ones */
643         if (ibuf && ibuf->rect) {
644                 ima_x= ibuf->x;
645                 ima_y= ibuf->y;
646         }
647         else {
648                 ima_x= 1;
649                 ima_y= 1;
650         }
651
652         /* Get the image aspect even if the buffer is invalid */
653         if (ima) {
654                 if (ima->aspx > ima->aspy) {
655                         sca_x= 1.0f;
656                         sca_y= ima->aspy / ima->aspx;
657                 }
658                 else if (ima->aspx < ima->aspy) {
659                         sca_x= ima->aspx / ima->aspy;
660                         sca_y= 1.0f;
661                 }
662                 else {
663                         sca_x= 1.0f;
664                         sca_y= 1.0f;
665                 }
666         }
667         else {
668                 sca_x= 1.0f;
669                 sca_y= 1.0f;
670         }
671
672         /* Calculate the scale center based on objects origin */
673         ofs_x= ob->ima_ofs[0] * ima_x;
674         ofs_y= ob->ima_ofs[1] * ima_y;
675
676         glMatrixMode(GL_MODELVIEW);
677         glPushMatrix();
678
679         /* Make sure we are drawing at the origin */
680         glTranslatef(0.0f,  0.0f,  0.0f);
681
682         /* Calculate Image scale */
683         scale= (ob->empty_drawsize / (float)MAX2(ima_x * sca_x, ima_y * sca_y));
684
685         /* Set the object scale */
686         glScalef(scale * sca_x, scale * sca_y, 1.0f);
687
688         if (ibuf && ibuf->rect) {
689                 /* Setup GL params */
690                 glEnable(GL_BLEND);
691                 glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA);
692
693                 /* Use the object color and alpha */
694                 glColor4fv(ob->col);
695
696                 /* Draw the Image on the screen */
697                 glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_UNSIGNED_BYTE, ibuf->rect);
698                 glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
699
700                 glDisable(GL_BLEND);
701         }
702
703         UI_ThemeColor((ob->flag & SELECT) ? TH_SELECT : TH_WIRE);
704
705         /* Calculate the outline vertex positions */
706         glBegin(GL_LINE_LOOP);
707         glVertex2f(ofs_x, ofs_y);
708         glVertex2f(ofs_x + ima_x, ofs_y);
709         glVertex2f(ofs_x + ima_x, ofs_y + ima_y);
710         glVertex2f(ofs_x, ofs_y + ima_y);
711         glEnd();
712
713         /* Reset GL settings */
714         glMatrixMode(GL_MODELVIEW);
715         glPopMatrix();
716 }
717
718 static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3], float rad, float tmat[][4])
719 {
720         float vx[3], vy[3];
721         float *viter= (float *)verts;
722         unsigned int a;
723
724         mul_v3_v3fl(vx, tmat[0], rad);
725         mul_v3_v3fl(vy, tmat[1], rad);
726
727         for (a=0; a < CIRCLE_RESOL; a++, viter += 3) {
728                 viter[0]= cent[0] + sinval[a] * vx[0] + cosval[a] * vy[0];
729                 viter[1]= cent[1] + sinval[a] * vx[1] + cosval[a] * vy[1];
730                 viter[2]= cent[2] + sinval[a] * vx[2] + cosval[a] * vy[2];
731         }
732 }
733
734 void drawcircball(int mode, const float cent[3], float rad, float tmat[][4])
735 {
736         float verts[CIRCLE_RESOL][3];
737
738         circball_array_fill(verts, cent, rad, tmat);
739
740         glEnableClientState(GL_VERTEX_ARRAY);
741         glVertexPointer(3, GL_FLOAT, 0, verts);
742         glDrawArrays(mode, 0, CIRCLE_RESOL);
743         glDisableClientState(GL_VERTEX_ARRAY);
744 }
745
746 /* circle for object centers, special_color is for library or ob users */
747 static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], int selstate, int special_color)
748 {
749         const float size= ED_view3d_pixel_size(rv3d, co) * (float)U.obcenter_dia * 0.5f;
750         float verts[CIRCLE_RESOL][3];
751
752         /* using gldepthfunc guarantees that it does write z values,
753          * but not checks for it, so centers remain visible independent order of drawing */
754         if (v3d->zbuf)  glDepthFunc(GL_ALWAYS);
755         glEnable(GL_BLEND);
756         
757         if (special_color) {
758                 if (selstate==ACTIVE || selstate==SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
759
760                 else glColor4ub(0x55, 0xCC, 0xCC, 155);
761         }
762         else {
763                 if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
764                 else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
765                 else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
766         }
767
768         circball_array_fill(verts, co, size, rv3d->viewinv);
769
770         /* enable vertex array */
771         glEnableClientState(GL_VERTEX_ARRAY);
772         glVertexPointer(3, GL_FLOAT, 0, verts);
773
774         /* 1. draw filled, blended polygon */
775         glDrawArrays(GL_POLYGON, 0, CIRCLE_RESOL);
776
777         /* 2. draw outline */
778         UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
779         glDrawArrays(GL_LINE_LOOP, 0, CIRCLE_RESOL);
780
781         /* finish up */
782         glDisableClientState(GL_VERTEX_ARRAY);
783
784         glDisable(GL_BLEND);
785
786         if (v3d->zbuf)  glDepthFunc(GL_LEQUAL);
787 }
788
789 /* *********** text drawing for object/particles/armature ************* */
790 static ListBase CachedText[3];
791 static int CachedTextLevel= 0;
792
793 typedef struct ViewCachedString {
794         struct ViewCachedString *next, *prev;
795         float vec[3];
796         union {
797                 unsigned char ub[4];
798                 int pack;
799         } col;
800         short sco[2];
801         short xoffs;
802         short flag;
803         int str_len, pad;
804         /* str is allocated past the end */
805 } ViewCachedString;
806
807 void view3d_cached_text_draw_begin(void)
808 {
809         ListBase *strings= &CachedText[CachedTextLevel];
810         strings->first= strings->last= NULL;
811         CachedTextLevel++;
812 }
813
814 void view3d_cached_text_draw_add(const float co[3],
815                                  const char *str,
816                                  short xoffs, short flag,
817                                  const unsigned char col[4])
818 {
819         int alloc_len= strlen(str) + 1;
820         ListBase *strings= &CachedText[CachedTextLevel-1];
821         /* TODO, replace with more efficient malloc, perhaps memarena per draw? */
822         ViewCachedString *vos= MEM_callocN(sizeof(ViewCachedString) + alloc_len, "ViewCachedString");
823
824         BLI_addtail(strings, vos);
825         copy_v3_v3(vos->vec, co);
826         vos->col.pack= *((int *)col);
827         vos->xoffs= xoffs;
828         vos->flag= flag;
829         vos->str_len= alloc_len-1;
830
831         /* allocate past the end */
832         memcpy(++vos, str, alloc_len);
833 }
834
835 void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, float mat[][4])
836 {
837         RegionView3D *rv3d= ar->regiondata;
838         ListBase *strings= &CachedText[CachedTextLevel-1];
839         ViewCachedString *vos;
840         int tot= 0;
841         
842         /* project first and test */
843         for (vos= strings->first; vos; vos= vos->next) {
844                 if (mat && !(vos->flag & V3D_CACHE_TEXT_WORLDSPACE))
845                         mul_m4_v3(mat, vos->vec);
846
847                 if (vos->flag & V3D_CACHE_TEXT_GLOBALSPACE)
848                         view3d_project_short_clip_persmat(ar, vos->vec, vos->sco, (vos->flag & V3D_CACHE_TEXT_LOCALCLIP) != 0);
849                 else
850                         view3d_project_short_clip(ar, vos->vec, vos->sco, (vos->flag & V3D_CACHE_TEXT_LOCALCLIP) != 0);
851
852                 if (vos->sco[0]!=IS_CLIPPED)
853                         tot++;
854         }
855
856         if (tot) {
857                 int col_pack_prev= 0;
858
859 #if 0
860                 bglMats mats; /* ZBuffer depth vars */
861                 double ux, uy, uz;
862                 float depth;
863
864                 if (v3d->zbuf)
865                         bgl_get_mats(&mats);
866 #endif
867                 if (rv3d->rflag & RV3D_CLIPPING) {
868                         ED_view3d_clipping_disable();
869                 }
870
871                 glMatrixMode(GL_PROJECTION);
872                 glPushMatrix();
873                 glMatrixMode(GL_MODELVIEW);
874                 glPushMatrix();
875                 ED_region_pixelspace(ar);
876                 
877                 if (depth_write) {
878                         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
879                 }
880                 else {
881                         glDepthMask(0);
882                 }
883                 
884                 for (vos= strings->first; vos; vos= vos->next) {
885                         /* too slow, reading opengl info while drawing is very bad,
886                          * better to see if we can use the zbuffer while in pixel space - campbell */
887 #if 0
888                         if (v3d->zbuf && (vos->flag & V3D_CACHE_TEXT_ZBUF)) {
889                                 gluProject(vos->vec[0], vos->vec[1], vos->vec[2], mats.modelview, mats.projection, (GLint *)mats.viewport, &ux, &uy, &uz);
890                                 glReadPixels(ar->winrct.xmin+vos->mval[0]+vos->xoffs, ar->winrct.ymin+vos->mval[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
891
892                                 if (uz > depth)
893                                         continue;
894                         }
895 #endif
896                         if (vos->sco[0]!=IS_CLIPPED) {
897                                 const char *str= (char *)(vos+1);
898
899                                 if (col_pack_prev != vos->col.pack) {
900                                         glColor3ubv(vos->col.ub);
901                                         col_pack_prev= vos->col.pack;
902                                 }
903
904                                 ((vos->flag & V3D_CACHE_TEXT_ASCII) ?
905                                             BLF_draw_default_ascii :
906                                             BLF_draw_default
907                                             ) ( (float)vos->sco[0] + vos->xoffs,
908                                                 (float)vos->sco[1],
909                                                 (depth_write) ? 0.0f: 2.0f,
910                                                 str,
911                                                 vos->str_len);
912                         }
913                 }
914                 
915                 if (depth_write) {
916                         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
917                 }
918                 else glDepthMask(1);
919                 
920                 glMatrixMode(GL_PROJECTION);
921                 glPopMatrix();
922                 glMatrixMode(GL_MODELVIEW);
923                 glPopMatrix();
924
925                 if (rv3d->rflag & RV3D_CLIPPING) {
926                         ED_view3d_clipping_enable();
927                 }
928         }
929         
930         if (strings->first)
931                 BLI_freelistN(strings);
932         
933         CachedTextLevel--;
934 }
935
936 /* ******************** primitive drawing ******************* */
937
938 static void drawcube(void)
939 {
940
941         glBegin(GL_LINE_STRIP);
942                 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
943                 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
944                 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
945         glEnd();
946
947         glBegin(GL_LINE_STRIP);
948                 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
949         glEnd();
950
951         glBegin(GL_LINE_STRIP);
952                 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
953         glEnd();
954
955         glBegin(GL_LINE_STRIP);
956                 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
957         glEnd();
958 }
959
960 /* draws a cube on given the scaling of the cube, assuming that 
961  * all required matrices have been set (used for drawing empties)
962  */
963 static void drawcube_size(float size)
964 {
965         glBegin(GL_LINE_STRIP);
966                 glVertex3f(-size,-size,-size); glVertex3f(-size,-size,size);
967                 glVertex3f(-size,size,size); glVertex3f(-size,size,-size);
968
969                 glVertex3f(-size,-size,-size); glVertex3f(size,-size,-size);
970                 glVertex3f(size,-size,size); glVertex3f(size,size,size);
971
972                 glVertex3f(size,size,-size); glVertex3f(size,-size,-size);
973         glEnd();
974
975         glBegin(GL_LINE_STRIP);
976                 glVertex3f(-size,-size,size); glVertex3f(size,-size,size);
977         glEnd();
978
979         glBegin(GL_LINE_STRIP);
980                 glVertex3f(-size,size,size); glVertex3f(size,size,size);
981         glEnd();
982
983         glBegin(GL_LINE_STRIP);
984                 glVertex3f(-size,size,-size); glVertex3f(size,size,-size);
985         glEnd();
986 }
987
988 /* this is an unused (old) cube-drawing function based on a given size */
989 #if 0
990 static void drawcube_size(const float size[3])
991 {
992
993         glPushMatrix();
994         glScalef(size[0],  size[1],  size[2]);
995         
996
997         glBegin(GL_LINE_STRIP);
998                 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
999                 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
1000                 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
1001         glEnd();
1002
1003         glBegin(GL_LINE_STRIP);
1004                 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
1005         glEnd();
1006
1007         glBegin(GL_LINE_STRIP);
1008                 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
1009         glEnd();
1010
1011         glBegin(GL_LINE_STRIP);
1012                 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
1013         glEnd();
1014         
1015         glPopMatrix();
1016 }
1017 #endif
1018
1019 static void drawshadbuflimits(Lamp *la, float mat[][4])
1020 {
1021         float sta[3], end[3], lavec[3];
1022
1023         negate_v3_v3(lavec, mat[2]);
1024         normalize_v3(lavec);
1025
1026         madd_v3_v3v3fl(sta, mat[3], lavec, la->clipsta);
1027         madd_v3_v3v3fl(end, mat[3], lavec, la->clipend);
1028
1029         glBegin(GL_LINE_STRIP);
1030                 glVertex3fv(sta);
1031                 glVertex3fv(end);
1032         glEnd();
1033
1034         glPointSize(3.0);
1035         bglBegin(GL_POINTS);
1036         bglVertex3fv(sta);
1037         bglVertex3fv(end);
1038         bglEnd();
1039         glPointSize(1.0);
1040 }
1041
1042
1043
1044 static void spotvolume(float lvec[3], float vvec[3], const float inp)
1045 {
1046         /* camera is at 0,0,0 */
1047         float temp[3],plane[3],mat1[3][3],mat2[3][3],mat3[3][3],mat4[3][3],q[4],co,si,angle;
1048
1049         normalize_v3(lvec);
1050         normalize_v3(vvec);                             /* is this the correct vector ? */
1051
1052         cross_v3_v3v3(temp,vvec,lvec);          /* equation for a plane through vvec en lvec */
1053         cross_v3_v3v3(plane,lvec,temp);         /* a plane perpendicular to this, parrallel with lvec */
1054
1055         /* vectors are exactly aligned, use the X axis, this is arbitrary */
1056         if (normalize_v3(plane) == 0.0f)
1057                 plane[1]= 1.0f;
1058
1059         /* now we've got two equations: one of a cone and one of a plane, but we have
1060          * three unknowns. We remove one unknown by rotating the plane to z=0 (the plane normal) */
1061
1062         /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
1063         /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
1064
1065         /* translating this comment to english didnt really help me understanding the math! :-) (ton) */
1066         
1067         q[1] =  plane[1];
1068         q[2] = -plane[0];
1069         q[3] =  0;
1070         normalize_v3(&q[1]);
1071
1072         angle = saacos(plane[2])/2.0f;
1073         co = cosf(angle);
1074         si = sqrtf(1-co*co);
1075
1076         q[0] =  co;
1077         q[1] *= si;
1078         q[2] *= si;
1079         q[3] =  0;
1080
1081         quat_to_mat3(mat1,q);
1082
1083         /* rotate lamp vector now over acos(inp) degrees */
1084         copy_v3_v3(vvec, lvec);
1085
1086         unit_m3(mat2);
1087         co = inp;
1088         si = sqrtf(1.0f-inp*inp);
1089
1090         mat2[0][0] =  co;
1091         mat2[1][0] = -si;
1092         mat2[0][1] =  si;
1093         mat2[1][1] =  co;
1094         mul_m3_m3m3(mat3,mat2,mat1);
1095
1096         mat2[1][0] =  si;
1097         mat2[0][1] = -si;
1098         mul_m3_m3m3(mat4,mat2,mat1);
1099         transpose_m3(mat1);
1100
1101         mul_m3_m3m3(mat2,mat1,mat3);
1102         mul_m3_v3(mat2,lvec);
1103         mul_m3_m3m3(mat2,mat1,mat4);
1104         mul_m3_v3(mat2,vvec);
1105
1106         return;
1107 }
1108
1109 static void draw_spot_cone(Lamp *la, float x, float z)
1110 {
1111         z= fabs(z);
1112
1113         glBegin(GL_TRIANGLE_FAN);
1114         glVertex3f(0.0f, 0.0f, -x);
1115
1116         if (la->mode & LA_SQUARE) {
1117                 glVertex3f(z, z, 0);
1118                 glVertex3f(-z, z, 0);
1119                 glVertex3f(-z, -z, 0);
1120                 glVertex3f(z, -z, 0);
1121                 glVertex3f(z, z, 0);
1122         }
1123         else {
1124                 float angle;
1125                 int a;
1126
1127                 for (a=0; a<33; a++) {
1128                         angle= a*M_PI*2/(33-1);
1129                         glVertex3f(z*cosf(angle), z*sinf(angle), 0);
1130                 }
1131         }
1132
1133         glEnd();
1134 }
1135
1136 static void draw_transp_spot_volume(Lamp *la, float x, float z)
1137 {
1138         glEnable(GL_CULL_FACE);
1139         glEnable(GL_BLEND);
1140         glDepthMask(0);
1141
1142         /* draw backside darkening */
1143         glCullFace(GL_FRONT);
1144
1145         glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
1146         glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
1147
1148         draw_spot_cone(la, x, z);
1149
1150         /* draw front side lighting */
1151         glCullFace(GL_BACK);
1152
1153         glBlendFunc(GL_ONE,  GL_ONE); 
1154         glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
1155
1156         draw_spot_cone(la, x, z);
1157
1158         /* restore state */
1159         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1160         glDisable(GL_BLEND);
1161         glDepthMask(1);
1162         glDisable(GL_CULL_FACE);
1163         glCullFace(GL_BACK);
1164 }
1165
1166 static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
1167 {
1168         Object *ob= base->object;
1169         const float pixsize= ED_view3d_pixel_size(rv3d, ob->obmat[3]);
1170         Lamp *la= ob->data;
1171         float vec[3], lvec[3], vvec[3], circrad, x,y,z;
1172         float lampsize;
1173         float imat[4][4], curcol[4];
1174         unsigned char col[4];
1175         /* cone can't be drawn for duplicated lamps, because duplilist would be freed to */
1176         /* the moment of view3d_draw_transp() call */
1177         const short is_view= (rv3d->persp==RV3D_CAMOB && v3d->camera == base->object);
1178         const short drawcone= ((dt > OB_WIRE) &&
1179                                !(G.f & G_PICKSEL) &&
1180                                (la->type == LA_SPOT) &&
1181                                (la->mode & LA_SHOW_CONE) &&
1182                                !(base->flag & OB_FROMDUPLI) &&
1183                                !is_view);
1184
1185         if (drawcone && !v3d->transp) {
1186                 /* in this case we need to draw delayed */
1187                 add_view3d_after(&v3d->afterdraw_transp, base, flag);
1188                 return;
1189         }
1190         
1191         /* we first draw only the screen aligned & fixed scale stuff */
1192         glPushMatrix();
1193         glLoadMatrixf(rv3d->viewmat);
1194
1195         /* lets calculate the scale: */
1196         lampsize= pixsize*((float)U.obcenter_dia*0.5f);
1197
1198         /* and view aligned matrix: */
1199         copy_m4_m4(imat, rv3d->viewinv);
1200         normalize_v3(imat[0]);
1201         normalize_v3(imat[1]);
1202
1203         /* lamp center */
1204         copy_v3_v3(vec, ob->obmat[3]);
1205         
1206         /* for AA effects */
1207         glGetFloatv(GL_CURRENT_COLOR, curcol);
1208         curcol[3]= 0.6;
1209         glColor4fv(curcol);
1210         
1211         if (lampsize > 0.0f) {
1212
1213                 if (ob->id.us>1) {
1214                         if (ob==OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155);
1215                         else glColor4ub(0x77, 0xCC, 0xCC, 155);
1216                 }
1217                 
1218                 /* Inner Circle */
1219                 glEnable(GL_BLEND);
1220                 drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
1221                 glDisable(GL_BLEND);
1222                 drawcircball(GL_POLYGON, vec, lampsize, imat);
1223                 
1224                 /* restore */
1225                 if (ob->id.us>1)
1226                         glColor4fv(curcol);
1227                         
1228                 /* Outer circle */
1229                 circrad = 3.0f*lampsize;
1230                 setlinestyle(3);
1231
1232                 drawcircball(GL_LINE_LOOP, vec, circrad, imat);
1233
1234                 /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
1235                 if (la->type!=LA_HEMI) {
1236                         if (    (la->mode & LA_SHAD_RAY) ||
1237                                 ((la->mode & LA_SHAD_BUF) && (la->type==LA_SPOT))
1238                         ) {
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                                                 if (steps == 0) v[1] = dir*circrad;
1401                                                 else v[1] = v[1] + dir*(steps*outdist); 
1402                                         }
1403                 
1404                                         v[2] = v[2] - steps*zdist;
1405                                         
1406                                         glVertex3fv(v);
1407                                         
1408                                         zdist = zdist * mul;
1409                                 }
1410                                 
1411                                 glEnd();
1412                                 /* flip the direction */
1413                                 dir = -dir;
1414                         }
1415                 }
1416         }
1417         else if (la->type==LA_AREA) {
1418                 setlinestyle(3);
1419                 if (la->area_shape==LA_AREA_SQUARE)
1420                         fdrawbox(-la->area_size*0.5f, -la->area_size*0.5f, la->area_size*0.5f, la->area_size*0.5f);
1421                 else if (la->area_shape==LA_AREA_RECT)
1422                         fdrawbox(-la->area_size*0.5f, -la->area_sizey*0.5f, la->area_size*0.5f, la->area_sizey*0.5f);
1423
1424                 glBegin(GL_LINE_STRIP); 
1425                 glVertex3f(0.0,0.0,-circrad);
1426                 glVertex3f(0.0,0.0,-la->dist);
1427                 glEnd();
1428         }
1429         
1430         /* and back to viewspace */
1431         glLoadMatrixf(rv3d->viewmat);
1432         copy_v3_v3(vec, ob->obmat[3]);
1433
1434         setlinestyle(0);
1435         
1436         if ((la->type == LA_SPOT) && (la->mode & LA_SHAD_BUF) && (is_view == FALSE)) {
1437                 drawshadbuflimits(la, ob->obmat);
1438         }
1439         
1440         UI_GetThemeColor4ubv(TH_LAMP, col);
1441         glColor4ubv(col);
1442          
1443         glEnable(GL_BLEND);
1444         
1445         if (vec[2]>0) vec[2] -= circrad;
1446         else vec[2] += circrad;
1447         
1448         glBegin(GL_LINE_STRIP);
1449                 glVertex3fv(vec); 
1450                 vec[2]= 0; 
1451                 glVertex3fv(vec);
1452         glEnd();
1453         
1454         glPointSize(2.0);
1455         glBegin(GL_POINTS);
1456                 glVertex3fv(vec);
1457         glEnd();
1458         glPointSize(1.0);
1459         
1460         glDisable(GL_BLEND);
1461         
1462         /* restore for drawing extra stuff */
1463         glColor3fv(curcol);
1464
1465 }
1466
1467 static void draw_limit_line(float sta, float end, unsigned int col)
1468 {
1469         glBegin(GL_LINES);
1470         glVertex3f(0.0, 0.0, -sta);
1471         glVertex3f(0.0, 0.0, -end);
1472         glEnd();
1473
1474         glPointSize(3.0);
1475         glBegin(GL_POINTS);
1476         cpack(col);
1477         glVertex3f(0.0, 0.0, -sta);
1478         glVertex3f(0.0, 0.0, -end);
1479         glEnd();
1480         glPointSize(1.0);
1481 }               
1482
1483
1484 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
1485 /* qdn: now also enabled for Blender to set focus point for defocus composite node */
1486 static void draw_focus_cross(float dist, float size)
1487 {
1488         glBegin(GL_LINES);
1489         glVertex3f(-size, 0.f, -dist);
1490         glVertex3f(size, 0.f, -dist);
1491         glVertex3f(0.f, -size, -dist);
1492         glVertex3f(0.f, size, -dist);
1493         glEnd();
1494 }
1495
1496 #ifdef VIEW3D_CAMERA_BORDER_HACK
1497 float view3d_camera_border_hack_col[4];
1498 short view3d_camera_border_hack_test= FALSE;
1499 #endif
1500
1501 /* ****************** draw clip data *************** */
1502
1503 static void draw_bundle_sphere(void)
1504 {
1505         static GLuint displist= 0;
1506
1507         if (displist == 0) {
1508                 GLUquadricObj *qobj;
1509
1510                 displist= glGenLists(1);
1511                 glNewList(displist, GL_COMPILE);
1512
1513                 qobj= gluNewQuadric();
1514                 gluQuadricDrawStyle(qobj, GLU_FILL);
1515                 glShadeModel(GL_SMOOTH);
1516                 gluSphere(qobj, 0.05, 8, 8);
1517                 glShadeModel(GL_FLAT);
1518                 gluDeleteQuadric(qobj);
1519
1520                 glEndList();
1521         }
1522
1523         glCallList(displist);
1524 }
1525
1526 static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D *v3d,
1527                         MovieClip *clip, MovieTrackingObject *tracking_object, int flag,
1528                         int *global_track_index, int draw_selected)
1529 {
1530         MovieTracking *tracking= &clip->tracking;
1531         MovieTrackingTrack *track;
1532         float mat[4][4], imat[4][4];
1533         unsigned char col[4], scol[4];
1534         int tracknr= *global_track_index;
1535         ListBase *tracksbase= BKE_tracking_object_tracks(tracking, tracking_object);
1536
1537         UI_GetThemeColor4ubv(TH_TEXT, col);
1538         UI_GetThemeColor4ubv(TH_SELECT, scol);
1539
1540         BKE_get_tracking_mat(scene, base->object, mat);
1541
1542         glPushMatrix();
1543
1544         if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
1545                 /* current ogl matrix is translated in camera space, bundles should
1546                  * be rendered in world space, so camera matrix should be "removed"
1547                  * from current ogl matrix */
1548                 invert_m4_m4(imat, base->object->obmat);
1549
1550                 glMultMatrixf(imat);
1551                 glMultMatrixf(mat);
1552         }
1553         else {
1554                 float obmat[4][4];
1555
1556                 BKE_tracking_get_interpolated_camera(tracking, tracking_object, scene->r.cfra, obmat);
1557
1558                 invert_m4_m4(imat, obmat);
1559                 glMultMatrixf(imat);
1560         }
1561
1562         for (track= tracksbase->first; track; track= track->next) {
1563                 int selected= TRACK_SELECTED(track);
1564
1565                 if ((draw_selected && !selected) || (draw_selected && !selected))
1566                         continue;
1567
1568                 if ((track->flag&TRACK_HAS_BUNDLE)==0)
1569                         continue;
1570
1571                 if (flag&DRAW_PICKING)
1572                         glLoadName(base->selcol + (tracknr<<16));
1573
1574                 glPushMatrix();
1575                         glTranslatef(track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]);
1576                         glScalef(v3d->bundle_size/0.05f, v3d->bundle_size/0.05f, v3d->bundle_size/0.05f);
1577
1578                         if (v3d->drawtype==OB_WIRE) {
1579                                 glDisable(GL_LIGHTING);
1580
1581                                 if (selected) {
1582                                         if (base==BASACT) UI_ThemeColor(TH_ACTIVE);
1583                                         else UI_ThemeColor(TH_SELECT);
1584                                 }
1585                                 else {
1586                                         if (track->flag&TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1587                                         else UI_ThemeColor(TH_WIRE);
1588                                 }
1589
1590                                 drawaxes(0.05f, v3d->bundle_drawtype);
1591
1592                                 glEnable(GL_LIGHTING);
1593                         }
1594                         else if (v3d->drawtype>OB_WIRE) {
1595                                 if (v3d->bundle_drawtype==OB_EMPTY_SPHERE) {
1596                                         /* selection outline */
1597                                         if (selected) {
1598                                                 if (base==BASACT) UI_ThemeColor(TH_ACTIVE);
1599                                                 else UI_ThemeColor(TH_SELECT);
1600
1601                                                 glLineWidth(2.f);
1602                                                 glDisable(GL_LIGHTING);
1603                                                 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1604
1605                                                 draw_bundle_sphere();
1606
1607                                                 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1608                                                 glEnable(GL_LIGHTING);
1609                                                 glLineWidth(1.f);
1610                                         }
1611
1612                                         if (track->flag&TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1613                                         else UI_ThemeColor(TH_BUNDLE_SOLID);
1614
1615                                         draw_bundle_sphere();
1616                                 }
1617                                 else {
1618                                         glDisable(GL_LIGHTING);
1619
1620                                         if (selected) {
1621                                                 if (base==BASACT) UI_ThemeColor(TH_ACTIVE);
1622                                                 else UI_ThemeColor(TH_SELECT);
1623                                         }
1624                                         else {
1625                                                 if (track->flag&TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1626                                                 else UI_ThemeColor(TH_WIRE);
1627                                         }
1628
1629                                         drawaxes(0.05f, v3d->bundle_drawtype);
1630
1631                                         glEnable(GL_LIGHTING);
1632                                 }
1633                         }
1634
1635                 glPopMatrix();
1636
1637                 if ((flag & DRAW_PICKING)==0 && (v3d->flag2&V3D_SHOW_BUNDLENAME)) {
1638                         float pos[3];
1639                         unsigned char tcol[4];
1640
1641                         if (selected) memcpy(tcol, scol, sizeof(tcol));
1642                         else memcpy(tcol, col, sizeof(tcol));
1643
1644                         mul_v3_m4v3(pos, mat, track->bundle_pos);
1645                         view3d_cached_text_draw_add(pos, track->name, 10, V3D_CACHE_TEXT_GLOBALSPACE, tcol);
1646                 }
1647
1648                 tracknr++;
1649         }
1650
1651         if ((flag & DRAW_PICKING)==0) {
1652                 if ((v3d->flag2&V3D_SHOW_CAMERAPATH) && (tracking_object->flag&TRACKING_OBJECT_CAMERA)) {
1653                         MovieTrackingReconstruction *reconstruction;
1654                         reconstruction= BKE_tracking_object_reconstruction(tracking, tracking_object);
1655
1656                         if (reconstruction->camnr) {
1657                                 MovieReconstructedCamera *camera= reconstruction->cameras;
1658                                 int a= 0;
1659
1660                                 glDisable(GL_LIGHTING);
1661                                 UI_ThemeColor(TH_CAMERA_PATH);
1662                                 glLineWidth(2.0f);
1663
1664                                 glBegin(GL_LINE_STRIP);
1665                                         for (a= 0; a<reconstruction->camnr; a++, camera++) {
1666                                                 glVertex3fv(camera->mat[3]);
1667                                         }
1668                                         glEnd();
1669
1670                                         glLineWidth(1.0f);
1671                                         glEnable(GL_LIGHTING);
1672                         }
1673                 }
1674         }
1675
1676         glPopMatrix();
1677
1678         *global_track_index= tracknr;
1679 }
1680
1681 static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, MovieClip *clip,
1682                         int flag, int draw_selected)
1683 {
1684         MovieTracking *tracking= &clip->tracking;
1685         MovieTrackingObject *tracking_object;
1686         float curcol[4];
1687         int global_track_index= 1;
1688
1689         if ((v3d->flag2&V3D_SHOW_RECONSTRUCTION)==0)
1690                 return;
1691
1692         if (v3d->flag2&V3D_RENDER_OVERRIDE)
1693                 return;
1694
1695         glGetFloatv(GL_CURRENT_COLOR, curcol);
1696
1697         glEnable(GL_LIGHTING);
1698         glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1699         glEnable(GL_COLOR_MATERIAL);
1700         glShadeModel(GL_SMOOTH);
1701
1702         tracking_object= tracking->objects.first;
1703         while (tracking_object) {
1704                 draw_viewport_object_reconstruction(scene, base, v3d, clip, tracking_object,
1705                                         flag, &global_track_index, draw_selected);
1706
1707                 tracking_object= tracking_object->next;
1708         }
1709
1710         /* restore */
1711         glShadeModel(GL_FLAT);
1712         glDisable(GL_COLOR_MATERIAL);
1713         glDisable(GL_LIGHTING);
1714
1715         glColor4fv(curcol);
1716
1717         if (flag&DRAW_PICKING)
1718                 glLoadName(base->selcol);
1719 }
1720
1721 /* flag similar to draw_object() */
1722 static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int flag)
1723 {
1724         /* a standing up pyramid with (0,0,0) as top */
1725         Camera *cam;
1726         Object *ob= base->object;
1727         float tvec[3];
1728         float vec[4][3], asp[2], shift[2], scale[3];
1729         int i;
1730         float drawsize;
1731         const short is_view= (rv3d->persp==RV3D_CAMOB && ob==v3d->camera);
1732         MovieClip *clip= object_get_movieclip(scene, base->object, 0);
1733
1734         /* draw data for movie clip set as active for scene */
1735         if (clip) {
1736                 draw_viewport_reconstruction(scene, base, v3d, clip, flag, FALSE);
1737                 draw_viewport_reconstruction(scene, base, v3d, clip, flag, TRUE);
1738         }
1739
1740 #ifdef VIEW3D_CAMERA_BORDER_HACK
1741         if (is_view && !(G.f & G_PICKSEL)) {
1742                 glGetFloatv(GL_CURRENT_COLOR, view3d_camera_border_hack_col);
1743                 view3d_camera_border_hack_test= TRUE;
1744                 return;
1745         }
1746 #endif
1747
1748         cam= ob->data;
1749
1750         scale[0]= 1.0f / len_v3(ob->obmat[0]);
1751         scale[1]= 1.0f / len_v3(ob->obmat[1]);
1752         scale[2]= 1.0f / len_v3(ob->obmat[2]);
1753
1754         camera_view_frame_ex(scene, cam, cam->drawsize, is_view, scale,
1755                              asp, shift, &drawsize, vec);
1756
1757         glDisable(GL_LIGHTING);
1758         glDisable(GL_CULL_FACE);
1759
1760         /* camera frame */
1761         glBegin(GL_LINE_LOOP);
1762         glVertex3fv(vec[0]);
1763         glVertex3fv(vec[1]);
1764         glVertex3fv(vec[2]);
1765         glVertex3fv(vec[3]);
1766         glEnd();
1767
1768         if (is_view)
1769                 return;
1770
1771         zero_v3(tvec);
1772
1773         /* center point to camera frame */
1774         glBegin(GL_LINE_STRIP);
1775         glVertex3fv(vec[1]);
1776         glVertex3fv(tvec);
1777         glVertex3fv(vec[0]);
1778         glVertex3fv(vec[3]);
1779         glVertex3fv(tvec);
1780         glVertex3fv(vec[2]);
1781         glEnd();
1782
1783
1784         /* arrow on top */
1785         tvec[2]= vec[1][2]; /* copy the depth */
1786
1787
1788         /* draw an outline arrow for inactive cameras and filled
1789          * for active cameras. We actually draw both outline+filled
1790          * for active cameras so the wire can be seen side-on */        
1791         for (i=0;i<2;i++) {
1792                 if (i==0) glBegin(GL_LINE_LOOP);
1793                 else if (i==1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1794                 else break;
1795
1796                 tvec[0]= shift[0] + ((-0.7f * drawsize) * scale[0]);
1797                 tvec[1]= shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]);
1798                 glVertex3fv(tvec); /* left */
1799                 
1800                 tvec[0]= shift[0] + ((0.7f * drawsize) * scale[0]);
1801                 glVertex3fv(tvec); /* right */
1802                 
1803                 tvec[0]= shift[0];
1804                 tvec[1]= shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]);
1805                 glVertex3fv(tvec); /* top */
1806         
1807                 glEnd();
1808         }
1809
1810         if (flag==0) {
1811                 if (cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
1812                         float nobmat[4][4];
1813                         World *wrld;
1814         
1815                         /* draw in normalized object matrix space */
1816                         copy_m4_m4(nobmat, ob->obmat);
1817                         normalize_m4(nobmat);
1818
1819                         glPushMatrix();
1820                         glLoadMatrixf(rv3d->viewmat);
1821                         glMultMatrixf(nobmat);
1822
1823                         if (cam->flag & CAM_SHOWLIMITS) {
1824                                 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
1825                                 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composite node */
1826                                 draw_focus_cross(object_camera_dof_distance(ob), cam->drawsize);
1827                         }
1828
1829                         wrld= scene->world;
1830                         if (cam->flag & CAM_SHOWMIST)
1831                                 if (wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
1832                                 
1833                         glPopMatrix();
1834                 }
1835         }
1836 }
1837
1838 /* flag similar to draw_object() */
1839 static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D *UNUSED(rv3d),
1840                         Object *UNUSED(ob), int UNUSED(flag))
1841 {
1842         //Speaker *spk = ob->data;
1843
1844         float vec[3];
1845         int i, j;
1846
1847         glEnable(GL_BLEND);
1848
1849         for (j = 0; j < 3; j++) {
1850                 vec[2] = 0.25f * j -0.125f;
1851
1852                 glBegin(GL_LINE_LOOP);
1853                 for (i = 0; i < 16; i++) {
1854                         vec[0] = cosf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1855                         vec[1] = sinf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1856                         glVertex3fv(vec);
1857                 }
1858                 glEnd();
1859         }
1860
1861         for (j = 0; j < 4; j++) {
1862                 vec[0] = (((j + 1) % 2) * (j - 1)) * 0.5f;
1863                 vec[1] = ((j % 2) * (j - 2)) * 0.5f;
1864                 glBegin(GL_LINE_STRIP);
1865                 for (i = 0; i < 3; i++) {
1866                         if (i == 1) {
1867                                 vec[0] *= 0.5f;
1868                                 vec[1] *= 0.5f;
1869                         }
1870
1871                         vec[2] = 0.25f * i -0.125f;
1872                         glVertex3fv(vec);
1873                 }
1874                 glEnd();
1875         }
1876
1877         glDisable(GL_BLEND);
1878 }
1879
1880 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1881 {
1882         BPoint *bp = lt->def;
1883         float *co = dl?dl->verts:NULL;
1884         int u, v, w;
1885
1886         UI_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
1887         glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1888         bglBegin(GL_POINTS);
1889
1890         for (w=0; w<lt->pntsw; w++) {
1891                 int wxt = (w==0 || w==lt->pntsw-1);
1892                 for (v=0; v<lt->pntsv; v++) {
1893                         int vxt = (v==0 || v==lt->pntsv-1);
1894                         for (u=0; u<lt->pntsu; u++, bp++, co+=3) {
1895                                 int uxt = (u==0 || u==lt->pntsu-1);
1896                                 if (!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1897                                         if (bp->hide==0) {
1898                                                 if ((bp->f1 & SELECT)==sel) {
1899                                                         bglVertex3fv(dl?co:bp->vec);
1900                                                 }
1901                                         }
1902                                 }
1903                         }
1904                 }
1905         }
1906         
1907         glPointSize(1.0);
1908         bglEnd();       
1909 }
1910
1911 void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
1912 {
1913         Object *obedit= vc->obedit;
1914         Lattice *lt= obedit->data;
1915         BPoint *bp = lt->editlatt->latt->def;
1916         DispList *dl = find_displist(&obedit->disp, DL_VERTS);
1917         float *co = dl?dl->verts:NULL;
1918         int i, N = lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
1919         short s[2] = {IS_CLIPPED, 0};
1920
1921         ED_view3d_clipping_local(vc->rv3d, obedit->obmat); /* for local clipping lookups */
1922
1923         for (i=0; i<N; i++, bp++, co+=3) {
1924                 if (bp->hide==0) {
1925                         view3d_project_short_clip(vc->ar, dl?co:bp->vec, s, TRUE);
1926                         if (s[0] != IS_CLIPPED)
1927                                 func(userData, bp, s[0], s[1]);
1928                 }
1929         }
1930 }
1931
1932 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1933 {
1934         int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
1935
1936         if (use_wcol) {
1937                 float col[3];
1938                 MDeformWeight *mdw= defvert_find_index (lt->dvert+index, use_wcol-1);
1939                 
1940                 weight_to_rgb(col, mdw?mdw->weight:0.0f);
1941                 glColor3fv(col);
1942
1943         }
1944         
1945         if (dl) {
1946                 glVertex3fv(&dl->verts[index*3]);
1947         }
1948         else {
1949                 glVertex3fv(lt->def[index].vec);
1950         }
1951 }
1952
1953 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1954 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1955 {
1956         Lattice *lt= ob->data;
1957         DispList *dl;
1958         int u, v, w;
1959         int use_wcol= 0, is_edit= (lt->editlatt != NULL);
1960
1961         /* now we default make displist, this will modifiers work for non animated case */
1962         if (ob->disp.first==NULL)
1963                 lattice_calc_modifiers(scene, ob);
1964         dl= find_displist(&ob->disp, DL_VERTS);
1965         
1966         if (is_edit) {
1967                 lt= lt->editlatt->latt;
1968
1969                 cpack(0x004000);
1970                 
1971                 if (ob->defbase.first && lt->dvert) {
1972                         use_wcol= ob->actdef;
1973                         glShadeModel(GL_SMOOTH);
1974                 }
1975         }
1976         
1977         glBegin(GL_LINES);
1978         for (w=0; w<lt->pntsw; w++) {
1979                 int wxt = (w==0 || w==lt->pntsw-1);
1980                 for (v=0; v<lt->pntsv; v++) {
1981                         int vxt = (v==0 || v==lt->pntsv-1);
1982                         for (u=0; u<lt->pntsu; u++) {
1983                                 int uxt = (u==0 || u==lt->pntsu-1);
1984
1985                                 if (w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1986                                         drawlattice__point(lt, dl, u, v, w-1, use_wcol);
1987                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1988                                 }
1989                                 if (v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1990                                         drawlattice__point(lt, dl, u, v-1, w, use_wcol);
1991                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1992                                 }
1993                                 if (u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1994                                         drawlattice__point(lt, dl, u-1, v, w, use_wcol);
1995                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1996                                 }
1997                         }
1998                 }
1999         }               
2000         glEnd();
2001         
2002         /* restoration for weight colors */
2003         if (use_wcol)
2004                 glShadeModel(GL_FLAT);
2005
2006         if (is_edit) {
2007                 if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
2008                 
2009                 lattice_draw_verts(lt, dl, 0);
2010                 lattice_draw_verts(lt, dl, 1);
2011                 
2012                 if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
2013         }
2014 }
2015
2016 /* ***************** ******************** */
2017
2018 /* Note! - foreach funcs should be called while drawing or directly after
2019  * if not, ED_view3d_init_mats_rv3d() can be used for selection tools
2020  * but would not give correct results with dupli's for eg. which dont
2021  * use the object matrix in the usual way */
2022 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2023 {
2024         foreachScreenVert_userData *data = userData;
2025         BMVert *eve = EDBM_get_vert_for_index(data->vc.em, index);
2026
2027         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
2028                 short s[2]= {IS_CLIPPED, 0};
2029
2030                 if (data->clipVerts != V3D_CLIP_TEST_OFF) {
2031                         view3d_project_short_clip(data->vc.ar, co, s, TRUE);
2032                 }
2033                 else {
2034                         float co2[2];
2035                         mul_v3_m4v3(co2, data->vc.obedit->obmat, co);
2036                         project_short_noclip(data->vc.ar, co2, s);
2037                 }
2038
2039                 if (s[0]!=IS_CLIPPED)
2040                         data->func(data->userData, eve, s[0], s[1], index);
2041         }
2042 }
2043
2044 void mesh_foreachScreenVert(
2045         ViewContext *vc,
2046         void (*func)(void *userData, BMVert *eve, int x, int y, int index),
2047         void *userData, eV3DClipTest clipVerts)
2048 {
2049         foreachScreenVert_userData data;
2050         DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
2051         
2052         data.vc= *vc;
2053         data.func = func;
2054         data.userData = userData;
2055         data.clipVerts = clipVerts;
2056
2057         if (clipVerts != V3D_CLIP_TEST_OFF)
2058                 ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2059
2060         EDBM_init_index_arrays(vc->em, 1, 0, 0);
2061         dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
2062         EDBM_free_index_arrays(vc->em);
2063
2064         dm->release(dm);
2065 }
2066
2067 /*  draw callback */
2068 static void drawSelectedVertices__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2069 {
2070         MVert *mv = &((MVert *)userData)[index];
2071
2072         if (!(mv->flag & ME_HIDE)) {
2073                 const char sel= mv->flag & SELECT;
2074
2075                 // TODO define selected color
2076                 if (sel) {
2077                         glColor3f(1.0f, 1.0f, 0.0f);
2078                 }
2079                 else {
2080                         glColor3f(0.0f, 0.0f, 0.0f);
2081                 }
2082
2083                 glVertex3fv(co);
2084         }
2085 }
2086
2087 static void drawSelectedVertices(DerivedMesh *dm, Mesh *me)
2088 {
2089         glBegin(GL_POINTS);
2090         dm->foreachMappedVert(dm, drawSelectedVertices__mapFunc, me->mvert);
2091         glEnd();
2092 }
2093 static int is_co_in_region(ARegion *ar, const short co[2])
2094 {
2095         return ( (co[0] != IS_CLIPPED) && /* may be the only initialized value, check first */
2096                  (co[0] >= 0)          &&
2097                  (co[0] <  ar->winx)   &&
2098                  (co[1] >= 0)          &&
2099                  (co[1] <  ar->winy));
2100 }
2101 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
2102 {
2103         foreachScreenEdge_userData *data = userData;
2104         BMEdge *eed = EDBM_get_edge_for_index(data->vc.em, index);
2105
2106         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
2107                 short s[2][2];
2108
2109                 if (data->clipVerts == V3D_CLIP_TEST_RV3D_CLIPPING) {
2110                         view3d_project_short_clip(data->vc.ar, v0co, s[0], TRUE);
2111                         view3d_project_short_clip(data->vc.ar, v1co, s[1], TRUE);
2112                 }
2113                 else {
2114                         float v1_co[3], v2_co[3];
2115
2116                         mul_v3_m4v3(v1_co, data->vc.obedit->obmat, v0co);
2117                         mul_v3_m4v3(v2_co, data->vc.obedit->obmat, v1co);
2118
2119                         project_short_noclip(data->vc.ar, v1_co, s[0]);
2120                         project_short_noclip(data->vc.ar, v2_co, s[1]);
2121
2122                         if (data->clipVerts == V3D_CLIP_TEST_REGION) {
2123                                 if ( !is_co_in_region(data->vc.ar, s[0]) &&
2124                                      !is_co_in_region(data->vc.ar, s[1]))
2125                                 {
2126                                         return;
2127                                 }
2128                         }
2129                 }
2130
2131                 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
2132         }
2133 }
2134
2135 void mesh_foreachScreenEdge(
2136         ViewContext *vc,
2137         void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index),
2138         void *userData, eV3DClipTest clipVerts)
2139 {
2140         foreachScreenEdge_userData data;
2141         DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
2142
2143         data.vc= *vc;
2144         data.func = func;
2145         data.userData = userData;
2146         data.clipVerts = clipVerts;
2147
2148         if (clipVerts != V3D_CLIP_TEST_OFF)
2149                 ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2150
2151         EDBM_init_index_arrays(vc->em, 0, 1, 0);
2152         dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
2153         EDBM_free_index_arrays(vc->em);
2154
2155         dm->release(dm);
2156 }
2157
2158 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
2159 {
2160         foreachScreenFace_userData *data = userData;
2161         BMFace *efa = EDBM_get_face_for_index(data->vc.em, index);
2162
2163         if (efa && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
2164                 float cent2[3];
2165                 short s[2];
2166
2167                 mul_v3_m4v3(cent2, data->vc.obedit->obmat, cent);
2168                 project_short(data->vc.ar, cent2, s);
2169
2170                 if (s[0] != IS_CLIPPED) {
2171                         data->func(data->userData, efa, s[0], s[1], index);
2172                 }
2173         }
2174 }
2175
2176 void mesh_foreachScreenFace(
2177         ViewContext *vc,
2178         void (*func)(void *userData, BMFace *efa, int x, int y, int index),
2179         void *userData)
2180 {
2181         foreachScreenFace_userData data;
2182         DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
2183
2184         data.vc= *vc;
2185         data.func = func;
2186         data.userData = userData;
2187
2188         //if (clipVerts)
2189         ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2190
2191         EDBM_init_index_arrays(vc->em, 0, 0, 1);
2192         dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
2193         EDBM_free_index_arrays(vc->em);
2194
2195         dm->release(dm);
2196 }
2197
2198 void nurbs_foreachScreenVert(
2199         ViewContext *vc,
2200         void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y),
2201         void *userData)
2202 {
2203         Curve *cu= vc->obedit->data;
2204         short s[2] = {IS_CLIPPED, 0};
2205         Nurb *nu;
2206         int i;
2207         ListBase *nurbs= curve_editnurbs(cu);
2208
2209         ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2210
2211         for (nu= nurbs->first; nu; nu=nu->next) {
2212                 if (nu->type == CU_BEZIER) {
2213                         for (i=0; i<nu->pntsu; i++) {
2214                                 BezTriple *bezt = &nu->bezt[i];
2215
2216                                 if (bezt->hide==0) {
2217                                         
2218                                         if (cu->drawflag & CU_HIDE_HANDLES) {
2219                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, TRUE);
2220                                                 if (s[0] != IS_CLIPPED)
2221                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
2222                                         }
2223                                         else {
2224                                                 view3d_project_short_clip(vc->ar, bezt->vec[0], s, TRUE);
2225                                                 if (s[0] != IS_CLIPPED)
2226                                                         func(userData, nu, NULL, bezt, 0, s[0], s[1]);
2227                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, TRUE);
2228                                                 if (s[0] != IS_CLIPPED)
2229                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
2230                                                 view3d_project_short_clip(vc->ar, bezt->vec[2], s, TRUE);
2231                                                 if (s[0] != IS_CLIPPED)
2232                                                         func(userData, nu, NULL, bezt, 2, s[0], s[1]);
2233                                         }
2234                                 }
2235                         }
2236                 }
2237                 else {
2238                         for (i=0; i<nu->pntsu*nu->pntsv; i++) {
2239                                 BPoint *bp = &nu->bp[i];
2240
2241                                 if (bp->hide==0) {
2242                                         view3d_project_short_clip(vc->ar, bp->vec, s, TRUE);
2243                                         if (s[0] != IS_CLIPPED)
2244                                                 func(userData, nu, bp, NULL, -1, s[0], s[1]);
2245                                 }
2246                         }
2247                 }
2248         }
2249 }
2250
2251 /* ************** DRAW MESH ****************** */
2252
2253 /* First section is all the "simple" draw routines, 
2254  * ones that just pass some sort of primitive to GL,
2255  * with perhaps various options to control lighting,
2256  * color, etc.
2257  *
2258  * These routines should not have user interface related
2259  * logic!!!
2260  */
2261
2262 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
2263 {
2264         drawDMNormal_userData *data = userData;
2265         BMFace *efa = EDBM_get_face_for_index(data->em, index);
2266
2267         if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
2268                 glVertex3fv(cent);
2269                 glVertex3f(cent[0] + no[0] * data->normalsize,
2270                            cent[1] + no[1] * data->normalsize,
2271                            cent[2] + no[2] * data->normalsize);
2272         }
2273 }
2274 static void draw_dm_face_normals(BMEditMesh *em, Scene *scene, DerivedMesh *dm) 
2275 {
2276         drawDMNormal_userData data;
2277
2278         data.em = em;
2279         data.normalsize = scene->toolsettings->normalsize;
2280
2281         glBegin(GL_LINES);
2282         dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, &data);
2283         glEnd();
2284 }
2285
2286 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
2287 {
2288         BMFace *efa = EDBM_get_face_for_index(((void **)userData)[0], index);
2289         int sel = *(((int **)userData)[1]);
2290         
2291         if (efa && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && BM_elem_flag_test(efa, BM_ELEM_SELECT)==sel) {
2292                 bglVertex3fv(cent);
2293         }
2294 }
2295 static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, int sel)
2296 {
2297         void *ptrs[2] = {em, &sel};
2298
2299         bglBegin(GL_POINTS);
2300         dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, ptrs);
2301         bglEnd();
2302 }
2303
2304 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
2305 {
2306         drawDMNormal_userData *data = userData;
2307         BMVert *eve = EDBM_get_vert_for_index(data->em, index);
2308
2309         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
2310                 glVertex3fv(co);
2311
2312                 if (no_f) {
2313                         glVertex3f(co[0] + no_f[0] * data->normalsize,
2314                                    co[1] + no_f[1] * data->normalsize,
2315                                    co[2] + no_f[2] * data->normalsize);
2316                 }
2317                 else {
2318                         glVertex3f(co[0] + no_s[0] * (data->normalsize / 32767.0f),
2319                                    co[1] + no_s[1] * (data->normalsize / 32767.0f),
2320                                    co[2] + no_s[2] * (data->normalsize / 32767.0f));
2321                 }
2322         }
2323 }
2324 static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, DerivedMesh *dm) 
2325 {
2326         drawDMNormal_userData data;
2327
2328         data.em = em;
2329         data.normalsize = scene->toolsettings->normalsize;
2330
2331         glBegin(GL_LINES);
2332         dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, &data);
2333         glEnd();
2334 }
2335
2336 /* Draw verts with color set based on selection */
2337 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2338 {
2339         drawDMVerts_userData * data = userData;
2340         BMVert *eve = EDBM_get_vert_for_index(data->em, index);
2341
2342         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT)==data->sel) {
2343                 /* draw active larger - need to stop/start point drawing for this :/ */
2344                 if (eve==data->eve_act) {
2345                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2346                         UI_ThemeColor4(TH_EDITMESH_ACTIVE);
2347                         
2348                         bglEnd();
2349                         
2350                         glPointSize(size);
2351                         bglBegin(GL_POINTS);
2352                         bglVertex3fv(co);
2353                         bglEnd();
2354                         
2355                         UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
2356                         glPointSize(size);
2357                         bglBegin(GL_POINTS);
2358                 }
2359                 else {
2360                         bglVertex3fv(co);
2361                 }
2362         }
2363 }
2364
2365 static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, int sel, BMVert *eve_act)
2366 {
2367         drawDMVerts_userData data;
2368         data.sel = sel;
2369         data.eve_act = eve_act;
2370         data.em = em;
2371
2372         bglBegin(GL_POINTS);
2373         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
2374         bglEnd();
2375 }
2376
2377         /* Draw edges with color set based on selection */
2378 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
2379 {
2380         BMEdge *eed;
2381         //unsigned char **cols = userData, *col;
2382         drawDMEdgesSel_userData * data = userData;
2383         unsigned char *col;
2384
2385         eed = EDBM_get_edge_for_index(data->em, index);
2386
2387         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
2388                 if (eed==data->eed_act) {
2389                         glColor4ubv(data->actCol);
2390                 }
2391                 else {
2392                         if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
2393                                 col = data->selCol;
2394                         }
2395                         else {
2396                                 col = data->baseCol;
2397                         }
2398                         /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode  */
2399                         if (col[3]==0) return 0;
2400                         
2401                         glColor4ubv(col);
2402                 }
2403                 return 1;
2404         }
2405         else {
2406                 return 0;
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 int draw_dm_edges__setDrawOptions(void *userData, int index)
2424 {
2425         return !BM_elem_flag_test(EDBM_get_edge_for_index(userData, index), BM_ELEM_HIDDEN);
2426 }
2427 static void draw_dm_edges(BMEditMesh *em, DerivedMesh *dm) 
2428 {
2429         dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, em);
2430 }
2431
2432         /* Draw edges with color interpolated based on selection */
2433 static int draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
2434 {
2435         return !BM_elem_flag_test(EDBM_get_edge_for_index(((void**)userData)[0], index), BM_ELEM_HIDDEN);
2436 }
2437 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
2438 {
2439         BMEdge *eed = EDBM_get_edge_for_index(((void**)userData)[0], index);
2440         unsigned char **cols = userData;
2441         unsigned char *col0 = cols[(BM_elem_flag_test(eed->v1, BM_ELEM_SELECT))?2:1];
2442         unsigned char *col1 = cols[(BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))?2:1];
2443
2444         glColor4ub(     col0[0] + (col1[0]-col0[0])*t,
2445                                 col0[1] + (col1[1]-col0[1])*t,
2446                                 col0[2] + (col1[2]-col0[2])*t,
2447                                 col0[3] + (col1[3]-col0[3])*t);
2448 }
2449
2450 static void draw_dm_edges_sel_interp(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
2451 {
2452         void *cols[3] = {em, baseCol, selCol};
2453
2454         dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
2455 }
2456
2457         /* Draw only seam edges */
2458 static int draw_dm_edges_seams__setDrawOptions(void *userData, int index)
2459 {
2460         BMEdge *eed = EDBM_get_edge_for_index(userData, index);
2461
2462         return !BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BM_elem_flag_test(eed, BM_ELEM_SEAM);
2463 }
2464
2465 static void draw_dm_edges_seams(BMEditMesh *em, DerivedMesh *dm)
2466 {
2467         dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, em);
2468 }
2469
2470         /* Draw only sharp edges */
2471 static int draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
2472 {
2473         BMEdge *eed = EDBM_get_edge_for_index(userData, index);
2474
2475         return !BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && !BM_elem_flag_test(eed, BM_ELEM_SMOOTH);
2476 }
2477 static void draw_dm_edges_sharp(BMEditMesh *em, DerivedMesh *dm)
2478 {
2479         dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, em);
2480 }
2481
2482
2483         /* Draw faces with color set based on selection
2484          * return 2 for the active face so it renders with stipple enabled */
2485 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *UNUSED(drawSmooth_r))
2486 {
2487         drawDMFacesSel_userData * data = userData;
2488         BMFace *efa = EDBM_get_face_for_index(data->em, index);
2489         unsigned char *col;
2490         
2491         if (!efa)
2492                 return 0;
2493         
2494         if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
2495                 if (efa == data->efa_act) {
2496                         glColor4ubv(data->cols[2]);
2497                         return 2; /* stipple */
2498                 }
2499                 else {
2500                         col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT)?1:0];
2501                         if (col[3]==0) return 0;
2502                         glColor4ubv(col);
2503                         return 1;
2504                 }
2505         }
2506         return 0;
2507 }
2508
2509 static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index)
2510 {
2511
2512         drawDMFacesSel_userData *data = userData;
2513         BMFace *efa;
2514         BMFace *next_efa;
2515
2516         unsigned char *col, *next_col;
2517
2518         if (!data->orig_index)
2519                 return 0;
2520
2521         efa= EDBM_get_face_for_index(data->em, data->orig_index[index]);
2522         next_efa= EDBM_get_face_for_index(data->em, data->orig_index[next_index]);
2523
2524         if (efa == next_efa)
2525                 return 1;
2526
2527         if (efa == data->efa_act || next_efa == data->efa_act)
2528                 return 0;
2529
2530         col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT)?1:0];
2531         next_col = data->cols[BM_elem_flag_test(next_efa, BM_ELEM_SELECT)?1:0];
2532
2533         if (col[3]==0 || next_col[3]==0)
2534                 return 0;
2535
2536         return col == next_col;
2537 }
2538
2539 /* also draws the active face */
2540 static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, 
2541                               unsigned char *selCol, unsigned char *actCol, BMFace *efa_act)
2542 {
2543         drawDMFacesSel_userData data;
2544         data.dm= dm;
2545         data.cols[0] = baseCol;
2546         data.em = em;
2547         data.cols[1] = selCol;
2548         data.cols[2] = actCol;
2549         data.efa_act = efa_act;
2550         data.orig_index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
2551
2552         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions, &data, 0);
2553 }
2554
2555 static int draw_dm_creases__setDrawOptions(void *userData, int index)
2556 {
2557         BMEditMesh *em = userData;
2558         BMEdge *eed = EDBM_get_edge_for_index(userData, index);
2559         float *crease = eed ? (float *)CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_CREASE) : NULL;
2560         
2561         if (!crease)
2562                 return 0;
2563         
2564         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && *crease!=0.0f) {
2565                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, *crease);
2566                 return 1;
2567         }
2568         else {
2569                 return 0;
2570         }
2571 }
2572 static void draw_dm_creases(BMEditMesh *em, DerivedMesh *dm)
2573 {
2574         glLineWidth(3.0);
2575         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, em);
2576         glLineWidth(1.0);
2577 }
2578
2579 static int draw_dm_bweights__setDrawOptions(void *userData, int index)
2580 {
2581         BMEditMesh *em = userData;
2582         BMEdge *eed = EDBM_get_edge_for_index(userData, index);
2583         float *bweight = (float *)CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_BWEIGHT);
2584
2585         if (!bweight)
2586                 return 0;
2587         
2588         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && *bweight!=0.0f) {
2589                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, *bweight);
2590                 return 1;
2591         }
2592         else {
2593                 return 0;
2594         }
2595 }
2596 static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2597 {
2598         BMEditMesh *em = userData;
2599         BMVert *eve = EDBM_get_vert_for_index(userData, index);
2600         float *bweight = (float *)CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_BWEIGHT);
2601         
2602         if (!bweight)
2603                 return;
2604         
2605         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && *bweight!=0.0f) {
2606                 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, *bweight);
2607                 bglVertex3fv(co);
2608         }
2609 }
2610 static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
2611 {
2612         ToolSettings *ts= scene->toolsettings;
2613
2614         if (ts->selectmode & SCE_SELECT_VERTEX) {
2615                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2616                 bglBegin(GL_POINTS);
2617                 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, em);
2618                 bglEnd();
2619         }
2620         else {
2621                 glLineWidth(3.0);
2622                 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, em);
2623                 glLineWidth(1.0);
2624         }
2625 }
2626
2627 /* Second section of routines: Combine first sets to form fancy
2628  * drawing routines (for example rendering twice to get overlays).
2629  *
2630  * Also includes routines that are basic drawing but are too
2631  * specialized to be split out (like drawing creases or measurements).
2632  */
2633
2634 /* EditMesh drawing routines*/
2635
2636 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, 
2637                                 BMEditMesh *em, DerivedMesh *cageDM, BMVert *eve_act)
2638 {
2639         ToolSettings *ts= scene->toolsettings;
2640         int sel;
2641
2642         if (v3d->zbuf) glDepthMask(0);          // disable write in zbuffer, zbuf select
2643
2644         for (sel=0; sel<2; sel++) {
2645                 unsigned char col[4], fcol[4];
2646                 int pass;
2647
2648                 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
2649                 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
2650
2651                 for (pass=0; pass<2; pass++) {
2652                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2653                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2654
2655                         if (pass==0) {
2656                                 if (v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
2657                                         glDisable(GL_DEPTH_TEST);
2658                                                 
2659                                         glEnable(GL_BLEND);
2660                                 }
2661                                 else {
2662                                         continue;
2663                                 }
2664
2665                                 size = (size > 2.1f ? size/2.0f:size);
2666                                 fsize = (fsize > 2.1f ? fsize/2.0f:fsize);
2667                                 col[3] = fcol[3] = 100;
2668                         }
2669                         else {
2670                                 col[3] = fcol[3] = 255;
2671                         }
2672                                 
2673                         if (ts->selectmode & SCE_SELECT_VERTEX) {
2674                                 glPointSize(size);
2675                                 glColor4ubv(col);
2676                                 draw_dm_verts(em, cageDM, sel, eve_act);
2677                         }
2678                         
2679                         if (check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2680                                 glPointSize(fsize);
2681                                 glColor4ubv(fcol);
2682                                 draw_dm_face_centers(em, cageDM, sel);
2683                         }
2684                         
2685                         if (pass==0) {
2686                                 glDisable(GL_BLEND);
2687                                 glEnable(GL_DEPTH_TEST);
2688                         }
2689                 }
2690         }
2691
2692         if (v3d->zbuf) glDepthMask(1);
2693         glPointSize(1.0);
2694 }
2695
2696 static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d,
2697                                 Mesh *me, DerivedMesh *cageDM, short sel_only,
2698                                 BMEdge *eed_act)
2699 {
2700         ToolSettings *ts= scene->toolsettings;
2701         int pass;
2702         unsigned char wireCol[4], selCol[4], actCol[4];
2703
2704         /* since this function does transparant... */
2705         UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2706         UI_GetThemeColor4ubv(TH_WIRE, wireCol);
2707         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2708         
2709         /* when sel only is used, dont render wire, only selected, this is used for
2710          * textured draw mode when the 'edges' option is disabled */
2711         if (sel_only)
2712                 wireCol[3] = 0;
2713
2714         for (pass=0; pass<2; pass++) {
2715                         /* show wires in transparant when no zbuf clipping for select */
2716                 if (pass==0) {
2717                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
2718                                 glEnable(GL_BLEND);
2719                                 glDisable(GL_DEPTH_TEST);
2720                                 selCol[3] = 85;
2721                                 if (!sel_only) wireCol[3] = 85;
2722                         }
2723                         else {
2724                                 continue;
2725                         }
2726                 }
2727                 else {
2728                         selCol[3] = 255;
2729                         if (!sel_only) wireCol[3] = 255;
2730                 }
2731
2732                 if (ts->selectmode == SCE_SELECT_FACE) {
2733                         draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
2734                 }       
2735                 else if ( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {
2736                         if (cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2737                                 glShadeModel(GL_SMOOTH);
2738                                 draw_dm_edges_sel_interp(em, cageDM, wireCol, selCol);
2739                                 glShadeModel(GL_FLAT);
2740                         }
2741                         else {
2742                                 draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
2743                         }
2744                 }
2745                 else {
2746                         if (!sel_only) {
2747                                 glColor4ubv(wireCol);
2748                                 draw_dm_edges(em, cageDM);
2749                         }
2750                 }
2751
2752                 if (pass==0) {
2753                         glDisable(GL_BLEND);
2754                         glEnable(GL_DEPTH_TEST);
2755                 }
2756         }
2757 }       
2758
2759 static void draw_em_measure_stats(View3D *v3d, Object *ob, BMEditMesh *em, UnitSettings *unit)
2760 {
2761         const short txt_flag = V3D_CACHE_TEXT_ASCII | V3D_CACHE_TEXT_LOCALCLIP;
2762         Mesh *me= ob->data;
2763         float v1[3], v2[3], v3[3], vmid[3], fvec[3];
2764         char numstr[32]; /* Stores the measurement display text here */
2765         const char *conv_float; /* Use a float conversion matching the grid size */
2766         unsigned char col[4]= {0, 0, 0, 255}; /* color of the text to draw */
2767         float area; /* area of the face */
2768         float grid= unit->system ? unit->scale_length : v3d->grid;
2769         const int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
2770         const int do_global= v3d->flag & V3D_GLOBAL_STATS;
2771         const int do_moving= G.moving;
2772
2773         BMIter iter;
2774         int i;
2775
2776         /* make the precision of the pronted value proportionate to the gridsize */
2777
2778         if (grid < 0.01f)               conv_float= "%.6g";
2779         else if (grid < 0.1f)   conv_float= "%.5g";
2780         else if (grid < 1.0f)   conv_float= "%.4g";
2781         else if (grid < 10.0f)  conv_float= "%.3g";
2782         else                                    conv_float= "%.2g";
2783         
2784         if (me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2785                 BMEdge *eed;
2786
2787                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2788
2789                 eed = BM_iter_new(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
2790                 for (; eed; eed=BM_iter_step(&iter)) {
2791                         /* draw selected edges, or edges next to selected verts while draging */
2792                         if (BM_elem_flag_test(eed, BM_ELEM_SELECT) ||
2793                             (do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
2794                                            BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))))
2795                         {
2796
2797                                 copy_v3_v3(v1, eed->v1->co);
2798                                 copy_v3_v3(v2, eed->v2->co);
2799
2800                                 mid_v3_v3v3(vmid, v1, v2);
2801
2802                                 if (do_global) {
2803                                         mul_mat3_m4_v3(ob->obmat, v1);
2804                                         mul_mat3_m4_v3(ob->obmat, v2);
2805                                 }
2806
2807                                 if (unit->system) {
2808                                         bUnit_AsString(numstr, sizeof(numstr), len_v3v3(v1, v2) * unit->scale_length, 3,
2809                                                        unit->system, B_UNIT_LENGTH, do_split, FALSE);
2810                                 }
2811                                 else {
2812                                         sprintf(numstr, conv_float, len_v3v3(v1, v2));
2813                                 }
2814
2815                                 view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col);
2816                         }
2817                 }
2818         }
2819
2820         if (me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2821                 /* would be nice to use BM_face_area_calc, but that is for 2d faces
2822                  * so instead add up tessellationf triangle areas */
2823                 BMFace *f;
2824                 int n;
2825
2826 #define DRAW_EM_MEASURE_STATS_FACEAREA()                                             \
2827                 if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {                                  \
2828                         mul_v3_fl(vmid, 1.0/n);                                                  \
2829                         if (unit->system)                                                        \
2830                                 bUnit_AsString(numstr, sizeof(numstr), area*unit->scale_length,      \
2831                                         3, unit->system, B_UNIT_LENGTH, do_split, FALSE);                \
2832                         else                                                                     \
2833                                 BLI_snprintf(numstr, sizeof(numstr), conv_float, area);              \
2834                         view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col);             \
2835                 }
2836
2837                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2838                 
2839                 f = NULL;
2840                 area = 0.0;
2841                 zero_v3(vmid);
2842                 n = 0;
2843                 for (i = 0; i < em->tottri; i++) {
2844                         BMLoop **l = em->looptris[i];
2845                         if (f && l[0]->f != f) {
2846                                 DRAW_EM_MEASURE_STATS_FACEAREA();
2847                                 zero_v3(vmid);
2848                                 area = 0.0;
2849                                 n = 0;
2850                         }
2851
2852                         f = l[0]->f;
2853                         copy_v3_v3(v1, l[0]->v->co);
2854                         copy_v3_v3(v2, l[1]->v->co);
2855                         copy_v3_v3(v3, l[2]->v->co);
2856                         if (do_global) {
2857                                 mul_mat3_m4_v3(ob->obmat, v1);
2858                                 mul_mat3_m4_v3(ob->obmat, v2);
2859                                 mul_mat3_m4_v3(ob->obmat, v3);
2860                         }
2861                         area += area_tri_v3(v1, v2, v3);
2862                         add_v3_v3(vmid, v1);
2863                         add_v3_v3(vmid, v2);
2864                         add_v3_v3(vmid, v3);
2865                         n += 3;
2866                 }
2867
2868                 if (f) {
2869                         DRAW_EM_MEASURE_STATS_FACEAREA();
2870                 }
2871 #undef DRAW_EM_MEASURE_STATS_FACEAREA
2872         }
2873
2874         if (me->drawflag & ME_DRAWEXTRA_FACEANG) {
2875                 BMFace *efa;
2876
2877                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2878
2879
2880                 for (efa = BM_iter_new(&iter, em->bm, BM_FACES_OF_MESH, NULL);
2881                     efa; efa=BM_iter_step(&iter)) {
2882                         BMIter liter;
2883                         BMLoop *loop;
2884
2885                         BM_face_center_bounds_calc(em->bm, efa, vmid);
2886
2887                         for (loop = BM_iter_new(&liter, em->bm, BM_LOOPS_OF_FACE, efa);
2888                             loop; loop = BM_iter_step(&liter)) {
2889
2890                                 float v1[3], v2[3], v3[3];
2891
2892                                 copy_v3_v3(v1, loop->prev->v->co);
2893                                 copy_v3_v3(v2, loop->v->co);
2894                                 copy_v3_v3(v3, loop->next->v->co);
2895
2896                                 if (do_global) {
2897                                         mul_mat3_m4_v3(ob->obmat, v1);
2898                                         mul_mat3_m4_v3(ob->obmat, v2);
2899                                         mul_mat3_m4_v3(ob->obmat, v3);
2900                                 }
2901
2902                                 if ( (BM_elem_flag_test(efa, BM_ELEM_SELECT)) ||
2903                                      (do_moving && BM_elem_flag_test(loop->v, BM_ELEM_SELECT)))
2904                                 {
2905                                         BLI_snprintf(numstr, sizeof(numstr), "%.3g", RAD2DEGF(angle_v3v3v3(v1, v2, v3)));
2906                                         interp_v3_v3v3(fvec, vmid, v2, 0.8f);
2907                                         view3d_cached_text_draw_add(fvec, numstr, 0, txt_flag, col);
2908                                 }
2909                         }
2910                 }
2911         }
2912 }
2913
2914 static void draw_em_indices(BMEditMesh *em)
2915 {
2916         const short txt_flag = V3D_CACHE_TEXT_ASCII | V3D_CACHE_TEXT_LOCALCLIP;
2917         BMEdge *e;
2918         BMFace *f;
2919         BMVert *v;
2920         int i;
2921         char numstr[32];
2922         float pos[3];
2923         unsigned char col[4];
2924
2925         BMIter iter;
2926         BMesh *bm= em->bm;
2927
2928         /* For now, reuse appropriate theme colors from stats text colors */
2929         i= 0;
2930         if (em->selectmode & SCE_SELECT_VERTEX) {
2931                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2932                 BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
2933                         if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
2934                                 sprintf(numstr, "%d", i);
2935                                 view3d_cached_text_draw_add(v->co, numstr, 0, txt_flag, col);
2936                         }
2937                         i++;
2938                 }
2939         }
2940
2941         if (em->selectmode & SCE_SELECT_EDGE) {
2942                 i= 0;
2943                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2944                 BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
2945                         if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
2946                                 sprintf(numstr, "%d", i);
2947                                 mid_v3_v3v3(pos, e->v1->co, e->v2->co);
2948                                 view3d_cached_text_draw_add(pos, numstr, 0, txt_flag, col);
2949                         }
2950                         i++;
2951                 }
2952         }
2953
2954         if (em->selectmode & SCE_SELECT_FACE) {
2955                 i= 0;
2956                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2957                 BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
2958                         if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
2959                                 BM_face_center_mean_calc(bm, f, pos);
2960                                 sprintf(numstr, "%d", i);
2961                                 view3d_cached_text_draw_add(pos, numstr, 0, txt_flag, col);
2962                         }
2963                         i++;
2964                 }
2965         }
2966 }
2967
2968 static int draw_em_fancy__setFaceOpts(void *userData, int index, int *UNUSED(drawSmooth_r))
2969 {
2970         BMFace *efa = EDBM_get_face_for_index(userData, index);
2971
2972         if (efa && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
2973                 GPU_enable_material(efa->mat_nr+1, NULL);
2974                 return 1;
2975         }
2976         else
2977                 return 0;
2978 }
2979
2980 static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
2981 {
2982         BMFace *efa = EDBM_get_face_for_index(userData, index);
2983
2984         return !BM_elem_flag_test(efa, BM_ELEM_HIDDEN);
2985 }
2986
2987 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
2988                           Object *ob, BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2989
2990 {
2991         Mesh *me = ob->data;
2992         BMFace *efa_act = BM_active_face_get(em->bm, FALSE); /* annoying but active faces is stored differently */
2993         BMEdge *eed_act = NULL;
2994         BMVert *eve_act = NULL;
2995         
2996         if (em->bm->selected.last) {
2997                 BMEditSelection *ese= em->bm->selected.last;
2998                 /* face is handeled above */
2999 #if 0
3000                 if (ese->type == BM_FACE ) {
3001                         efa_act = (BMFace *)ese->data;
3002                 }
3003                 else 
3004 #endif
3005                 if ( ese->htype == BM_EDGE ) {
3006                         eed_act = (BMEdge *)ese->ele;
3007                 }
3008                 else if ( ese->htype == BM_VERT ) {
3009                         eve_act = (BMVert *)ese->ele;
3010                 }
3011         }
3012         
3013         EDBM_init_index_arrays(em, 1, 1, 1);
3014
3015         if (dt>OB_WIRE) {
3016                 if (CHECK_OB_DRAWTEXTURE(v3d, dt)) {
3017                         if (draw_glsl_material(scene, ob, v3d, dt)) {
3018                                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
3019
3020                                 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
3021                                                              draw_em_fancy__setGLSLFaceOpts, em);
3022                                 GPU_disable_material();
3023
3024                                 glFrontFace(GL_CCW);
3025                         }
3026                         else {
3027                                 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
3028                         }
3029                 }
3030                 else {
3031                         /* 3 floats for position,
3032                          * 3 for normal and times two because the faces may actually be quads instead of triangles */
3033                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, (me->flag & ME_TWOSIDED) ? GL_TRUE : GL_FALSE);
3034
3035                         glEnable(GL_LIGHTING);
3036                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
3037                         finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, GPU_enable_material, NULL, me->edit_btmesh, 0);
3038
3039                         glFrontFace(GL_CCW);
3040                         glDisable(GL_LIGHTING);
3041                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
3042                 }
3043                         
3044                 // Setup for drawing wire over, disable zbuffer
3045                 // write to show selected edge wires better
3046                 UI_ThemeColor(TH_WIRE);
3047
3048                 bglPolygonOffset(rv3d->dist, 1.0);
3049                 glDepthMask(0);
3050         } 
3051         else {
3052                 if (cageDM!=finalDM) {
3053                         UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
3054                         finalDM->drawEdges(finalDM, 1, 0);
3055                 }
3056         }
3057         
3058         if (me->drawflag & ME_DRAWFACES) {      /* transp faces */
3059                 unsigned char col1[4], col2[4], col3[4];
3060                         
3061                 UI_GetThemeColor4ubv(TH_FACE, col1);
3062                 UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
3063                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
3064                 
3065                 glEnable(GL_BLEND);
3066                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
3067                 
3068                 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
3069                 if CHECK_OB_DRAWTEXTURE(v3d, dt)
3070                         col1[3] = 0;
3071                 
3072                 draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act);
3073
3074                 glDisable(GL_BLEND);
3075                 glDepthMask(1);         // restore write in zbuffer
3076         }
3077         else if (efa_act) {
3078                 /* even if draw faces is off it would be nice to draw the stipple face
3079                  * Make all other faces zero alpha except for the active
3080                  * */
3081                 unsigned char col1[4], col2[4], col3[4];
3082                 col1[3] = col2[3] = 0; /* dont draw */