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