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