Cycles: svn merge -r39669:39870 https://svn.blender.org/svnroot/bf-blender/trunk...
[blender.git] / source / blender / editors / space_view3d / drawobject.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * Contributor(s): Blender Foundation, full recode and added functions
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/space_view3d/drawobject.c
29  *  \ingroup spview3d
30  */
31
32
33 #include <string.h>
34 #include <math.h>
35
36 #include "MEM_guardedalloc.h"
37
38 #include "DNA_camera_types.h"
39 #include "DNA_curve_types.h"
40 #include "DNA_constraint_types.h" // for drawing constraint
41 #include "DNA_lamp_types.h"
42 #include "DNA_lattice_types.h"
43 #include "DNA_material_types.h"
44 #include "DNA_meshdata_types.h"
45 #include "DNA_meta_types.h"
46 #include "DNA_scene_types.h"
47 #include "DNA_smoke_types.h"
48 #include "DNA_speaker_types.h"
49 #include "DNA_world_types.h"
50 #include "DNA_armature_types.h"
51
52 #include "BLI_blenlib.h"
53 #include "BLI_math.h"
54 #include "BLI_editVert.h"
55 #include "BLI_edgehash.h"
56 #include "BLI_rand.h"
57 #include "BLI_utildefines.h"
58
59 #include "BKE_anim.h"                   //for the where_on_path function
60 #include "BKE_constraint.h" // for the get_constraint_target function
61 #include "BKE_DerivedMesh.h"
62 #include "BKE_deform.h"
63 #include "BKE_displist.h"
64 #include "BKE_font.h"
65 #include "BKE_global.h"
66 #include "BKE_image.h"
67 #include "BKE_key.h"
68 #include "BKE_lattice.h"
69 #include "BKE_mesh.h"
70 #include "BKE_material.h"
71 #include "BKE_mball.h"
72 #include "BKE_modifier.h"
73 #include "BKE_object.h"
74 #include "BKE_paint.h"
75 #include "BKE_particle.h"
76 #include "BKE_pointcache.h"
77 #include "BKE_scene.h"
78 #include "BKE_unit.h"
79
80 #include "smoke_API.h"
81
82 #include "IMB_imbuf.h"
83 #include "IMB_imbuf_types.h"
84
85 #include "BIF_gl.h"
86 #include "BIF_glutil.h"
87
88 #include "GPU_draw.h"
89 #include "GPU_extensions.h"
90
91 #include "ED_mesh.h"
92 #include "ED_particle.h"
93 #include "ED_screen.h"
94 #include "ED_sculpt.h"
95 #include "ED_types.h"
96 #include "ED_curve.h" /* for ED_curve_editnurbs */
97
98 #include "UI_resources.h"
99
100 #include "WM_api.h"
101 #include "wm_subwindow.h"
102 #include "BLF_api.h"
103
104 #include "view3d_intern.h"      // own include
105
106
107 /* this condition has been made more complex since editmode can draw textures */
108 #define CHECK_OB_DRAWTEXTURE(vd, dt) \
109         ((ELEM(vd->drawtype, OB_TEXTURE, OB_MATERIAL) && dt>OB_SOLID))
110
111 static void draw_bounding_volume(Scene *scene, Object *ob);
112
113 static void drawcube_size(float size);
114 static void drawcircle_size(float size);
115 static void draw_empty_sphere(float size);
116 static void draw_empty_cone(float size);
117
118 static int check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
119 {
120         if((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0)
121                 return 0;
122
123         if(G.f & G_BACKBUFSEL)
124                 return 0;
125
126         if((vd->flag & V3D_ZBUF_SELECT) == 0)
127                 return 1;
128
129         /* if its drawing textures with zbuf sel, then dont draw dots */
130         if(dt==OB_TEXTURE && vd->drawtype==OB_TEXTURE)
131                 return 0;
132
133         return 1;
134 }
135
136 /* ************* only use while object drawing **************
137  * or after running ED_view3d_init_mats_rv3d
138  * */
139 static void view3d_project_short_clip(ARegion *ar, float *vec, short *adr, int local)
140 {
141         RegionView3D *rv3d= ar->regiondata;
142         float fx, fy, vec4[4];
143         
144         adr[0]= IS_CLIPPED;
145         
146         /* clipplanes in eye space */
147         if(rv3d->rflag & RV3D_CLIPPING) {
148                 if(ED_view3d_test_clipping(rv3d, vec, local))
149                         return;
150         }
151         
152         copy_v3_v3(vec4, vec);
153         vec4[3]= 1.0;
154         
155         mul_m4_v4(rv3d->persmatob, vec4);
156         
157         /* clipplanes in window space */
158         if( vec4[3] > (float)BL_NEAR_CLIP ) {   /* is the NEAR clipping cutoff for picking */
159                 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
160                 
161                 if( fx>0 && fx<ar->winx) {
162                         
163                         fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
164                         
165                         if(fy > 0.0f && fy < (float)ar->winy) {
166                                 adr[0]= (short)floorf(fx);
167                                 adr[1]= (short)floorf(fy);
168                         }
169                 }
170         }
171 }
172
173 /* only use while object drawing */
174 static void view3d_project_short_noclip(ARegion *ar, float *vec, short *adr)
175 {
176         RegionView3D *rv3d= ar->regiondata;
177         float fx, fy, vec4[4];
178         
179         adr[0]= IS_CLIPPED;
180         
181         copy_v3_v3(vec4, vec);
182         vec4[3]= 1.0;
183         
184         mul_m4_v4(rv3d->persmatob, vec4);
185         
186         if( vec4[3] > (float)BL_NEAR_CLIP ) {   /* is the NEAR clipping cutoff for picking */
187                 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
188                 
189                 if( fx>-32700 && fx<32700) {
190                         
191                         fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
192                         
193                         if(fy > -32700.0f && fy < 32700.0f) {
194                                 adr[0]= (short)floorf(fx);
195                                 adr[1]= (short)floorf(fy);
196                         }
197                 }
198         }
199 }
200
201 /* ************************ */
202
203 /* check for glsl drawing */
204
205 int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt)
206 {
207         if(!GPU_glsl_support())
208                 return 0;
209         if(G.f & G_PICKSEL)
210                 return 0;
211         if(!CHECK_OB_DRAWTEXTURE(v3d, dt))
212                 return 0;
213         if(ob==OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
214                 return 0;
215         if(scene_use_new_shading_system(scene))
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 /* flag similar to draw_object() */
1495 static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D *UNUSED(rv3d), Object *UNUSED(ob), int UNUSED(flag))
1496 {
1497         //Speaker *spk = ob->data;
1498
1499         float vec[3];
1500         int i, j;
1501
1502         glEnable(GL_BLEND);
1503
1504         for(j = 0; j < 3; j++) {
1505                 vec[2] = 0.25f * j -0.125f;
1506
1507                 glBegin(GL_LINE_LOOP);
1508                 for(i = 0; i < 16; i++) {
1509                         vec[0] = cosf(M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1510                         vec[1] = sinf(M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1511                         glVertex3fv(vec);
1512                 }
1513                 glEnd();
1514         }
1515
1516         for(j = 0; j < 4; j++) {
1517                 vec[0] = (((j + 1) % 2) * (j - 1)) * 0.5f;
1518                 vec[1] = ((j % 2) * (j - 2)) * 0.5f;
1519                 glBegin(GL_LINE_STRIP);
1520                 for(i = 0; i < 3; i++) {
1521                         if(i == 1) {
1522                                 vec[0] *= 0.5f;
1523                                 vec[1] *= 0.5f;
1524                         }
1525
1526                         vec[2] = 0.25f * i -0.125f;
1527                         glVertex3fv(vec);
1528                 }
1529                 glEnd();
1530         }
1531
1532         glDisable(GL_BLEND);
1533 }
1534
1535 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1536 {
1537         BPoint *bp = lt->def;
1538         float *co = dl?dl->verts:NULL;
1539         int u, v, w;
1540
1541         UI_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
1542         glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1543         bglBegin(GL_POINTS);
1544
1545         for(w=0; w<lt->pntsw; w++) {
1546                 int wxt = (w==0 || w==lt->pntsw-1);
1547                 for(v=0; v<lt->pntsv; v++) {
1548                         int vxt = (v==0 || v==lt->pntsv-1);
1549                         for(u=0; u<lt->pntsu; u++, bp++, co+=3) {
1550                                 int uxt = (u==0 || u==lt->pntsu-1);
1551                                 if(!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1552                                         if(bp->hide==0) {
1553                                                 if((bp->f1 & SELECT)==sel) {
1554                                                         bglVertex3fv(dl?co:bp->vec);
1555                                                 }
1556                                         }
1557                                 }
1558                         }
1559                 }
1560         }
1561         
1562         glPointSize(1.0);
1563         bglEnd();       
1564 }
1565
1566 void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
1567 {
1568         Object *obedit= vc->obedit;
1569         Lattice *lt= obedit->data;
1570         BPoint *bp = lt->editlatt->latt->def;
1571         DispList *dl = find_displist(&obedit->disp, DL_VERTS);
1572         float *co = dl?dl->verts:NULL;
1573         int i, N = lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
1574         short s[2] = {IS_CLIPPED, 0};
1575
1576         ED_view3d_local_clipping(vc->rv3d, obedit->obmat); /* for local clipping lookups */
1577
1578         for (i=0; i<N; i++, bp++, co+=3) {
1579                 if (bp->hide==0) {
1580                         view3d_project_short_clip(vc->ar, dl?co:bp->vec, s, 1);
1581                         if (s[0] != IS_CLIPPED)
1582                                 func(userData, bp, s[0], s[1]);
1583                 }
1584         }
1585 }
1586
1587 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1588 {
1589         int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
1590
1591         if(use_wcol) {
1592                 float col[3];
1593                 MDeformWeight *mdw= defvert_find_index (lt->dvert+index, use_wcol-1);
1594                 
1595                 weight_to_rgb(mdw?mdw->weight:0.0f, col, col+1, col+2);
1596                 glColor3fv(col);
1597
1598         }
1599         
1600         if (dl) {
1601                 glVertex3fv(&dl->verts[index*3]);
1602         } else {
1603                 glVertex3fv(lt->def[index].vec);
1604         }
1605 }
1606
1607 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1608 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1609 {
1610         Lattice *lt= ob->data;
1611         DispList *dl;
1612         int u, v, w;
1613         int use_wcol= 0, is_edit= (lt->editlatt != NULL);
1614
1615         /* now we default make displist, this will modifiers work for non animated case */
1616         if(ob->disp.first==NULL)
1617                 lattice_calc_modifiers(scene, ob);
1618         dl= find_displist(&ob->disp, DL_VERTS);
1619         
1620         if(is_edit) {
1621                 lt= lt->editlatt->latt;
1622
1623                 cpack(0x004000);
1624                 
1625                 if(ob->defbase.first && lt->dvert) {
1626                         use_wcol= ob->actdef;
1627                         glShadeModel(GL_SMOOTH);
1628                 }
1629         }
1630         
1631         glBegin(GL_LINES);
1632         for(w=0; w<lt->pntsw; w++) {
1633                 int wxt = (w==0 || w==lt->pntsw-1);
1634                 for(v=0; v<lt->pntsv; v++) {
1635                         int vxt = (v==0 || v==lt->pntsv-1);
1636                         for(u=0; u<lt->pntsu; u++) {
1637                                 int uxt = (u==0 || u==lt->pntsu-1);
1638
1639                                 if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1640                                         drawlattice__point(lt, dl, u, v, w-1, use_wcol);
1641                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1642                                 }
1643                                 if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1644                                         drawlattice__point(lt, dl, u, v-1, w, use_wcol);
1645                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1646                                 }
1647                                 if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1648                                         drawlattice__point(lt, dl, u-1, v, w, use_wcol);
1649                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1650                                 }
1651                         }
1652                 }
1653         }               
1654         glEnd();
1655         
1656         /* restoration for weight colors */
1657         if(use_wcol)
1658                 glShadeModel(GL_FLAT);
1659
1660         if(is_edit) {
1661                 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
1662                 
1663                 lattice_draw_verts(lt, dl, 0);
1664                 lattice_draw_verts(lt, dl, 1);
1665                 
1666                 if(v3d->zbuf) glEnable(GL_DEPTH_TEST); 
1667         }
1668 }
1669
1670 /* ***************** ******************** */
1671
1672 /* Note! - foreach funcs should be called while drawing or directly after
1673  * if not, ED_view3d_init_mats_rv3d() can be used for selection tools
1674  * but would not give correct results with dupli's for eg. which dont
1675  * use the object matrix in the useual way */
1676 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1677 {
1678         struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
1679         EditVert *eve = EM_get_vert_for_index(index);
1680
1681         if (eve->h==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, eve, s[0], s[1], index);
1692         }
1693 }
1694
1695 void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
1696 {
1697         struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } data;
1698         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, 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->obedit->obmat); /* for local clipping lookups */
1707
1708         EM_init_index_arrays(vc->em, 1, 0, 0);
1709         dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
1710         EM_free_index_arrays();
1711
1712         dm->release(dm);
1713 }
1714
1715 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
1716 {
1717         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;
1718         EditEdge *eed = EM_get_edge_for_index(index);
1719         short s[2][2];
1720
1721         if (eed->h==0) {
1722                 if (data->clipVerts==1) {
1723                         view3d_project_short_clip(data->vc.ar, v0co, s[0], 1);
1724                         view3d_project_short_clip(data->vc.ar, v1co, s[1], 1);
1725                 } else {
1726                         view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
1727                         view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
1728
1729                         if (data->clipVerts==2) {
1730                                 if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy))
1731                                         if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<data->vc.ar->winx && s[1][1]<data->vc.ar->winy)) 
1732                                                 return;
1733                         }
1734                 }
1735
1736                 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
1737         }
1738 }
1739
1740 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)
1741 {
1742         struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } data;
1743         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1744
1745         data.vc= *vc;
1746         data.func = func;
1747         data.userData = userData;
1748         data.clipVerts = clipVerts;
1749
1750         if(clipVerts)
1751                 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1752
1753         EM_init_index_arrays(vc->em, 0, 1, 0);
1754         dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
1755         EM_free_index_arrays();
1756
1757         dm->release(dm);
1758 }
1759
1760 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
1761 {
1762         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } *data = userData;
1763         EditFace *efa = EM_get_face_for_index(index);
1764         short s[2];
1765
1766         if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
1767                 view3d_project_short_clip(data->vc.ar, cent, s, 1);
1768
1769                 data->func(data->userData, efa, s[0], s[1], index);
1770         }
1771 }
1772
1773 void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
1774 {
1775         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } data;
1776         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1777
1778         data.vc= *vc;
1779         data.func = func;
1780         data.userData = userData;
1781
1782         //if(clipVerts)
1783         ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1784
1785         EM_init_index_arrays(vc->em, 0, 0, 1);
1786         dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
1787         EM_free_index_arrays();
1788
1789         dm->release(dm);
1790 }
1791
1792 void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
1793 {
1794         Curve *cu= vc->obedit->data;
1795         short s[2] = {IS_CLIPPED, 0};
1796         Nurb *nu;
1797         int i;
1798         ListBase *nurbs= ED_curve_editnurbs(cu);
1799
1800         ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1801
1802         for (nu= nurbs->first; nu; nu=nu->next) {
1803                 if(nu->type == CU_BEZIER) {
1804                         for (i=0; i<nu->pntsu; i++) {
1805                                 BezTriple *bezt = &nu->bezt[i];
1806
1807                                 if(bezt->hide==0) {
1808                                         
1809                                         if(cu->drawflag & CU_HIDE_HANDLES) {
1810                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
1811                                                 if (s[0] != IS_CLIPPED)
1812                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1813                                         } else {
1814                                                 view3d_project_short_clip(vc->ar, bezt->vec[0], s, 1);
1815                                                 if (s[0] != IS_CLIPPED)
1816                                                         func(userData, nu, NULL, bezt, 0, s[0], s[1]);
1817                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
1818                                                 if (s[0] != IS_CLIPPED)
1819                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1820                                                 view3d_project_short_clip(vc->ar, bezt->vec[2], s, 1);
1821                                                 if (s[0] != IS_CLIPPED)
1822                                                         func(userData, nu, NULL, bezt, 2, s[0], s[1]);
1823                                         }
1824                                 }
1825                         }
1826                 }
1827                 else {
1828                         for (i=0; i<nu->pntsu*nu->pntsv; i++) {
1829                                 BPoint *bp = &nu->bp[i];
1830
1831                                 if(bp->hide==0) {
1832                                         view3d_project_short_clip(vc->ar, bp->vec, s, 1);
1833                                         if (s[0] != IS_CLIPPED)
1834                                                 func(userData, nu, bp, NULL, -1, s[0], s[1]);
1835                                 }
1836                         }
1837                 }
1838         }
1839 }
1840
1841 /* ************** DRAW MESH ****************** */
1842
1843 /* First section is all the "simple" draw routines, 
1844  * ones that just pass some sort of primitive to GL,
1845  * with perhaps various options to control lighting,
1846  * color, etc.
1847  *
1848  * These routines should not have user interface related
1849  * logic!!!
1850  */
1851
1852 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
1853 {
1854         ToolSettings *ts= ((Scene *)userData)->toolsettings;
1855         EditFace *efa = EM_get_face_for_index(index);
1856
1857         if (efa->h==0 && efa->fgonf!=EM_FGON) {
1858                 glVertex3fv(cent);
1859                 glVertex3f(     cent[0] + no[0]*ts->normalsize,
1860                                         cent[1] + no[1]*ts->normalsize,
1861                                         cent[2] + no[2]*ts->normalsize);
1862         }
1863 }
1864 static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm) 
1865 {
1866         glBegin(GL_LINES);
1867         dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
1868         glEnd();
1869 }
1870
1871 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
1872 {
1873         EditFace *efa = EM_get_face_for_index(index);
1874         int sel = *((int*) userData);
1875
1876         if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
1877                 bglVertex3fv(cent);
1878         }
1879 }
1880 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
1881 {
1882         bglBegin(GL_POINTS);
1883         dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
1884         bglEnd();
1885 }
1886
1887 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1888 {
1889         Scene *scene= (Scene *)userData;
1890         ToolSettings *ts= scene->toolsettings;
1891         EditVert *eve = EM_get_vert_for_index(index);
1892
1893         if (eve->h==0) {
1894                 glVertex3fv(co);
1895
1896                 if (no_f) {
1897                         glVertex3f(     co[0] + no_f[0]*ts->normalsize,
1898                                                 co[1] + no_f[1]*ts->normalsize,
1899                                                 co[2] + no_f[2]*ts->normalsize);
1900                 } else {
1901                         glVertex3f(     co[0] + no_s[0]*ts->normalsize/32767.0f,
1902                                                 co[1] + no_s[1]*ts->normalsize/32767.0f,
1903                                                 co[2] + no_s[2]*ts->normalsize/32767.0f);
1904                 }
1905         }
1906 }
1907 static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm) 
1908 {
1909         glBegin(GL_LINES);
1910         dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
1911         glEnd();
1912 }
1913
1914         /* Draw verts with color set based on selection */
1915 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1916 {
1917         struct { int sel; EditVert *eve_act; } * data = userData;
1918         EditVert *eve = EM_get_vert_for_index(index);
1919
1920         if (eve->h==0 && (eve->f&SELECT)==data->sel) {
1921                 /* draw active larger - need to stop/start point drawing for this :/ */
1922                 if (eve==data->eve_act) {
1923                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1924                         UI_ThemeColor4(TH_EDITMESH_ACTIVE);
1925                         
1926                         bglEnd();
1927                         
1928                         glPointSize(size);
1929                         bglBegin(GL_POINTS);
1930                         bglVertex3fv(co);
1931                         bglEnd();
1932                         
1933                         UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
1934                         glPointSize(size);
1935                         bglBegin(GL_POINTS);
1936                 } else {
1937                         bglVertex3fv(co);
1938                 }
1939         }
1940 }
1941
1942 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
1943 {
1944         struct { int sel; EditVert *eve_act; } data;
1945         data.sel = sel;
1946         data.eve_act = eve_act;
1947
1948         bglBegin(GL_POINTS);
1949         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
1950         bglEnd();
1951 }
1952
1953         /* Draw edges with color set based on selection */
1954 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
1955 {
1956         EditEdge *eed = EM_get_edge_for_index(index);
1957         //unsigned char **cols = userData, *col;
1958         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
1959         unsigned char *col;
1960
1961         if (eed->h==0) {
1962                 if (eed==data->eed_act) {
1963                         glColor4ubv(data->actCol);
1964                 } else {
1965                         if (eed->f&SELECT) {
1966                                 col = data->selCol;
1967                         } else {
1968                                 col = data->baseCol;
1969                         }
1970                         /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode  */
1971                         if (col[3]==0) return 0;
1972                         
1973                         glColor4ubv(col);
1974                 }
1975                 return 1;
1976         } else {
1977                 return 0;
1978         }
1979 }
1980 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act) 
1981 {
1982         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
1983         
1984         data.baseCol = baseCol;
1985         data.selCol = selCol;
1986         data.actCol = actCol;
1987         data.eed_act = eed_act;
1988         dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
1989 }
1990
1991         /* Draw edges */
1992 static int draw_dm_edges__setDrawOptions(void *UNUSED(userData), int index)
1993 {
1994         return EM_get_edge_for_index(index)->h==0;
1995 }
1996 static void draw_dm_edges(DerivedMesh *dm) 
1997 {
1998         dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
1999 }
2000
2001         /* Draw edges with color interpolated based on selection */
2002 static int draw_dm_edges_sel_interp__setDrawOptions(void *UNUSED(userData), int index)
2003 {
2004         return EM_get_edge_for_index(index)->h==0;
2005 }
2006 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
2007 {
2008         EditEdge *eed = EM_get_edge_for_index(index);
2009         unsigned char **cols = userData;
2010         unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
2011         unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
2012
2013         glColor4ub(     col0[0] + (col1[0]-col0[0])*t,
2014                                 col0[1] + (col1[1]-col0[1])*t,
2015                                 col0[2] + (col1[2]-col0[2])*t,
2016                                 col0[3] + (col1[3]-col0[3])*t);
2017 }
2018
2019 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
2020 {
2021         unsigned char *cols[2];
2022         cols[0]= baseCol;
2023         cols[1]= selCol;
2024         dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
2025 }
2026
2027         /* Draw only seam edges */
2028 static int draw_dm_edges_seams__setDrawOptions(void *UNUSED(userData), int index)
2029 {
2030         EditEdge *eed = EM_get_edge_for_index(index);
2031
2032         return (eed->h==0 && eed->seam);
2033 }
2034 static void draw_dm_edges_seams(DerivedMesh *dm)
2035 {
2036         dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
2037 }
2038
2039         /* Draw only sharp edges */
2040 static int draw_dm_edges_sharp__setDrawOptions(void *UNUSED(userData), int index)
2041 {
2042         EditEdge *eed = EM_get_edge_for_index(index);
2043
2044         return (eed->h==0 && eed->sharp);
2045 }
2046 static void draw_dm_edges_sharp(DerivedMesh *dm)
2047 {
2048         dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
2049 }
2050
2051
2052         /* Draw faces with color set based on selection
2053          * return 2 for the active face so it renders with stipple enabled */
2054 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *UNUSED(drawSmooth_r))
2055 {
2056         struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
2057         EditFace *efa = EM_get_face_for_index(index);
2058         unsigned char *col;
2059         
2060         if (efa->h==0) {
2061                 if (efa == data->efa_act) {
2062                         glColor4ubv(data->cols[2]);
2063                         return 2; /* stipple */
2064                 } else {
2065                         col = data->cols[(efa->f&SELECT)?1:0];
2066                         if (col[3]==0) return 0;
2067                         glColor4ubv(col);
2068                         return 1;
2069                 }
2070         }
2071         return 0;
2072 }
2073
2074 static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index)
2075 {
2076         struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
2077         EditFace *efa = EM_get_face_for_index(index);
2078         EditFace *next_efa = EM_get_face_for_index(next_index);
2079         unsigned char *col, *next_col;
2080
2081         if(efa == next_efa)
2082                 return 1;
2083
2084         if(efa == data->efa_act || next_efa == data->efa_act)
2085                 return 0;
2086
2087         col = data->cols[(efa->f&SELECT)?1:0];
2088         next_col = data->cols[(next_efa->f&SELECT)?1:0];
2089
2090         if(col[3]==0 || next_col[3]==0)
2091                 return 0;
2092
2093         return col == next_col;
2094 }
2095
2096 /* also draws the active face */
2097 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act) 
2098 {
2099         struct { unsigned char *cols[3]; EditFace *efa_act; } data;
2100         data.cols[0] = baseCol;
2101         data.cols[1] = selCol;
2102         data.cols[2] = actCol;
2103         data.efa_act = efa_act;
2104
2105         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions);
2106 }
2107
2108 static int draw_dm_creases__setDrawOptions(void *UNUSED(userData), int index)
2109 {
2110         EditEdge *eed = EM_get_edge_for_index(index);
2111
2112         if (eed->h==0 && eed->crease != 0.0f) {
2113                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, eed->crease);
2114                 return 1;
2115         } else {
2116                 return 0;
2117         }
2118 }
2119 static void draw_dm_creases(DerivedMesh *dm)
2120 {
2121         glLineWidth(3.0);
2122         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
2123         glLineWidth(1.0);
2124 }
2125
2126 static int draw_dm_bweights__setDrawOptions(void *UNUSED(userData), int index)
2127 {
2128         EditEdge *eed = EM_get_edge_for_index(index);
2129
2130         if (eed->h==0 && eed->bweight != 0.0f) {
2131                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
2132                 return 1;
2133         } else {
2134                 return 0;
2135         }
2136 }
2137 static void draw_dm_bweights__mapFunc(void *UNUSED(userData), int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2138 {
2139         EditVert *eve = EM_get_vert_for_index(index);
2140
2141         if (eve->h==0 && eve->bweight != 0.0f) {
2142                 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
2143                 bglVertex3fv(co);
2144         }
2145 }
2146 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
2147 {
2148         ToolSettings *ts= scene->toolsettings;
2149
2150         if (ts->selectmode & SCE_SELECT_VERTEX) {
2151                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2152                 bglBegin(GL_POINTS);
2153                 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
2154                 bglEnd();
2155         }
2156         else {
2157                 glLineWidth(3.0);
2158                 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
2159                 glLineWidth(1.0);
2160         }
2161 }
2162
2163 /* Second section of routines: Combine first sets to form fancy
2164  * drawing routines (for example rendering twice to get overlays).
2165  *
2166  * Also includes routines that are basic drawing but are too
2167  * specialized to be split out (like drawing creases or measurements).
2168  */
2169
2170 /* EditMesh drawing routines*/
2171
2172 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, DerivedMesh *cageDM, EditVert *eve_act)
2173 {
2174         ToolSettings *ts= scene->toolsettings;
2175         int sel;
2176
2177         if(v3d->zbuf) glDepthMask(0);           // disable write in zbuffer, zbuf select
2178
2179         for (sel=0; sel<2; sel++) {
2180                 unsigned char col[4], fcol[4];
2181                 int pass;
2182
2183                 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
2184                 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
2185
2186                 for (pass=0; pass<2; pass++) {
2187                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2188                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2189
2190                         if (pass==0) {
2191                                 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
2192                                         glDisable(GL_DEPTH_TEST);
2193                                                 
2194                                         glEnable(GL_BLEND);
2195                                 } else {
2196                                         continue;
2197                                 }
2198
2199                                 size = (size > 2.1f ? size/2.0f:size);
2200                                 fsize = (fsize > 2.1f ? fsize/2.0f:fsize);
2201                                 col[3] = fcol[3] = 100;
2202                         } else {
2203                                 col[3] = fcol[3] = 255;
2204                         }
2205                                 
2206                         if(ts->selectmode & SCE_SELECT_VERTEX) {
2207                                 glPointSize(size);
2208                                 glColor4ubv(col);
2209                                 draw_dm_verts(cageDM, sel, eve_act);
2210                         }
2211                         
2212                         if(check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2213                                 glPointSize(fsize);
2214                                 glColor4ubv(fcol);
2215                                 draw_dm_face_centers(cageDM, sel);
2216                         }
2217                         
2218                         if (pass==0) {
2219                                 glDisable(GL_BLEND);
2220                                 glEnable(GL_DEPTH_TEST);
2221                         }
2222                 }
2223         }
2224
2225         if(v3d->zbuf) glDepthMask(1);
2226         glPointSize(1.0);
2227 }
2228
2229 static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
2230 {
2231         ToolSettings *ts= scene->toolsettings;
2232         int pass;
2233         unsigned char wireCol[4], selCol[4], actCol[4];
2234
2235         /* since this function does transparant... */
2236         UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2237         UI_GetThemeColor4ubv(TH_WIRE, wireCol);
2238         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2239         
2240         /* when sel only is used, dont render wire, only selected, this is used for
2241          * textured draw mode when the 'edges' option is disabled */
2242         if (sel_only)
2243                 wireCol[3] = 0;
2244
2245         for (pass=0; pass<2; pass++) {
2246                         /* show wires in transparant when no zbuf clipping for select */
2247                 if (pass==0) {
2248                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
2249                                 glEnable(GL_BLEND);
2250                                 glDisable(GL_DEPTH_TEST);
2251                                 selCol[3] = 85;
2252                                 if (!sel_only) wireCol[3] = 85;
2253                         } else {
2254                                 continue;
2255                         }
2256                 } else {
2257                         selCol[3] = 255;
2258                         if (!sel_only) wireCol[3] = 255;
2259                 }
2260
2261                 if(ts->selectmode == SCE_SELECT_FACE) {
2262                         draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2263                 }       
2264                 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {        
2265                         if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2266                                 glShadeModel(GL_SMOOTH);
2267                                 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
2268                                 glShadeModel(GL_FLAT);
2269                         } else {
2270                                 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2271                         }
2272                 }
2273                 else {
2274                         if (!sel_only) {
2275                                 glColor4ubv(wireCol);
2276                                 draw_dm_edges(cageDM);
2277                         }
2278                 }
2279
2280                 if (pass==0) {
2281                         glDisable(GL_BLEND);
2282                         glEnable(GL_DEPTH_TEST);
2283                 }
2284         }
2285 }       
2286
2287 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, UnitSettings *unit)
2288 {
2289         Mesh *me= ob->data;
2290         EditEdge *eed;
2291         EditFace *efa;
2292         float v1[3], v2[3], v3[3], v4[3], vmid[3];
2293         float fvec[3];
2294         char val[32]; /* Stores the measurement display text here */
2295         const char *conv_float; /* Use a float conversion matching the grid size */
2296         unsigned char col[4]= {0, 0, 0, 255}; /* color of the text to draw */
2297         float area; /* area of the face */
2298         float grid= unit->system ? unit->scale_length : v3d->grid;
2299         const int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
2300         const int do_global= v3d->flag & V3D_GLOBAL_STATS;
2301         const int do_moving= G.moving;
2302
2303         /* make the precision of the pronted value proportionate to the gridsize */
2304
2305         if (grid < 0.01f)               conv_float= "%.6g";
2306         else if (grid < 0.1f)   conv_float= "%.5g";
2307         else if (grid < 1.0f)   conv_float= "%.4g";
2308         else if (grid < 10.0f)  conv_float= "%.3g";
2309         else                                    conv_float= "%.2g";
2310
2311         if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
2312                 glDisable(GL_DEPTH_TEST);
2313
2314         if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
2315         
2316         if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2317                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2318
2319                 for(eed= em->edges.first; eed; eed= eed->next) {
2320                         /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
2321                         if((eed->h != EM_FGON) && ((eed->f & SELECT) || (do_moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
2322                                 copy_v3_v3(v1, eed->v1->co);
2323                                 copy_v3_v3(v2, eed->v2->co);
2324
2325                                 interp_v3_v3v3(vmid, v1, v2, 0.5f);
2326
2327                                 if(do_global) {
2328                                         mul_mat3_m4_v3(ob->obmat, v1);
2329                                         mul_mat3_m4_v3(ob->obmat, v2);
2330                                 }
2331                                 if(unit->system)
2332                                         bUnit_AsString(val, sizeof(val), len_v3v3(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
2333                                 else
2334                                         sprintf(val, conv_float, len_v3v3(v1, v2));
2335
2336                                 view3d_cached_text_draw_add(vmid, val, 0, V3D_CACHE_TEXT_ASCII, col);
2337                         }
2338                 }
2339         }
2340
2341         if(me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2342 // XXX          extern int faceselectedOR(EditFace *efa, int flag);             // editmesh.h shouldn't be in this file... ok for now?
2343                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2344                 
2345                 for(efa= em->faces.first; efa; efa= efa->next) {
2346                         if((efa->f & SELECT)) { // XXX || (do_moving && faceselectedOR(efa, SELECT)) ) {
2347                                 copy_v3_v3(v1, efa->v1->co);
2348                                 copy_v3_v3(v2, efa->v2->co);
2349                                 copy_v3_v3(v3, efa->v3->co);
2350                                 if (efa->v4) {
2351                                         copy_v3_v3(v4, efa->v4->co);
2352                                 }
2353                                 if(do_global) {
2354                                         mul_mat3_m4_v3(ob->obmat, v1);
2355                                         mul_mat3_m4_v3(ob->obmat, v2);
2356                                         mul_mat3_m4_v3(ob->obmat, v3);
2357                                         if (efa->v4) mul_mat3_m4_v3(ob->obmat, v4);
2358                                 }
2359                                 
2360                                 if (efa->v4)
2361                                         area=  area_quad_v3(v1, v2, v3, v4);
2362                                 else
2363                                         area = area_tri_v3(v1, v2, v3);
2364
2365                                 if(unit->system)
2366                                         bUnit_AsString(val, sizeof(val), area*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); // XXX should be B_UNIT_AREA
2367                                 else
2368                                         sprintf(val, conv_float, area);
2369
2370                                 view3d_cached_text_draw_add(efa->cent, val, 0, V3D_CACHE_TEXT_ASCII, col);
2371                         }
2372                 }
2373         }
2374
2375         if(me->drawflag & ME_DRAWEXTRA_FACEANG) {
2376                 EditEdge *e1, *e2, *e3, *e4;
2377                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2378                 for(efa= em->faces.first; efa; efa= efa->next) {
2379                         copy_v3_v3(v1, efa->v1->co);
2380                         copy_v3_v3(v2, efa->v2->co);
2381                         copy_v3_v3(v3, efa->v3->co);
2382                         if(efa->v4) {
2383                                 copy_v3_v3(v4, efa->v4->co); 
2384                         }
2385                         else {
2386                                 copy_v3_v3(v4, v3);
2387                         }
2388                         if(do_global) {
2389                                 mul_mat3_m4_v3(ob->obmat, v1);
2390                                 mul_mat3_m4_v3(ob->obmat, v2);
2391                                 mul_mat3_m4_v3(ob->obmat, v3);
2392                                 mul_mat3_m4_v3(ob->obmat, v4); /* intentionally executed even for tri's */
2393                         }
2394                         
2395                         e1= efa->e1;
2396                         e2= efa->e2;
2397                         e3= efa->e3;
2398                         if(efa->e4) e4= efa->e4; else e4= e3;
2399                         
2400                         /* Calculate the angles */
2401                                 
2402                         if( (e4->f & e1->f & SELECT) || (do_moving && (efa->v1->f & SELECT)) ) {
2403                                 /* Vec 1 */
2404                                 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v4, v1, v2)));
2405                                 interp_v3_v3v3(fvec, efa->cent, efa->v1->co, 0.8f);
2406                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2407                         }
2408                         if( (e1->f & e2->f & SELECT) || (do_moving && (efa->v2->f & SELECT)) ) {
2409                                 /* Vec 2 */
2410                                 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v1, v2, v3)));
2411                                 interp_v3_v3v3(fvec, efa->cent, efa->v2->co, 0.8f);
2412                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2413                         }
2414                         if( (e2->f & e3->f & SELECT) || (do_moving && (efa->v3->f & SELECT)) ) {
2415                                 /* Vec 3 */
2416                                 if(efa->v4) 
2417                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v4)));
2418                                 else
2419                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v1)));
2420                                 interp_v3_v3v3(fvec, efa->cent, efa->v3->co, 0.8f);
2421                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2422                         }
2423                                 /* Vec 4 */
2424                         if(efa->v4) {
2425                                 if( (e3->f & e4->f & SELECT) || (do_moving && (efa->v4->f & SELECT)) ) {
2426                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v3, v4, v1)));
2427                                         interp_v3_v3v3(fvec, efa->cent, efa->v4->co, 0.8f);
2428                                         view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2429                                 }
2430                         }
2431                 }
2432         }
2433
2434         /* useful for debugging index vs shape key index */
2435 #if 0
2436         {
2437                 EditVert *eve;
2438                 int j;
2439                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2440                 for(eve= em->verts.first, j= 0; eve; eve= eve->next, j++) {
2441                         sprintf(val, "%d:%d", j, eve->keyindex);
2442                         view3d_cached_text_draw_add(eve->co, val, 0, V3D_CACHE_TEXT_ASCII, col);
2443                 }
2444         }
2445 #endif
2446
2447         if(v3d->zbuf) {
2448                 glEnable(GL_DEPTH_TEST);
2449                 bglPolygonOffset(rv3d->dist, 0.0f);
2450         }
2451 }
2452
2453 static int draw_em_fancy__setFaceOpts(void *UNUSED(userData), int index, int *UNUSED(drawSmooth_r))
2454 {
2455         EditFace *efa = EM_get_face_for_index(index);
2456
2457         if (efa->h==0) {
2458                 GPU_enable_material(efa->mat_nr+1, NULL);
2459                 return 1;
2460         }
2461         else
2462                 return 0;
2463 }
2464
2465 static int draw_em_fancy__setGLSLFaceOpts(void *UNUSED(userData), int index)
2466 {
2467         EditFace *efa = EM_get_face_for_index(index);
2468
2469         return (efa->h==0);
2470 }
2471
2472 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2473 {
2474         Mesh *me = ob->data;
2475         EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2476         EditEdge *eed_act = NULL;
2477         EditVert *eve_act = NULL;
2478         
2479         if (em->selected.last) {
2480                 EditSelection *ese = em->selected.last;
2481                 /* face is handeled above */
2482                 /*if (ese->type == EDITFACE ) {
2483                         efa_act = (EditFace *)ese->data;
2484                 } else */ if ( ese->type == EDITEDGE ) {
2485                         eed_act = (EditEdge *)ese->data;
2486                 } else if ( ese->type == EDITVERT ) {
2487                         eve_act = (EditVert *)ese->data;
2488                 }
2489         }
2490         
2491         EM_init_index_arrays(em, 1, 1, 1);
2492
2493         if(dt>OB_WIRE) {
2494                 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2495                         if(draw_glsl_material(scene, ob, v3d, dt)) {
2496                                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2497
2498                                 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2499                                         draw_em_fancy__setGLSLFaceOpts, NULL);
2500                                 GPU_disable_material();
2501
2502                                 glFrontFace(GL_CCW);
2503                         }
2504                         else {
2505                                 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2506                         }
2507                 }
2508                 else {
2509                         /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
2510                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2511
2512                         glEnable(GL_LIGHTING);
2513                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2514
2515                         finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, NULL, 0, GPU_enable_material, NULL);
2516
2517                         glFrontFace(GL_CCW);
2518                         glDisable(GL_LIGHTING);
2519                 }
2520                         
2521                 // Setup for drawing wire over, disable zbuffer
2522                 // write to show selected edge wires better
2523                 UI_ThemeColor(TH_WIRE);
2524
2525                 bglPolygonOffset(rv3d->dist, 1.0);
2526                 glDepthMask(0);
2527         } 
2528         else {
2529                 if (cageDM!=finalDM) {
2530                         UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2531                         finalDM->drawEdges(finalDM, 1, 0);
2532                 }
2533         }
2534         
2535         if(me->drawflag & ME_DRAWFACES) {       /* transp faces */
2536                 unsigned char col1[4], col2[4], col3[4];
2537                         
2538                 UI_GetThemeColor4ubv(TH_FACE, col1);
2539                 UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
2540                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2541                 
2542                 glEnable(GL_BLEND);
2543                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2544                 
2545                 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2546                 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2547                         col1[3] = 0;
2548                 
2549                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2550
2551                 glDisable(GL_BLEND);
2552                 glDepthMask(1);         // restore write in zbuffer
2553         } else if (efa_act) {
2554                 /* even if draw faces is off it would be nice to draw the stipple face
2555                  * Make all other faces zero alpha except for the active
2556                  * */
2557                 unsigned char col1[4], col2[4], col3[4];
2558                 col1[3] = col2[3] = 0; /* dont draw */
2559                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2560                 
2561                 glEnable(GL_BLEND);
2562                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2563                 
2564                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2565
2566                 glDisable(GL_BLEND);
2567                 glDepthMask(1);         // restore write in zbuffer
2568                 
2569         }
2570
2571         /* here starts all fancy draw-extra over */
2572         if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2573                 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2574                 
2575                 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2576                 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
2577                 
2578         } else {
2579                 if(me->drawflag & ME_DRAWSEAMS) {
2580                         UI_ThemeColor(TH_EDGE_SEAM);
2581                         glLineWidth(2);
2582         
2583                         draw_dm_edges_seams(cageDM);
2584         
2585                         glColor3ub(0,0,0);
2586                         glLineWidth(1);
2587                 }
2588                 
2589                 if(me->drawflag & ME_DRAWSHARP) {
2590                         UI_ThemeColor(TH_EDGE_SHARP);
2591                         glLineWidth(2);
2592         
2593                         draw_dm_edges_sharp(cageDM);
2594         
2595                         glColor3ub(0,0,0);
2596                         glLineWidth(1);
2597                 }
2598         
2599                 if(me->drawflag & ME_DRAWCREASES) {
2600                         draw_dm_creases(cageDM);
2601                 }
2602                 if(me->drawflag & ME_DRAWBWEIGHTS) {
2603                         draw_dm_bweights(scene, cageDM);
2604                 }
2605         
2606                 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
2607         }
2608         if(em) {
2609 // XXX          retopo_matrix_update(v3d);
2610
2611                 draw_em_fancy_verts(scene, v3d, ob, cageDM, eve_act);
2612
2613                 if(me->drawflag & ME_DRAWNORMALS) {
2614                         UI_ThemeColor(TH_NORMAL);
2615                         draw_dm_face_normals(scene, cageDM);
2616                 }
2617                 if(me->drawflag & ME_DRAW_VNORMALS) {
2618                         UI_ThemeColor(TH_VNORMAL);
2619                         draw_dm_vert_normals(scene, cageDM);
2620                 }
2621
2622                 if(me->drawflag & (ME_DRAWEXTRA_EDGELEN|ME_DRAWEXTRA_FACEAREA|ME_DRAWEXTRA_FACEANG) && !((v3d->flag2 & V3D_RENDER_OVERRIDE)))
2623                         draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
2624         }
2625
2626         if(dt>OB_WIRE) {
2627                 glDepthMask(1);
2628                 bglPolygonOffset(rv3d->dist, 0.0);
2629                 GPU_disable_material();
2630         }
2631
2632         EM_free_index_arrays();
2633 }
2634
2635 /* Mesh drawing routines */
2636
2637 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2638 {
2639         
2640         if(v3d->transp==0) {    // not when we draw the transparent pass
2641                 glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
2642                 glDepthMask(0);
2643                 
2644                 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2645                    drawFacesSolid() doesn't draw the transparent faces */
2646                 if(ob->dtx & OB_DRAWTRANSP) {
2647                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2648                         dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2649                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2650                         GPU_disable_material();
2651                 }
2652                 else {
2653                         dm->drawEdges(dm, 0, 1);
2654                 }
2655                                         
2656                 glLineWidth(1.0);
2657                 glDepthMask(1);
2658         }
2659 }
2660
2661 static int wpaint__setSolidDrawOptions(void *UNUSED(userData), int UNUSED(index), int *drawSmooth_r)
2662 {
2663         *drawSmooth_r = 1;
2664         return 1;
2665 }
2666
2667 static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2668 {
2669         Object *ob= base->object;
2670         Mesh *me = ob->data;
2671         Material *ma= give_current_material(ob, 1);
2672         const short hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
2673         const short is_paint_sel= (ob==OBACT && paint_facesel_test(ob));
2674         int draw_wire = 0;
2675         int /* totvert,*/ totedge, totface;
2676         DerivedMesh *dm= mesh_get_derived_final(scene, ob, scene->customdata_mask);
2677
2678         if(!dm)
2679                 return;
2680         
2681         if (ob->dtx&OB_DRAWWIRE) {
2682                 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
2683         }
2684         
2685         /* totvert = dm->getNumVerts(dm); */ /*UNUSED*/
2686         totedge = dm->getNumEdges(dm);
2687         totface = dm->getNumFaces(dm);
2688         
2689         /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2690         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2691
2692                 // Unwanted combination.
2693         if (is_paint_sel) draw_wire = 0;
2694
2695         if(dt==OB_BOUNDBOX) {
2696                 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_WIRE)==0)
2697                         draw_bounding_volume(scene, ob);
2698         }
2699         else if(hasHaloMat || (totface==0 && totedge==0)) {
2700                 glPointSize(1.5);
2701                 dm->drawVerts(dm);
2702                 glPointSize(1.0);
2703         }
2704         else if(dt==OB_WIRE || totface==0) {
2705                 draw_wire = 1; /* draw wire only, no depth buffer stuff  */
2706         }
2707         else if(        (is_paint_sel || (ob==OBACT && ob->mode & OB_MODE_TEXTURE_PAINT)) ||
2708                                 CHECK_OB_DRAWTEXTURE(v3d, dt))
2709         {
2710                 if ((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !(G.f&G_PICKSEL || is_paint_sel) && !draw_wire) {
2711                         draw_mesh_object_outline(v3d, ob, dm);
2712                 }
2713
2714                 if(draw_glsl_material(scene, ob, v3d, dt)) {
2715                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2716
2717                         dm->drawFacesGLSL(dm, GPU_enable_material);
2718 //                      if(get_ob_property(ob, "Text"))
2719 // XXX                          draw_mesh_text(ob, 1);
2720                         GPU_disable_material();
2721
2722                         glFrontFace(GL_CCW);
2723                 }
2724                 else {
2725                         draw_mesh_textured(scene, v3d, rv3d, ob, dm, is_paint_sel);
2726                 }
2727
2728                 if(!is_paint_sel) {
2729                         if(base->flag & SELECT)
2730                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2731                         else
2732                                 UI_ThemeColor(TH_WIRE);
2733
2734                         if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
2735                                 dm->drawLooseEdges(dm);
2736                 }
2737         }
2738         else if(dt==OB_SOLID) {
2739                 if(ob==OBACT && ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2740                         /* weight paint in solid mode, special case. focus on making the weights clear
2741                          * rather than the shading, this is also forced in wire view */
2742                         GPU_enable_material(0, NULL);
2743                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material, NULL);
2744                 
2745                         bglPolygonOffset(rv3d->dist, 1.0);
2746                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2747
2748                         glEnable(GL_BLEND);
2749                         glColor4ub(255, 255, 255, 96);
2750                         glEnable(GL_LINE_STIPPLE);
2751                         glLineStipple(1, 0xAAAA);
2752
2753                         dm->drawEdges(dm, 1, 1);
2754
2755                         bglPolygonOffset(rv3d->dist, 0.0);
2756                         glDepthMask(1);
2757                         glDisable(GL_LINE_STIPPLE);
2758
2759                         GPU_disable_material();
2760                         
2761                         /* since we already draw wire as wp guide, dont draw over the top */
2762                         draw_wire= 0;
2763                 }
2764                 else {
2765                         Paint *p;
2766
2767                         if((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !draw_wire && !ob->sculpt)
2768                                 draw_mesh_object_outline(v3d, ob, dm);
2769
2770                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
2771
2772                         glEnable(GL_LIGHTING);
2773                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2774
2775                         if(ob->sculpt && (p=paint_get_active(scene))) {
2776                                 float planes[4][4];
2777                                 float (*fpl)[4] = NULL;
2778                                 int fast= (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING);
2779
2780                                 if(ob->sculpt->partial_redraw) {
2781                                         if(ar->do_draw & RGN_DRAW_PARTIAL) {
2782                                                 sculpt_get_redraw_planes(planes, ar, rv3d, ob);
2783                                                 fpl = planes;
2784                                                 ob->sculpt->partial_redraw = 0;
2785                                         }
2786                                 }
2787
2788                                 dm->drawFacesSolid(dm, fpl, fast, GPU_enable_material);
2789                         }
2790                         else
2791                                 dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2792
2793                         GPU_disable_material();
2794
2795                         glFrontFace(GL_CCW);
2796                         glDisable(GL_LIGHTING);
2797
2798                         if(base->flag & SELECT) {
2799                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2800                         } else {
2801                                 UI_ThemeColor(TH_WIRE);
2802                         }
2803                         if(!ob->sculpt && (v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
2804                                 dm->drawLooseEdges(dm);
2805                 }
2806         }
2807         else if(dt==OB_PAINT) {
2808                 if(ob==OBACT) {
2809                         if(ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2810                                 /* enforce default material settings */
2811                                 GPU_enable_material(0, NULL);
2812                                 
2813                                 /* but set default spec */
2814                                 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
2815                                 glEnable(GL_COLOR_MATERIAL);    /* according manpages needed */
2816                                 glColor3ub(120, 120, 120);
2817                                 glDisable(GL_COLOR_MATERIAL);
2818                                 /* diffuse */
2819                                 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2820                                 glEnable(GL_LIGHTING);
2821                                 glEnable(GL_COLOR_MATERIAL);
2822
2823                                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material, NULL);
2824                                 glDisable(GL_COLOR_MATERIAL);
2825                                 glDisable(GL_LIGHTING);
2826
2827                                 GPU_disable_material();
2828                         }
2829                         else if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_TEXTURE_PAINT)) {
2830                                 if(me->mcol)
2831                                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1, GPU_enable_material, NULL);
2832                                 else {
2833                                         glColor3f(1.0f, 1.0f, 1.0f);
2834                                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0, GPU_enable_material, NULL);
2835                                 }
2836                         }
2837                 }
2838         }
2839         
2840         /* set default draw color back for wire or for draw-extra later on */
2841         if (dt!=OB_WIRE) {
2842                 if(base->flag & SELECT) {
2843                         if(ob==OBACT && ob->flag & OB_FROMGROUP) 
2844                                 UI_ThemeColor(TH_GROUP_ACTIVE);
2845                         else if(ob->flag & OB_FROMGROUP) 
2846                                 UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
2847                         else if(flag!=DRAW_CONSTCOLOR)
2848                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2849                         else
2850                                 glColor3ub(80,80,80);
2851                 } else {
2852                         if (ob->flag & OB_FROMGROUP) 
2853                                 UI_ThemeColor(TH_GROUP);
2854                         else {
2855                                 if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
2856                                         glColor3ub(80,80,80);
2857                                 else
2858                                         UI_ThemeColor(TH_WIRE);
2859                         }
2860                 }
2861         }
2862         if (draw_wire) {
2863
2864                 /* When using wireframe object traw in particle edit mode
2865                  * the mesh gets in the way of seeing the particles, fade the wire color
2866                  * with the background. */
2867                 if(ob==OBACT && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
2868                         float col_wire[4], col_bg[4], col[3];
2869
2870                         UI_GetThemeColor3fv(TH_BACK, col_bg);
2871                         glGetFloatv(GL_CURRENT_COLOR, col_wire);
2872                         interp_v3_v3v3(col, col_bg, col_wire, 0.15);
2873                         glColor3fv(col);
2874                 }
2875
2876                 /* If drawing wire and drawtype is not OB_WIRE then we are
2877                  * overlaying the wires.
2878                  *
2879                  * UPDATE bug #10290 - With this wire-only objects can draw
2880                  * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
2881                  *
2882                  * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
2883                  * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
2884                  */
2885                 if (dt!=OB_WIRE && draw_wire==2) {
2886                         bglPolygonOffset(rv3d->dist, 1.0);
2887                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2888                 }
2889                 
2890                 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_SOLID)==0)
2891                         dm->drawEdges(dm, (dt==OB_WIRE || totface==0), me->drawflag & ME_ALLEDGES);
2892
2893                 if (dt!=OB_WIRE && draw_wire==2) {
2894                         glDepthMask(1);
2895                         bglPolygonOffset(rv3d->dist, 0.0);
2896                 }
2897         }
2898
2899         dm->release(dm);
2900 }
2901
2902 /* returns 1 if nothing was drawn, for detecting to draw an object center */
2903 static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2904 {
2905         Object *ob= base->object;
2906         Object *obedit= scene->obedit;
2907         Mesh *me= ob->data;
2908         EditMesh *em= me->edit_mesh;
2909         int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha, i;
2910
2911         /* If we are drawing shadows and any of the materials don't cast a shadow,
2912          * then don't draw the object */
2913         if (v3d->flag2 & V3D_RENDER_SHADOW) {
2914                 for(i=0; i<ob->totcol; ++i) {
2915                         Material *ma= give_current_material(ob, i);
2916                         if (ma && !(ma->mode & MA_SHADBUF)) {
2917                                 return 1;
2918                         }
2919                 }
2920         }
2921         
2922         if(obedit && ob!=obedit && ob->data==obedit->data) {
2923                 if(ob_get_key(ob) || ob_get_key(obedit));
2924                 else if(ob->modifiers.first || obedit->modifiers.first);
2925                 else drawlinked= 1;
2926         }
2927         
2928         if(ob==obedit || drawlinked) {
2929                 DerivedMesh *finalDM, *cageDM;
2930                 
2931                 if (obedit!=ob)
2932                         finalDM = cageDM = editmesh_get_derived_base(ob, em);
2933                 else
2934                         cageDM = editmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
2935                                                                                         scene->customdata_mask);
2936
2937                 if(dt>OB_WIRE) {
2938                         // no transp in editmode, the fancy draw over goes bad then
2939                         glsl = draw_glsl_material(scene, ob, v3d, dt);
2940                         GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
2941                 }
2942
2943                 draw_em_fancy(scene, v3d, rv3d, ob, em, cageDM, finalDM, dt);
2944
2945                 GPU_end_object_materials();
2946
2947                 if (obedit!=ob && finalDM)
2948                         finalDM->release(finalDM);
2949         }
2950         else {
2951                 /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */
2952                 if(me->totface<=4 || ED_view3d_boundbox_clip(rv3d, ob->obmat, (ob->bb)? ob->bb: me->bb)) {
2953                         glsl = draw_glsl_material(scene, ob, v3d, dt);
2954                         check_alpha = check_material_alpha(base, me, glsl);
2955
2956                         if(dt==OB_SOLID || glsl) {
2957                                 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl,
2958                                         (check_alpha)? &do_alpha_pass: NULL);
2959                         }
2960
2961                         draw_mesh_fancy(scene, ar, v3d, rv3d, base, dt, flag);
2962
2963                         GPU_end_object_materials();
2964                         
2965                         if(me->totvert==0) retval= 1;
2966                 }
2967         }
2968         
2969         /* GPU_begin_object_materials checked if this is needed */
2970         if(do_alpha_pass) {
2971                 if(ob->dtx & OB_DRAWXRAY) {
2972                         add_view3d_after(&v3d->afterdraw_xraytransp, base, flag);
2973                 }
2974                 else {
2975                         add_view3d_after(&v3d->afterdraw_transp, base, flag);
2976                 }
2977         }
2978         else if(ob->dtx & OB_DRAWXRAY && ob->dtx & OB_DRAWTRANSP) {
2979                 /* special case xray+transp when alpha is 1.0, without this the object vanishes */
2980                 if(v3d->xray == 0 && v3d->transp == 0) {
2981                         add_view3d_after(&v3d->afterdraw_xray, base, flag);
2982                 }
2983         }
2984         
2985         return retval;
2986 }
2987
2988 /* ************** DRAW DISPLIST ****************** */
2989
2990 static int draw_index_wire= 1;
2991 static int index3_nors_incr= 1;
2992
2993 /* returns 1 when nothing was drawn */
2994 static int drawDispListwire(ListBase *dlbase)
2995 {
2996         DispList *dl;
2997         int parts, nr;
2998         float *data;
2999
3000         if(dlbase==NULL) return 1;
3001         
3002         glEnableClientState(GL_VERTEX_ARRAY);
3003         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
3004
3005         for(dl= dlbase->first; dl; dl= dl->next) {
3006                 if(dl->parts==0 || dl->nr==0)
3007                         continue;
3008                 
3009                 data= dl->verts;
3010         
3011                 switch(dl->type) {
3012                 case DL_SEGM:
3013                         
3014                         glVertexPointer(3, GL_FLOAT, 0, data);
3015                         
3016                         for(parts=0; parts<dl->parts; parts++)
3017                                 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
3018                                 
3019                         break;
3020                 case DL_POLY:
3021                         
3022                         glVertexPointer(3, GL_FLOAT, 0, data);
3023                         
3024                         for(parts=0; parts<dl->parts; parts++)
3025                                 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
3026                         
3027                         break;
3028                 case DL_SURF:
3029                         
3030                         glVertexPointer(3, GL_FLOAT, 0, data);
3031                         
3032                         for(parts=0; parts<dl->parts; parts++) {
3033                                 if(dl->flag & DL_CYCL_U) 
3034                                         glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
3035                                 else
3036                                         glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
3037                         }
3038                         
3039                         for(nr=0; nr<dl->nr; nr++) {
3040                                 int ofs= 3*dl->nr;
3041                                 
3042                                 data= (  dl->verts )+3*nr;
3043                                 parts= dl->parts;
3044
3045                                 if(dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP);
3046                                 else glBegin(GL_LINE_STRIP);
3047                                 
3048                                 while(parts--) {
3049                                         glVertex3fv(data);
3050                                         data+=ofs;
3051                                 }
3052                                 glEnd();
3053                                 
3054                                 /* (ton) this code crashes for me when resolv is 86 or higher... no clue */
3055 //                              glVertexPointer(3, GL_FLOAT, sizeof(float)*3*dl->nr, data + 3*nr);
3056 //                              if(dl->flag & DL_CYCL_V) 
3057 //                                      glDrawArrays(GL_LINE_LOOP, 0, dl->parts);
3058 //                              else
3059 //                                      glDrawArrays(GL_LINE_STRIP, 0, dl->parts);
3060                         }
3061                         break;
3062                         
3063                 case DL_INDEX3:
3064                         if(draw_index_wire) {
3065                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
3066                                 glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
3067                         }
3068                         break;
3069                         
3070                 case DL_INDEX4:
3071                         if(draw_index_wire) {
3072                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
3073                                 glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
3074                         }
3075                         break;
3076                 }
3077         }
3078         
3079         glDisableClientState(GL_VERTEX_ARRAY);
3080         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 
3081         
3082         return 0;
3083 }
3084
3085 static void drawDispListsolid(ListBase *lb, Object *ob, int glsl)