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