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