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