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