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