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