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