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