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