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