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