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