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