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