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