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