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