79412480d9556bf499b5afcfec1ec718bb7fbf62
[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_arithb.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 static void view3d_project_short_clip(ARegion *ar, float *vec, short *adr)
144 {
145         RegionView3D *rv3d= ar->regiondata;
146         float fx, fy, vec4[4];
147         
148         adr[0]= IS_CLIPPED;
149         
150         /* clipplanes in eye space */
151         if(rv3d->rflag & RV3D_CLIPPING) {
152                 VECCOPY(vec4, vec);
153                 Mat4MulVecfl(rv3d->viewmatob, vec4);
154                 if(view3d_test_clipping(rv3d, vec4))
155                         return;
156         }
157         
158         VECCOPY(vec4, vec);
159         vec4[3]= 1.0;
160         
161         Mat4MulVec4fl(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         Mat4MulVec4fl(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_extensions_minimum_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         VecMulf(vx, rad);
458         VecMulf(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                         Mat4MulVecfl(mat, vos->vec);
546                 view3d_project_short_clip(ar, vos->vec, vos->mval);
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(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(lvec);
707         Normalize(vvec);                                /* is this the correct vector ? */
708
709         Crossf(temp,vvec,lvec);         /* equation for a plane through vvec en lvec */
710         Crossf(plane,lvec,temp);                /* a plane perpendicular to this, parrallel with lvec */
711
712         Normalize(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(&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         QuatToMat3(q,mat1);
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         Mat3One(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         Mat3MulMat3(mat3,mat2,mat1);
753
754         mat2[1][0] =  si;
755         mat2[0][1] = -si;
756         Mat3MulMat3(mat4,mat2,mat1);
757         Mat3Transp(mat1);
758
759         Mat3MulMat3(mat2,mat1,mat3);
760         Mat3MulVecfl(mat2,lvec);
761         Mat3MulMat3(mat2,mat1,mat4);
762         Mat3MulVecfl(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         Mat4CpyMat4(imat, rv3d->viewinv);
791         Normalize(imat[0]);
792         Normalize(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                 VecRotToMat3(imat[2], M_PI/4.0f, mat);
837                 
838                 /* vectors */
839                 VECCOPY(v1, imat[0]);
840                 VecMulf(v1, circrad*1.2f);
841                 VECCOPY(v2, imat[0]);
842                 VecMulf(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                         Mat3MulVecfl(mat, v1);
854                         Mat3MulVecfl(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                         /* make sure the line is always visible - prevent it from reaching the outer border (or 0) 
924                          * values are kinda arbitrary - just what seemed to work well */
925                         if (spotblcirc == 0) spotblcirc = 0.15;
926                         else if (spotblcirc == fabs(z)) spotblcirc = fabs(z) - 0.07;
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                         Mat4CpyMat4(vec, ob->obmat);
1146                         Mat4Ortho(vec);
1147                         wmMultMatrix(vec);
1148
1149                         Mat4SwapMat4(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                         Mat4SwapMat4(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         for (i=0; i<N; i++, bp++, co+=3) {
1209                 if (bp->hide==0) {
1210                         view3d_project_short_clip(vc->ar, dl?co:bp->vec, s);
1211                         if (s[0] != IS_CLIPPED)
1212                                 func(userData, bp, s[0], s[1]);
1213                 }
1214         }
1215 }
1216
1217 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1218 {
1219         int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
1220
1221         if(use_wcol) {
1222                 float col[3];
1223                 MDeformWeight *mdw= ED_vgroup_weight_get (lt->dvert+index, use_wcol-1);
1224                 
1225                 weight_to_rgb(mdw?mdw->weight:0.0f, col, col+1, col+2);
1226                 glColor3fv(col);
1227
1228         }
1229         
1230         if (dl) {
1231                 glVertex3fv(&dl->verts[index*3]);
1232         } else {
1233                 glVertex3fv(lt->def[index].vec);
1234         }
1235 }
1236
1237 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1238 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1239 {
1240         Lattice *lt= ob->data;
1241         DispList *dl;
1242         int u, v, w;
1243         int use_wcol= 0;
1244
1245         /* now we default make displist, this will modifiers work for non animated case */
1246         if(ob->disp.first==NULL)
1247                 lattice_calc_modifiers(scene, ob);
1248         dl= find_displist(&ob->disp, DL_VERTS);
1249         
1250         if(lt->editlatt) {
1251                 cpack(0x004000);
1252                 
1253                 if(ob->defbase.first && lt->dvert) {
1254                         use_wcol= ob->actdef;
1255                         glShadeModel(GL_SMOOTH);
1256                 }
1257         }
1258         
1259         if(lt->editlatt) lt= lt->editlatt;
1260         
1261         glBegin(GL_LINES);
1262         for(w=0; w<lt->pntsw; w++) {
1263                 int wxt = (w==0 || w==lt->pntsw-1);
1264                 for(v=0; v<lt->pntsv; v++) {
1265                         int vxt = (v==0 || v==lt->pntsv-1);
1266                         for(u=0; u<lt->pntsu; u++) {
1267                                 int uxt = (u==0 || u==lt->pntsu-1);
1268
1269                                 if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1270                                         drawlattice__point(lt, dl, u, v, w-1, use_wcol);
1271                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1272                                 }
1273                                 if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1274                                         drawlattice__point(lt, dl, u, v-1, w, use_wcol);
1275                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1276                                 }
1277                                 if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1278                                         drawlattice__point(lt, dl, u-1, v, w, use_wcol);
1279                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1280                                 }
1281                         }
1282                 }
1283         }               
1284         glEnd();
1285         
1286         /* restoration for weight colors */
1287         if(use_wcol)
1288                 glShadeModel(GL_FLAT);
1289
1290         if( ((Lattice *)ob->data)->editlatt ) {
1291                 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
1292                 
1293                 lattice_draw_verts(lt, dl, 0);
1294                 lattice_draw_verts(lt, dl, 1);
1295                 
1296                 if(v3d->zbuf) glEnable(GL_DEPTH_TEST); 
1297         }
1298 }
1299
1300 /* ***************** ******************** */
1301
1302 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1303 {
1304         struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
1305         EditVert *eve = EM_get_vert_for_index(index);
1306
1307         if (eve->h==0) {
1308                 short s[2]= {IS_CLIPPED, 0};
1309
1310                 if (data->clipVerts) {
1311                         view3d_project_short_clip(data->vc.ar, co, s);
1312                 } else {
1313                         view3d_project_short_noclip(data->vc.ar, co, s);
1314                 }
1315
1316                 if (s[0]!=IS_CLIPPED)
1317                         data->func(data->userData, eve, s[0], s[1], index);
1318         }
1319 }
1320
1321 void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
1322 {
1323         struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } data;
1324         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1325         
1326         data.vc= *vc;
1327         data.func = func;
1328         data.userData = userData;
1329         data.clipVerts = clipVerts;
1330
1331         EM_init_index_arrays(vc->em, 1, 0, 0);
1332         dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
1333         EM_free_index_arrays();
1334
1335         dm->release(dm);
1336 }
1337
1338 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
1339 {
1340         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;
1341         EditEdge *eed = EM_get_edge_for_index(index);
1342         short s[2][2];
1343
1344         if (eed->h==0) {
1345                 if (data->clipVerts==1) {
1346                         view3d_project_short_clip(data->vc.ar, v0co, s[0]);
1347                         view3d_project_short_clip(data->vc.ar, v1co, s[1]);
1348                 } else {
1349                         view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
1350                         view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
1351
1352                         if (data->clipVerts==2) {
1353                 if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy)) 
1354                                         if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<data->vc.ar->winx && s[1][1]<data->vc.ar->winy)) 
1355                                                 return;
1356                         }
1357                 }
1358
1359                 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
1360         }
1361 }
1362
1363 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)
1364 {
1365         struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } data;
1366         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1367
1368         data.vc= *vc;
1369         data.func = func;
1370         data.userData = userData;
1371         data.clipVerts = clipVerts;
1372
1373         EM_init_index_arrays(vc->em, 0, 1, 0);
1374         dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
1375         EM_free_index_arrays();
1376
1377         dm->release(dm);
1378 }
1379
1380 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *no)
1381 {
1382         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } *data = userData;
1383         EditFace *efa = EM_get_face_for_index(index);
1384         short s[2];
1385
1386         if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
1387                 view3d_project_short_clip(data->vc.ar, cent, s);
1388
1389                 data->func(data->userData, efa, s[0], s[1], index);
1390         }
1391 }
1392
1393 void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
1394 {
1395         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } data;
1396         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1397
1398         data.vc= *vc;
1399         data.func = func;
1400         data.userData = userData;
1401
1402         EM_init_index_arrays(vc->em, 0, 0, 1);
1403         dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
1404         EM_free_index_arrays();
1405
1406         dm->release(dm);
1407 }
1408
1409 void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
1410 {
1411         Curve *cu= vc->obedit->data;
1412         short s[2] = {IS_CLIPPED, 0};
1413         Nurb *nu;
1414         int i;
1415
1416         for (nu= cu->editnurb->first; nu; nu=nu->next) {
1417                 if(nu->type == CU_BEZIER) {
1418                         for (i=0; i<nu->pntsu; i++) {
1419                                 BezTriple *bezt = &nu->bezt[i];
1420
1421                                 if(bezt->hide==0) {
1422                                         
1423                                         if(cu->drawflag & CU_HIDE_HANDLES) {
1424                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s);
1425                                                 if (s[0] != IS_CLIPPED)
1426                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1427                                         } else {
1428                                                 view3d_project_short_clip(vc->ar, bezt->vec[0], s);
1429                                                 if (s[0] != IS_CLIPPED)
1430                                                         func(userData, nu, NULL, bezt, 0, s[0], s[1]);
1431                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s);
1432                                                 if (s[0] != IS_CLIPPED)
1433                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1434                                                 view3d_project_short_clip(vc->ar, bezt->vec[2], s);
1435                                                 if (s[0] != IS_CLIPPED)
1436                                                         func(userData, nu, NULL, bezt, 2, s[0], s[1]);
1437                                         }
1438                                 }
1439                         }
1440                 }
1441                 else {
1442                         for (i=0; i<nu->pntsu*nu->pntsv; i++) {
1443                                 BPoint *bp = &nu->bp[i];
1444
1445                                 if(bp->hide==0) {
1446                                         view3d_project_short_clip(vc->ar, bp->vec, s);
1447                                         if (s[0] != IS_CLIPPED)
1448                                                 func(userData, nu, bp, NULL, -1, s[0], s[1]);
1449                                 }
1450                         }
1451                 }
1452         }
1453 }
1454
1455 /* ************** DRAW MESH ****************** */
1456
1457 /* First section is all the "simple" draw routines, 
1458  * ones that just pass some sort of primitive to GL,
1459  * with perhaps various options to control lighting,
1460  * color, etc.
1461  *
1462  * These routines should not have user interface related
1463  * logic!!!
1464  */
1465
1466 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
1467 {
1468         ToolSettings *ts= ((Scene *)userData)->toolsettings;
1469         EditFace *efa = EM_get_face_for_index(index);
1470
1471         if (efa->h==0 && efa->fgonf!=EM_FGON) {
1472                 glVertex3fv(cent);
1473                 glVertex3f(     cent[0] + no[0]*ts->normalsize,
1474                                         cent[1] + no[1]*ts->normalsize,
1475                                         cent[2] + no[2]*ts->normalsize);
1476         }
1477 }
1478 static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm) 
1479 {
1480         glBegin(GL_LINES);
1481         dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
1482         glEnd();
1483 }
1484
1485 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *no)
1486 {
1487         EditFace *efa = EM_get_face_for_index(index);
1488         int sel = *((int*) userData);
1489
1490         if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
1491                 bglVertex3fv(cent);
1492         }
1493 }
1494 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
1495 {
1496         bglBegin(GL_POINTS);
1497         dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
1498         bglEnd();
1499 }
1500
1501 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1502 {
1503         Scene *scene= (Scene *)userData;
1504         ToolSettings *ts= scene->toolsettings;
1505         EditVert *eve = EM_get_vert_for_index(index);
1506
1507         if (eve->h==0) {
1508                 glVertex3fv(co);
1509
1510                 if (no_f) {
1511                         glVertex3f(     co[0] + no_f[0]*ts->normalsize,
1512                                                 co[1] + no_f[1]*ts->normalsize,
1513                                                 co[2] + no_f[2]*ts->normalsize);
1514                 } else {
1515                         glVertex3f(     co[0] + no_s[0]*ts->normalsize/32767.0f,
1516                                                 co[1] + no_s[1]*ts->normalsize/32767.0f,
1517                                                 co[2] + no_s[2]*ts->normalsize/32767.0f);
1518                 }
1519         }
1520 }
1521 static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm) 
1522 {
1523         glBegin(GL_LINES);
1524         dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
1525         glEnd();
1526 }
1527
1528         /* Draw verts with color set based on selection */
1529 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1530 {
1531         struct { int sel; EditVert *eve_act; } * data = userData;
1532         EditVert *eve = EM_get_vert_for_index(index);
1533
1534         if (eve->h==0 && (eve->f&SELECT)==data->sel) {
1535                 /* draw active larger - need to stop/start point drawing for this :/ */
1536                 if (eve==data->eve_act) {
1537                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1538                         UI_ThemeColor4(TH_EDITMESH_ACTIVE);
1539                         
1540                         bglEnd();
1541                         
1542                         glPointSize(size);
1543                         bglBegin(GL_POINTS);
1544                         bglVertex3fv(co);
1545                         bglEnd();
1546                         
1547                         UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
1548                         glPointSize(size);
1549                         bglBegin(GL_POINTS);
1550                 } else {
1551                         bglVertex3fv(co);
1552                 }
1553         }
1554 }
1555
1556 /* disabled because it crashes combined with e.g. subsurf modifier,
1557  * the derivedmesh can't be assumed to be an EditMeshDerivedMesh,
1558  * nor should this struct be copied around, it should be defined in
1559  * a single place only to avoid them getting out of sync */
1560 #if 0
1561 /* originally defined in DerivedMesh.c */
1562 typedef struct {
1563         DerivedMesh dm;
1564
1565         EditMesh *em;
1566         float (*vertexCos)[3];
1567         float (*vertexNos)[3];
1568         float (*faceNos)[3];
1569 } EditMeshDerivedMesh;
1570 #endif
1571
1572 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
1573 {
1574         struct { int sel; EditVert *eve_act; } data;
1575         //GPUBuffer *buffer;
1576         //float *varray;
1577         data.sel = sel;
1578         data.eve_act = eve_act;
1579
1580 #if 0
1581         /* first come the unselected vertices, then the selected */
1582         buffer = GPU_buffer_legacy(dm)?0:GPU_buffer_alloc( sizeof(float)*3*dm->getNumVerts(dm)*2, 0 );
1583
1584         if( (varray = GPU_buffer_lock_stream( buffer )) && bglPointHack() == 0 ) {
1585                 EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
1586                 EditVert *eve;
1587                 int i;
1588                 int numverts = 0, numselected = 0;
1589                 int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_END };
1590                 GPU_buffer_unlock( buffer );
1591                 GPU_interleaved_setup( buffer, datatype );
1592                 varray = GPU_buffer_lock_stream( buffer );
1593
1594                 glBegin(GL_POINTS);
1595                 for (i=0,eve= emdm->em->verts.first; eve; i++,eve=eve->next) {
1596                         if (eve->h==0 && (eve->f&SELECT)==data.sel) {
1597                                 if (eve==data.eve_act) {
1598                                         if (emdm->vertexCos) {
1599                                                 VECCOPY(&varray[3*(dm->getNumVerts(dm)+numselected)],emdm->vertexCos[i]);
1600                                         }
1601                                         else {
1602                                                 VECCOPY(&varray[3*(dm->getNumVerts(dm)+numselected)],eve->co);
1603                                         }
1604                                         numselected++;
1605                                 } else {
1606                                         if (emdm->vertexCos) {
1607                                                 VECCOPY(&varray[3*numverts],emdm->vertexCos[i]);
1608                                         } else {
1609                                                 VECCOPY(&varray[3*numverts],eve->co);
1610                                         }
1611                                         numverts++;
1612                                 }
1613                         }
1614                 }
1615                 glEnd();
1616                 GPU_buffer_unlock( buffer );
1617                 glDrawArrays(GL_POINTS,0,numverts);
1618                 UI_ThemeColor4(TH_EDITMESH_ACTIVE);
1619                 glDrawArrays(GL_POINTS,dm->getNumVerts(dm),numselected);
1620                 UI_ThemeColor4(data.sel?TH_VERTEX_SELECT:TH_VERTEX);
1621                 GPU_buffer_unbind();
1622         }
1623         {
1624 #endif
1625                 bglBegin(GL_POINTS);
1626                 dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
1627                 bglEnd();
1628 #if 0
1629         }
1630         GPU_buffer_free( buffer, 0 );
1631 #endif
1632 }
1633
1634         /* Draw edges with color set based on selection */
1635 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
1636 {
1637         EditEdge *eed = EM_get_edge_for_index(index);
1638         //unsigned char **cols = userData, *col;
1639         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
1640         unsigned char *col;
1641
1642         if (eed->h==0) {
1643                 if (eed==data->eed_act) {
1644                         glColor4ubv(data->actCol);
1645                 } else {
1646                         if (eed->f&SELECT) {
1647                                 col = data->selCol;
1648                         } else {
1649                                 col = data->baseCol;
1650                         }
1651                         /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode  */
1652                         if (col[3]==0) return 0;
1653                         
1654                         glColor4ubv(col);
1655                 }
1656                 return 1;
1657         } else {
1658                 return 0;
1659         }
1660 }
1661 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act) 
1662 {
1663         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
1664         
1665         data.baseCol = baseCol;
1666         data.selCol = selCol;
1667         data.actCol = actCol;
1668         data.eed_act = eed_act;
1669         dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
1670 }
1671
1672         /* Draw edges */
1673 static int draw_dm_edges__setDrawOptions(void *userData, int index)
1674 {
1675         return EM_get_edge_for_index(index)->h==0;
1676 }
1677 static void draw_dm_edges(DerivedMesh *dm) 
1678 {
1679         dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
1680 }
1681
1682         /* Draw edges with color interpolated based on selection */
1683 static int draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
1684 {
1685         return EM_get_edge_for_index(index)->h==0;
1686 }
1687 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
1688 {
1689         EditEdge *eed = EM_get_edge_for_index(index);
1690         unsigned char **cols = userData;
1691         unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
1692         unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
1693
1694         glColor4ub(     col0[0] + (col1[0]-col0[0])*t,
1695                                 col0[1] + (col1[1]-col0[1])*t,
1696                                 col0[2] + (col1[2]-col0[2])*t,
1697                                 col0[3] + (col1[3]-col0[3])*t);
1698 }
1699
1700 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
1701 {
1702         unsigned char *cols[2] = {baseCol, selCol};
1703 #if 0
1704         int elemsize = sizeof(float)*3+sizeof(unsigned char)*4;
1705         EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh *)dm;
1706         EditMesh *em= emdm->em;
1707         unsigned char *varray;
1708         int i;
1709         GPUBuffer *buffer;
1710
1711         buffer = GPU_buffer_legacy(dm)?0:GPU_buffer_alloc( elemsize*em->totedge*2, 0 );
1712         if( (varray = GPU_buffer_lock_stream( buffer )) ) {
1713                 EditEdge *eed;
1714                 int numedges = 0;
1715                 int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_C4UB, GPU_BUFFER_INTER_END };
1716                 GPU_buffer_unlock( buffer );
1717                 GPU_interleaved_setup( buffer, datatype );
1718                 varray = GPU_buffer_lock_stream( buffer );
1719                 for (i=0,eed= em->edges.first; eed; i++,eed= eed->next) {
1720                         if(eed->h==0) {
1721                                 unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
1722                                 unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
1723
1724                                 if( emdm->vertexCos ) {
1725                                         VECCOPY(((float *)&varray[elemsize*numedges*2]),emdm->vertexCos[(int) eed->v1->tmp.l]);
1726                                 }
1727                                 else {
1728                                         VECCOPY(((float *)&varray[elemsize*numedges*2]),eed->v1->co);
1729                                 }
1730                                 QUATCOPY(&varray[elemsize*numedges*2+sizeof(float)*3],col0);
1731                                 if( emdm->vertexCos ) {
1732                                         VECCOPY(((float *)&varray[elemsize*numedges*2+elemsize]),emdm->vertexCos[(int) eed->v2->tmp.l]);
1733                                 }
1734                                 else {
1735                                         VECCOPY(((float *)&varray[elemsize*numedges*2+elemsize]),eed->v2->co);
1736                                 }
1737                                 QUATCOPY(&varray[elemsize*numedges*2+elemsize+sizeof(float)*3],col1);
1738                                 numedges++;
1739                         }
1740                 }
1741                 GPU_buffer_unlock( buffer );
1742                 glDrawArrays(GL_LINES,0,numedges*2);
1743                 GPU_buffer_unbind();
1744         }
1745         else {
1746 #endif
1747                 dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
1748 #if 0
1749         }
1750         GPU_buffer_free( buffer, 0 );
1751 #endif
1752 }
1753
1754         /* Draw only seam edges */
1755 static int draw_dm_edges_seams__setDrawOptions(void *userData, int index)
1756 {
1757         EditEdge *eed = EM_get_edge_for_index(index);
1758
1759         return (eed->h==0 && eed->seam);
1760 }
1761 static void draw_dm_edges_seams(DerivedMesh *dm)
1762 {
1763         dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
1764 }
1765
1766         /* Draw only sharp edges */
1767 static int draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
1768 {
1769         EditEdge *eed = EM_get_edge_for_index(index);
1770
1771         return (eed->h==0 && eed->sharp);
1772 }
1773 static void draw_dm_edges_sharp(DerivedMesh *dm)
1774 {
1775         dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
1776 }
1777
1778
1779         /* Draw faces with color set based on selection
1780          * return 2 for the active face so it renders with stipple enabled */
1781 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *drawSmooth_r)
1782 {
1783         struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
1784         EditFace *efa = EM_get_face_for_index(index);
1785         unsigned char *col;
1786         
1787         if (efa->h==0) {
1788                 if (efa == data->efa_act) {
1789                         glColor4ubv(data->cols[2]);
1790                         return 2; /* stipple */
1791                 } else {
1792                         col = data->cols[(efa->f&SELECT)?1:0];
1793                         if (col[3]==0) return 0;
1794                         glColor4ubv(col);
1795                         return 1;
1796                 }
1797         }
1798         return 0;
1799 }
1800
1801 /* also draws the active face */
1802 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act) 
1803 {
1804         struct { unsigned char *cols[3]; EditFace *efa_act; } data;
1805         //EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh *)dm;
1806         EditFace *efa;
1807         unsigned char *col;
1808         GPUBuffer *buffer;
1809         unsigned char *varray;
1810         unsigned char black[] = { 0, 0, 0, 0 };
1811         int i, draw=0;
1812         int elemsize = (sizeof(float)*6+sizeof(unsigned char)*4);
1813         data.cols[0] = baseCol;
1814         data.cols[1] = selCol;
1815         data.cols[2] = actCol;
1816         data.efa_act = efa_act;
1817
1818
1819         buffer = GPU_buffer_legacy(dm)?0:GPU_buffer_alloc( elemsize*dm->getNumFaces(dm)*3*2, 0 );
1820         if( dm->getVertCos == 0 && (varray = GPU_buffer_lock_stream( buffer )) ) {
1821                 int prevdraw = 0;
1822                 int numfaces = 0;
1823                 int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_N3F, GPU_BUFFER_INTER_C4UB, GPU_BUFFER_INTER_END };
1824                 GPU_buffer_unlock( buffer );
1825                 GPU_interleaved_setup( buffer, datatype );
1826                 glShadeModel(GL_SMOOTH);
1827                 varray = GPU_buffer_lock_stream( buffer );
1828                 for (i=0,efa= efa_act; efa; i++,efa= efa->next) {
1829                         int drawSmooth = (efa->flag & ME_SMOOTH);
1830                         if (efa->h==0) {
1831                                 if (efa == data.efa_act) {
1832                                         draw = 2;
1833                                 } else {
1834                                         col = data.cols[(efa->f&SELECT)?1:0];
1835                                         if (col[3]==0) draw = 0;
1836                                         else draw = 1;
1837                                 }
1838                         }
1839                         else {
1840                                 draw = 0;
1841                         }
1842                         if( prevdraw != draw && prevdraw != 0 && numfaces > 0) {
1843                                 if( prevdraw==2 ) {
1844                                         glEnable(GL_POLYGON_STIPPLE);
1845                                         glPolygonStipple(stipple_quarttone);
1846                                 }
1847                                 GPU_buffer_unlock( buffer );
1848                                 glDrawArrays(GL_TRIANGLES,0,numfaces*3);
1849                                 if( prevdraw==2 ) {
1850                                         glDisable(GL_POLYGON_STIPPLE);
1851                                 }
1852                                 varray = GPU_buffer_lock_stream( buffer );
1853                                 numfaces = 0;
1854                         }
1855
1856                         if( draw != 0 ) {
1857                                 if(!drawSmooth) {
1858                                         /*if (emdm->vertexCos) {
1859                                                 VECCOPY((float *)&varray[elemsize*3*numfaces],emdm->vertexCos[(int) efa->v1->tmp.l]);
1860                                                 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],emdm->faceNos[i]);
1861
1862                                                 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],emdm->vertexCos[(int) efa->v2->tmp.l]);
1863                                                 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],emdm->faceNos[i]);
1864
1865                                                 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],emdm->vertexCos[(int) efa->v3->tmp.l]);
1866                                                 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],emdm->faceNos[i]);
1867                                         }
1868                                         else {*/
1869                                                 VECCOPY((float *)&varray[elemsize*3*numfaces],efa->v1->co);
1870                                                 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],efa->n);
1871
1872                                                 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],efa->v2->co);
1873                                                 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],efa->n);
1874
1875                                                 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],efa->v3->co);
1876                                                 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],efa->n);
1877                                         /*}*/
1878                                         if( draw == 2 ) {
1879                                                 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[2]);
1880                                                 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[2]);
1881                                                 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[2]);
1882                                         }
1883                                         else if( draw == 1 ) {
1884                                                 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1885                                                 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1886                                                 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1887                                         }
1888                                         else {
1889                                                 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],black);
1890                                                 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],black);
1891                                                 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],black);
1892                                         }
1893
1894                                         numfaces++;
1895                                         if( efa->v4 ) {
1896                                                 /*if (emdm->vertexCos) {
1897                                                         VECCOPY((float *)&varray[elemsize*3*numfaces],emdm->vertexCos[(int) efa->v3->tmp.l]);
1898                                                         VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],emdm->faceNos[i]);
1899
1900                                                         VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],emdm->vertexCos[(int) efa->v4->tmp.l]);
1901                                                         VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],emdm->faceNos[i]);
1902
1903                                                         VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],emdm->vertexCos[(int) efa->v1->tmp.l]);
1904                                                         VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],emdm->faceNos[i]);
1905                                                 }
1906                                                 else {*/
1907                                                         VECCOPY((float *)&varray[elemsize*3*numfaces],efa->v3->co);
1908                                                         VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],efa->n);
1909
1910                                                         VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],efa->v4->co);
1911                                                         VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],efa->n);
1912
1913                                                         VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],efa->v1->co);
1914                                                         VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],efa->n);
1915                                                 /*}*/
1916
1917                                                 if( draw == 2 ) {
1918                                                         QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[2]);
1919                                                         QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[2]);
1920                                                         QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[2]);
1921                                                 }
1922                                                 else if( draw == 1 ) {
1923                                                         QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1924                                                         QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1925                                                         QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1926                                                 }
1927                                                 else {
1928                                                         QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],black);
1929                                                         QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],black);
1930                                                         QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],black);
1931                                                 }
1932
1933                                                 numfaces++;
1934                                         }
1935                                 }
1936                                 else {
1937                                         /*if (emdm->vertexCos) {
1938                                                 VECCOPY((float *)&varray[elemsize*3*numfaces],emdm->vertexCos[(int) efa->v1->tmp.l]);
1939                                                 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],emdm->vertexNos[(int) efa->v1->tmp.l]);
1940
1941                                                 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],emdm->vertexCos[(int) efa->v2->tmp.l]);
1942                                                 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],emdm->vertexNos[(int) efa->v2->tmp.l]);
1943
1944                                                 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],emdm->vertexCos[(int) efa->v3->tmp.l]);
1945                                                 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],emdm->vertexNos[(int) efa->v3->tmp.l]);
1946                                         }
1947                                         else {*/
1948                                                 VECCOPY((float *)&varray[elemsize*3*numfaces],efa->v1->co);
1949                                                 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],efa->v1->no);
1950
1951                                                 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],efa->v2->co);
1952                                                 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],efa->v2->no);
1953
1954                                                 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],efa->v3->co);
1955                                                 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],efa->v3->no);
1956                                         /*}*/
1957
1958                                         if( draw == 2 ) {
1959                                                 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[2]);
1960                                                 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[2]);
1961                                                 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[2]);
1962                                         }
1963                                         else if( draw == 1 ) {
1964                                                 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1965                                                 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1966                                                 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1967                                         }
1968                                         else {
1969                                                 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],black);
1970                                                 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],black);
1971                                                 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],black);
1972                                         }
1973
1974                                         numfaces++;
1975                                         if( efa->v4 ) {
1976                                                 /*if (emdm->vertexCos) {
1977                                                         VECCOPY((float *)&varray[elemsize*3*numfaces],emdm->vertexCos[(int) efa->v3->tmp.l]);
1978                                                         VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],emdm->vertexNos[(int) efa->v1->tmp.l]);
1979
1980                                                         VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],emdm->vertexCos[(int) efa->v4->tmp.l]);
1981                                                         VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],emdm->vertexNos[(int) efa->v2->tmp.l]);
1982
1983                                                         VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],emdm->vertexCos[(int) efa->v1->tmp.l]);
1984                                                         VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],emdm->vertexNos[(int) efa->v3->tmp.l]);
1985                                                 }
1986                                                 else {*/
1987                                                         VECCOPY((float *)&varray[elemsize*3*numfaces],efa->v3->co);
1988                                                         VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],efa->v3->no);
1989
1990                                                         VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],efa->v4->co);
1991                                                         VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],efa->v4->no);
1992
1993                                                         VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],efa->v1->co);
1994                                                         VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],efa->v1->no);
1995                                                 /*}*/
1996
1997                                                 if( draw == 2 ) {
1998                                                         QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[2]);
1999                                                         QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[2]);
2000                                                         QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[2]);
2001                                                 }
2002                                                 else if( draw == 1 ) {
2003                                                         QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
2004                                                         QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
2005                                                         QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
2006                                                 }
2007                                                 else {
2008                                                         QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],black);
2009                                                         QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],black);
2010                                                         QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],black);
2011                                                 }
2012
2013                                                 numfaces++;
2014                                         }
2015                                 }
2016                         }
2017                         prevdraw = draw;
2018                 }
2019                 GPU_buffer_unlock( buffer );
2020                 if( prevdraw != 0 && numfaces > 0) {
2021                         if( prevdraw==2 ) {
2022                                 glEnable(GL_POLYGON_STIPPLE);
2023                                 glPolygonStipple(stipple_quarttone);
2024                         }
2025                         glDrawArrays(GL_TRIANGLES,0,numfaces*3);
2026                         if( prevdraw==2 ) {
2027                                 glDisable(GL_POLYGON_STIPPLE);
2028                         }
2029                 }
2030                 GPU_buffer_unbind();
2031         } else {
2032                 dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0);
2033         }
2034         GPU_buffer_free( buffer, 0 );
2035 }
2036
2037 static int draw_dm_creases__setDrawOptions(void *userData, int index)
2038 {
2039         EditEdge *eed = EM_get_edge_for_index(index);
2040
2041         if (eed->h==0 && eed->crease!=0.0) {
2042                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->crease);
2043                 return 1;
2044         } else {
2045                 return 0;
2046         }
2047 }
2048 static void draw_dm_creases(DerivedMesh *dm)
2049 {
2050         glLineWidth(3.0);
2051         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
2052         glLineWidth(1.0);
2053 }
2054
2055 static int draw_dm_bweights__setDrawOptions(void *userData, int index)
2056 {
2057         EditEdge *eed = EM_get_edge_for_index(index);
2058
2059         if (eed->h==0 && eed->bweight!=0.0) {
2060                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
2061                 return 1;
2062         } else {
2063                 return 0;
2064         }
2065 }
2066 static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
2067 {
2068         EditVert *eve = EM_get_vert_for_index(index);
2069
2070         if (eve->h==0 && eve->bweight!=0.0) {
2071                 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
2072                 bglVertex3fv(co);
2073         }
2074 }
2075 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
2076 {
2077         ToolSettings *ts= scene->toolsettings;
2078
2079         if (ts->selectmode & SCE_SELECT_VERTEX) {
2080                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2081                 bglBegin(GL_POINTS);
2082                 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
2083                 bglEnd();
2084         }
2085         else {
2086                 glLineWidth(3.0);
2087                 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
2088                 glLineWidth(1.0);
2089         }
2090 }
2091
2092 /* Second section of routines: Combine first sets to form fancy
2093  * drawing routines (for example rendering twice to get overlays).
2094  *
2095  * Also includes routines that are basic drawing but are too
2096  * specialized to be split out (like drawing creases or measurements).
2097  */
2098
2099 /* EditMesh drawing routines*/
2100
2101 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, EditMesh *em, DerivedMesh *cageDM, EditVert *eve_act)
2102 {
2103         ToolSettings *ts= scene->toolsettings;
2104         int sel;
2105
2106         if(v3d->zbuf) glDepthMask(0);           // disable write in zbuffer, zbuf select
2107
2108         for (sel=0; sel<2; sel++) {
2109                 char col[4], fcol[4];
2110                 int pass;
2111
2112                 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
2113                 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
2114
2115                 for (pass=0; pass<2; pass++) {
2116                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2117                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2118
2119                         if (pass==0) {
2120                                 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
2121                                         glDisable(GL_DEPTH_TEST);
2122                                                 
2123                                         glEnable(GL_BLEND);
2124                                 } else {
2125                                         continue;
2126                                 }
2127
2128                                 size = (size>2.1?size/2.0:size);
2129                                 fsize = (fsize>2.1?fsize/2.0:fsize);
2130                                 col[3] = fcol[3] = 100;
2131                         } else {
2132                                 col[3] = fcol[3] = 255;
2133                         }
2134                                 
2135                         if(ts->selectmode & SCE_SELECT_VERTEX) {
2136                                 glPointSize(size);
2137                                 glColor4ubv((GLubyte *)col);
2138                                 draw_dm_verts(cageDM, sel, eve_act);
2139                         }
2140                         
2141                         if( CHECK_OB_DRAWFACEDOT(scene, v3d, obedit->dt) ) {
2142                                 glPointSize(fsize);
2143                                 glColor4ubv((GLubyte *)fcol);
2144                                 draw_dm_face_centers(cageDM, sel);
2145                         }
2146                         
2147                         if (pass==0) {
2148                                 glDisable(GL_BLEND);
2149                                 glEnable(GL_DEPTH_TEST);
2150                         }
2151                 }
2152         }
2153
2154         if(v3d->zbuf) glDepthMask(1);
2155         glPointSize(1.0);
2156 }
2157
2158 static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
2159 {
2160         ToolSettings *ts= scene->toolsettings;
2161         int pass;
2162         unsigned char wireCol[4], selCol[4], actCol[4];
2163
2164         /* since this function does transparant... */
2165         UI_GetThemeColor4ubv(TH_EDGE_SELECT, (char *)selCol);
2166         UI_GetThemeColor4ubv(TH_WIRE, (char *)wireCol);
2167         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)actCol);
2168         
2169         /* when sel only is used, dont render wire, only selected, this is used for
2170          * textured draw mode when the 'edges' option is disabled */
2171         if (sel_only)
2172                 wireCol[3] = 0;
2173
2174         for (pass=0; pass<2; pass++) {
2175                         /* show wires in transparant when no zbuf clipping for select */
2176                 if (pass==0) {
2177                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
2178                                 glEnable(GL_BLEND);
2179                                 glDisable(GL_DEPTH_TEST);
2180                                 selCol[3] = 85;
2181                                 if (!sel_only) wireCol[3] = 85;
2182                         } else {
2183                                 continue;
2184                         }
2185                 } else {
2186                         selCol[3] = 255;
2187                         if (!sel_only) wireCol[3] = 255;
2188                 }
2189
2190                 if(ts->selectmode == SCE_SELECT_FACE) {
2191                         draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2192                 }       
2193                 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {        
2194                         if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2195                                 glShadeModel(GL_SMOOTH);
2196                                 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
2197                                 glShadeModel(GL_FLAT);
2198                         } else {
2199                                 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2200                         }
2201                 }
2202                 else {
2203                         if (!sel_only) {
2204                                 glColor4ubv(wireCol);
2205                                 draw_dm_edges(cageDM);
2206                         }
2207                 }
2208
2209                 if (pass==0) {
2210                         glDisable(GL_BLEND);
2211                         glEnable(GL_DEPTH_TEST);
2212                 }
2213         }
2214 }       
2215
2216 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, UnitSettings *unit)
2217 {
2218         Mesh *me= ob->data;
2219         EditEdge *eed;
2220         EditFace *efa;
2221         float v1[3], v2[3], v3[3], v4[3], x, y, z;
2222         float fvec[3];
2223         char val[32]; /* Stores the measurement display text here */
2224         char conv_float[5]; /* Use a float conversion matching the grid size */
2225         float area, col[3]; /* area of the face,  color of the text to draw */
2226         float grid= unit->system ? unit->scale_length : v3d->grid;
2227         int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
2228         if(G.f & (G_RENDER_OGL|G_RENDER_SHADOW))
2229                 return;
2230
2231         /* make the precission of the pronted value proportionate to the gridsize */
2232
2233         if (grid < 0.01f)
2234                 strcpy(conv_float, "%.6f");
2235         else if (grid < 0.1f)
2236                 strcpy(conv_float, "%.5f");
2237         else if (grid < 1.0f)
2238                 strcpy(conv_float, "%.4f");
2239         else if (grid < 10.0f)
2240                 strcpy(conv_float, "%.3f");
2241         else
2242                 strcpy(conv_float, "%.2f");
2243         
2244         
2245         if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
2246                 glDisable(GL_DEPTH_TEST);
2247
2248         if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
2249         
2250         if(me->drawflag & ME_DRAW_EDGELEN) {
2251                 UI_GetThemeColor3fv(TH_TEXT, col);
2252                 /* make color a bit more red */
2253                 if(col[0]> 0.5f) {col[1]*=0.7f; col[2]*= 0.7f;}
2254                 else col[0]= col[0]*0.7f + 0.3f;
2255                 glColor3fv(col);
2256                 
2257                 for(eed= em->edges.first; eed; eed= eed->next) {
2258                         /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
2259                         if((eed->h != EM_FGON) && ((eed->f & SELECT) || (G.moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
2260                                 VECCOPY(v1, eed->v1->co);
2261                                 VECCOPY(v2, eed->v2->co);
2262                                 
2263                                 x= 0.5f*(v1[0]+v2[0]);
2264                                 y= 0.5f*(v1[1]+v2[1]);
2265                                 z= 0.5f*(v1[2]+v2[2]);
2266                                 
2267                                 if(v3d->flag & V3D_GLOBAL_STATS) {
2268                                         Mat4MulVecfl(ob->obmat, v1);
2269                                         Mat4MulVecfl(ob->obmat, v2);
2270                                 }
2271                                 if(unit->system)
2272                                         bUnit_AsString(val, sizeof(val), VecLenf(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
2273                                 else
2274                                         sprintf(val, conv_float, VecLenf(v1, v2));
2275                                 
2276                                 view3d_cached_text_draw_add(x, y, z, val, 0);
2277                         }
2278                 }
2279         }
2280
2281         if(me->drawflag & ME_DRAW_FACEAREA) {
2282 // XXX          extern int faceselectedOR(EditFace *efa, int flag);             // editmesh.h shouldn't be in this file... ok for now?
2283                 
2284                 UI_GetThemeColor3fv(TH_TEXT, col);
2285                 /* make color a bit more green */
2286                 if(col[1]> 0.5f) {col[0]*=0.7f; col[2]*= 0.7f;}
2287                 else col[1]= col[1]*0.7f + 0.3f;
2288                 glColor3fv(col);
2289                 
2290                 for(efa= em->faces.first; efa; efa= efa->next) {
2291                         if((efa->f & SELECT)) { // XXX || (G.moving && faceselectedOR(efa, SELECT)) ) {
2292                                 VECCOPY(v1, efa->v1->co);
2293                                 VECCOPY(v2, efa->v2->co);
2294                                 VECCOPY(v3, efa->v3->co);
2295                                 if (efa->v4) {
2296                                         VECCOPY(v4, efa->v4->co);
2297                                 }
2298                                 if(v3d->flag & V3D_GLOBAL_STATS) {
2299                                         Mat4MulVecfl(ob->obmat, v1);
2300                                         Mat4MulVecfl(ob->obmat, v2);
2301                                         Mat4MulVecfl(ob->obmat, v3);
2302                                         if (efa->v4) Mat4MulVecfl(ob->obmat, v4);
2303                                 }
2304                                 
2305                                 if (efa->v4)
2306                                         area=  AreaQ3Dfl(v1, v2, v3, v4);
2307                                 else
2308                                         area = AreaT3Dfl(v1, v2, v3);
2309
2310                                 if(unit->system)
2311                                         bUnit_AsString(val, sizeof(val), area*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); // XXX should be B_UNIT_AREA
2312                                 else
2313                                         sprintf(val, conv_float, area);
2314
2315                                 view3d_cached_text_draw_add(efa->cent[0], efa->cent[1], efa->cent[2], val, 0);
2316                         }
2317                 }
2318         }
2319
2320         if(me->drawflag & ME_DRAW_EDGEANG) {
2321                 EditEdge *e1, *e2, *e3, *e4;
2322                 
2323                 UI_GetThemeColor3fv(TH_TEXT, col);
2324                 /* make color a bit more blue */
2325                 if(col[2]> 0.5f) {col[0]*=0.7f; col[1]*= 0.7f;}
2326                 else col[2]= col[2]*0.7f + 0.3f;
2327                 glColor3fv(col);
2328                 
2329                 for(efa= em->faces.first; efa; efa= efa->next) {
2330                         VECCOPY(v1, efa->v1->co);
2331                         VECCOPY(v2, efa->v2->co);
2332                         VECCOPY(v3, efa->v3->co);
2333                         if(efa->v4) {
2334                                 VECCOPY(v4, efa->v4->co); 
2335                         }
2336                         else {
2337                                 VECCOPY(v4, v3);
2338                         }
2339                         if(v3d->flag & V3D_GLOBAL_STATS) {
2340                                 Mat4MulVecfl(ob->obmat, v1);
2341                                 Mat4MulVecfl(ob->obmat, v2);
2342                                 Mat4MulVecfl(ob->obmat, v3);
2343                                 Mat4MulVecfl(ob->obmat, v4);
2344                         }
2345                         
2346                         e1= efa->e1;
2347                         e2= efa->e2;
2348                         e3= efa->e3;
2349                         if(efa->e4) e4= efa->e4; else e4= e3;
2350                         
2351                         /* Calculate the angles */
2352                                 
2353                         if( (e4->f & e1->f & SELECT) || (G.moving && (efa->v1->f & SELECT)) ) {
2354                                 /* Vec 1 */
2355                                 sprintf(val,"%.3f", RAD2DEG(VecAngle3(v4, v1, v2)));
2356                                 VecLerpf(fvec, efa->cent, efa->v1->co, 0.8f);
2357                                 view3d_cached_text_draw_add(efa->cent[0], efa->cent[1], efa->cent[2], val, 0);
2358                         }
2359                         if( (e1->f & e2->f & SELECT) || (G.moving && (efa->v2->f & SELECT)) ) {
2360                                 /* Vec 2 */
2361                                 sprintf(val,"%.3f", RAD2DEG(VecAngle3(v1, v2, v3)));
2362                                 VecLerpf(fvec, efa->cent, efa->v2->co, 0.8f);
2363                                 view3d_cached_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2364                         }
2365                         if( (e2->f & e3->f & SELECT) || (G.moving && (efa->v3->f & SELECT)) ) {
2366                                 /* Vec 3 */
2367                                 if(efa->v4) 
2368                                         sprintf(val,"%.3f", RAD2DEG(VecAngle3(v2, v3, v4)));
2369                                 else
2370                                         sprintf(val,"%.3f", RAD2DEG(VecAngle3(v2, v3, v1)));
2371                                 VecLerpf(fvec, efa->cent, efa->v3->co, 0.8f);
2372                                 view3d_cached_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2373                         }
2374                                 /* Vec 4 */
2375                         if(efa->v4) {
2376                                 if( (e3->f & e4->f & SELECT) || (G.moving && (efa->v4->f & SELECT)) ) {
2377                                         sprintf(val,"%.3f", RAD2DEG(VecAngle3(v3, v4, v1)));
2378                                         VecLerpf(fvec, efa->cent, efa->v4->co, 0.8f);
2379                                         view3d_cached_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2380                                 }
2381                         }
2382                 }
2383         }    
2384         
2385         if(v3d->zbuf) {
2386                 glEnable(GL_DEPTH_TEST);
2387                 bglPolygonOffset(rv3d->dist, 0.0f);
2388         }
2389 }
2390
2391 static int draw_em_fancy__setFaceOpts(void *userData, int index, int *drawSmooth_r)
2392 {
2393         EditFace *efa = EM_get_face_for_index(index);
2394
2395         if (efa->h==0) {
2396                 GPU_enable_material(efa->mat_nr+1, NULL);
2397                 return 1;
2398         }
2399         else
2400                 return 0;
2401 }
2402
2403 static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
2404 {
2405         EditFace *efa = EM_get_face_for_index(index);
2406
2407         return (efa->h==0);
2408 }
2409
2410 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2411 {
2412         Mesh *me = ob->data;
2413         EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2414         EditEdge *eed_act = NULL;
2415         EditVert *eve_act = NULL;
2416         
2417         if (em->selected.last) {
2418                 EditSelection *ese = em->selected.last;
2419                 /* face is handeled above */
2420                 /*if (ese->type == EDITFACE ) {
2421                         efa_act = (EditFace *)ese->data;
2422                 } else */ if ( ese->type == EDITEDGE ) {
2423                         eed_act = (EditEdge *)ese->data;
2424                 } else if ( ese->type == EDITVERT ) {
2425                         eve_act = (EditVert *)ese->data;
2426                 }
2427         }
2428         
2429         EM_init_index_arrays(em, 1, 1, 1);
2430
2431         if(dt>OB_WIRE) {
2432                 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2433                         if(draw_glsl_material(scene, ob, v3d, dt)) {
2434                                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2435
2436                                 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2437                                         draw_em_fancy__setGLSLFaceOpts, NULL);
2438                                 GPU_disable_material();
2439
2440                                 glFrontFace(GL_CCW);
2441                         }
2442                         else {
2443                                 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2444                         }
2445                 }
2446                 else {
2447                         /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
2448                         GPUBuffer *buffer = GPU_buffer_legacy(em->derivedFinal)?0:GPU_buffer_alloc( sizeof(float)*6*em->totface*3*2, 0 );
2449                         float *varray;
2450                         EditFace *efa;
2451                         int i, curmat = 0, draw = 0;
2452
2453                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2454
2455                         glEnable(GL_LIGHTING);
2456                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2457
2458                         if( finalDM->getVertCos == 0 && (varray = GPU_buffer_lock_stream( buffer )) ) {
2459                                 int prevdraw = 0, prevmat = 0;
2460                                 int numfaces = 0;
2461                                 int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_N3F, GPU_BUFFER_INTER_END };
2462                                 GPU_buffer_unlock( buffer );
2463                                 GPU_interleaved_setup( buffer, datatype );
2464                                 glShadeModel(GL_SMOOTH);
2465                                 varray = GPU_buffer_lock_stream( buffer );
2466                                 for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) {
2467                                         int drawSmooth = (efa->flag & ME_SMOOTH);
2468                                         if( efa->h == 0 ) {
2469                                                 curmat = efa->mat_nr+1;
2470                                                 draw = 1;
2471                                         } 
2472                                         else {
2473                                                 draw = 0;
2474                                         }
2475                                         if( ((prevdraw != draw) || (curmat != prevmat)) && prevdraw != 0 && numfaces > 0) {
2476                                                 if( prevdraw==2 ) {
2477                                                         glEnable(GL_POLYGON_STIPPLE);
2478                                                         glPolygonStipple(stipple_quarttone);
2479                                                 }
2480                                                 GPU_buffer_unlock( buffer );
2481                                                 GPU_enable_material(prevmat, NULL);
2482                                                 glDrawArrays(GL_TRIANGLES,0,numfaces*3);
2483                                                 if( prevdraw==2 ) {
2484                                                         glDisable(GL_POLYGON_STIPPLE);
2485                                                 }
2486                                                 varray = GPU_buffer_lock_stream( buffer );
2487                                                 numfaces = 0;
2488                                         }
2489                                         if( draw != 0 ) {
2490                                                 if(!drawSmooth) {
2491                                                         VECCOPY(&varray[numfaces*18],efa->v1->co);
2492                                                         VECCOPY(&varray[numfaces*18+3],efa->n);
2493
2494                                                         VECCOPY(&varray[numfaces*18+6],efa->v2->co);
2495                                                         VECCOPY(&varray[numfaces*18+9],efa->n);
2496
2497                                                         VECCOPY(&varray[numfaces*18+12],efa->v3->co);
2498                                                         VECCOPY(&varray[numfaces*18+15],efa->n);
2499                                                         numfaces++;
2500                                                         if( efa->v4 ) {
2501                                                                 VECCOPY(&varray[numfaces*18],efa->v3->co);
2502                                                                 VECCOPY(&varray[numfaces*18+3],efa->n);
2503
2504                                                                 VECCOPY(&varray[numfaces*18+6],efa->v4->co);
2505                                                                 VECCOPY(&varray[numfaces*18+9],efa->n);
2506
2507                                                                 VECCOPY(&varray[numfaces*18+12],efa->v1->co);
2508                                                                 VECCOPY(&varray[numfaces*18+15],efa->n);
2509                                                                 numfaces++;
2510                                                         }
2511                                                 }
2512                                                 else {
2513                                                         VECCOPY(&varray[numfaces*18],efa->v1->co);
2514                                                         VECCOPY(&varray[numfaces*18+3],efa->v1->no);
2515
2516                                                         VECCOPY(&varray[numfaces*18+6],efa->v2->co);
2517                                                         VECCOPY(&varray[numfaces*18+9],efa->v2->no);
2518
2519                                                         VECCOPY(&varray[numfaces*18+12],efa->v3->co);
2520                                                         VECCOPY(&varray[numfaces*18+15],efa->v3->no);
2521                                                         numfaces++;
2522                                                         if( efa->v4 ) {
2523                                                                 VECCOPY(&varray[numfaces*18],efa->v3->co);
2524                                                                 VECCOPY(&varray[numfaces*18+3],efa->v3->no);
2525
2526                                                                 VECCOPY(&varray[numfaces*18+6],efa->v4->co);
2527                                                                 VECCOPY(&varray[numfaces*18+9],efa->v4->no);
2528
2529                                                                 VECCOPY(&varray[numfaces*18+12],efa->v1->co);
2530                                                                 VECCOPY(&varray[numfaces*18+15],efa->v1->no);
2531                                                                 numfaces++;
2532                                                         }
2533                                                 }
2534                                         }
2535                                         prevdraw = draw;
2536                                         prevmat = curmat;
2537                                 }
2538                                 GPU_buffer_unlock( buffer );
2539                                 if( prevdraw != 0 && numfaces > 0) {
2540                                         if( prevdraw==2 ) {
2541                                                 glEnable(GL_POLYGON_STIPPLE);
2542                                                 glPolygonStipple(stipple_quarttone);
2543                                         }
2544                                         GPU_enable_material(prevmat, NULL);
2545                                         glDrawArrays(GL_TRIANGLES,0,numfaces*3);
2546                                         if( prevdraw==2 ) {
2547                                                 glDisable(GL_POLYGON_STIPPLE);
2548                                         }
2549                                 }
2550                                 GPU_buffer_unbind();
2551                         }
2552                         else {
2553                                 finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, 0, 0);
2554                         }
2555                         GPU_buffer_free(buffer,0);
2556
2557                         glFrontFace(GL_CCW);
2558                         glDisable(GL_LIGHTING);
2559                 }
2560                         
2561                 // Setup for drawing wire over, disable zbuffer
2562                 // write to show selected edge wires better
2563                 UI_ThemeColor(TH_WIRE);
2564
2565                 bglPolygonOffset(rv3d->dist, 1.0);
2566                 glDepthMask(0);
2567         } 
2568         else {
2569                 if (cageDM!=finalDM) {
2570                         UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2571                         finalDM->drawEdges(finalDM, 1);
2572                 }
2573         }
2574         
2575         if((me->drawflag & (ME_DRAWFACES)) || paint_facesel_test(ob)) { /* transp faces */
2576                 unsigned char col1[4], col2[4], col3[4];
2577                         
2578                 UI_GetThemeColor4ubv(TH_FACE, (char *)col1);
2579                 UI_GetThemeColor4ubv(TH_FACE_SELECT, (char *)col2);
2580                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2581                 
2582                 glEnable(GL_BLEND);
2583                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2584                 
2585                 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2586                 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2587                         col1[3] = 0;
2588                 
2589                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2590
2591                 glDisable(GL_BLEND);
2592                 glDepthMask(1);         // restore write in zbuffer
2593         } else if (efa_act) {
2594                 /* even if draw faces is off it would be nice to draw the stipple face
2595                  * Make all other faces zero alpha except for the active
2596                  * */
2597                 unsigned char col1[4], col2[4], col3[4];
2598                 col1[3] = col2[3] = 0; /* dont draw */
2599                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2600                 
2601                 glEnable(GL_BLEND);
2602                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2603                 
2604                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2605
2606                 glDisable(GL_BLEND);
2607                 glDepthMask(1);         // restore write in zbuffer
2608                 
2609         }
2610
2611         /* here starts all fancy draw-extra over */
2612         if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2613                 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2614                 
2615                 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2616                 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
2617                 
2618         } else {
2619                 if(me->drawflag & ME_DRAWSEAMS) {
2620                         UI_ThemeColor(TH_EDGE_SEAM);
2621                         glLineWidth(2);
2622         
2623                         draw_dm_edges_seams(cageDM);
2624         
2625                         glColor3ub(0,0,0);
2626                         glLineWidth(1);
2627                 }
2628                 
2629                 if(me->drawflag & ME_DRAWSHARP) {
2630                         UI_ThemeColor(TH_EDGE_SHARP);
2631                         glLineWidth(2);
2632         
2633                         draw_dm_edges_sharp(cageDM);
2634         
2635                         glColor3ub(0,0,0);
2636                         glLineWidth(1);
2637                 }
2638         
2639                 if(me->drawflag & ME_DRAWCREASES) {
2640                         draw_dm_creases(cageDM);
2641                 }
2642                 if(me->drawflag & ME_DRAWBWEIGHTS) {
2643                         draw_dm_bweights(scene, cageDM);
2644                 }
2645         
2646                 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
2647         }
2648         if(em) {
2649 // XXX          retopo_matrix_update(v3d);
2650
2651                 draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act);
2652
2653                 if(me->drawflag & ME_DRAWNORMALS) {
2654                         UI_ThemeColor(TH_NORMAL);
2655                         draw_dm_face_normals(scene, cageDM);
2656                 }
2657                 if(me->drawflag & ME_DRAW_VNORMALS) {
2658                         UI_ThemeColor(TH_NORMAL);
2659                         draw_dm_vert_normals(scene, cageDM);
2660                 }
2661
2662                 if(me->drawflag & (ME_DRAW_EDGELEN|ME_DRAW_FACEAREA|ME_DRAW_EDGEANG))
2663                         draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
2664         }
2665
2666         if(dt>OB_WIRE) {
2667                 glDepthMask(1);
2668                 bglPolygonOffset(rv3d->dist, 0.0);
2669                 GPU_disable_material();
2670         }
2671
2672         EM_free_index_arrays();
2673 }
2674
2675 /* Mesh drawing routines */
2676
2677 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2678 {
2679         
2680         if(v3d->transp==0) {    // not when we draw the transparent pass
2681                 glLineWidth(2.0);
2682                 glDepthMask(0);
2683                 
2684                 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2685                    drawFacesSolid() doesn't draw the transparent faces */
2686                 if(ob->dtx & OB_DRAWTRANSP) {
2687                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2688                         dm->drawFacesSolid(dm, GPU_enable_material);
2689                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2690                         GPU_disable_material();
2691                 }
2692                 else {
2693                         dm->drawEdges(dm, 0);
2694                 }
2695                                         
2696                 glLineWidth(1.0);
2697                 glDepthMask(1);
2698         }
2699 }
2700
2701 static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
2702 {
2703         *drawSmooth_r = 1;
2704         return 1;
2705 }
2706
2707 static void draw_mesh_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2708 {
2709         Object *ob= base->object;
2710         Mesh *me = ob->data;
2711         Material *ma= give_current_material(ob, 1);
2712         int hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
2713         int draw_wire = 0;
2714         int totvert, totedge, totface;
2715         DispList *dl;
2716         DerivedMesh *dm= mesh_get_derived_final(scene, ob, v3d->customdata_mask);
2717
2718         if(!dm)
2719                 return;
2720         
2721         if (ob->dtx&OB_DRAWWIRE) {
2722                 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
2723         }
2724         
2725         totvert = dm->getNumVerts(dm);
2726         totedge = dm->getNumEdges(dm);
2727         totface = dm->getNumFaces(dm);
2728         
2729         /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2730         if(dt!=OB_SHADED)
2731                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2732
2733                 // Unwanted combination.
2734         if (ob==OBACT && paint_facesel_test(ob)) draw_wire = 0;
2735
2736         if(dt==OB_BOUNDBOX) {
2737                 draw_bounding_volume(scene, ob);
2738         }
2739         else if(hasHaloMat || (totface==0 && totedge==0)) {
2740                 glPointSize(1.5);
2741                 dm->drawVerts(dm);
2742                 glPointSize(1.0);
2743         }
2744         else if(dt==OB_WIRE || totface==0) {
2745                 draw_wire = 1; /* draw wire only, no depth buffer stuff  */
2746         }
2747         else if(        (ob==OBACT && (ob->mode & OB_MODE_TEXTURE_PAINT || paint_facesel_test(ob))) ||
2748                                 CHECK_OB_DRAWTEXTURE(v3d, dt))
2749         {
2750                 int faceselect= (ob==OBACT && paint_facesel_test(ob));
2751
2752                 if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !(G.f&G_PICKSEL || paint_facesel_test(ob)) && !draw_wire) {
2753                         draw_mesh_object_outline(v3d, ob, dm);
2754                 }
2755
2756                 if(draw_glsl_material(scene, ob, v3d, dt)) {
2757                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2758
2759                         dm->drawFacesGLSL(dm, GPU_enable_material);
2760 //                      if(get_ob_property(ob, "Text"))
2761 // XXX                          draw_mesh_text(ob, 1);
2762                         GPU_disable_material();
2763
2764                         glFrontFace(GL_CCW);
2765                 }
2766                 else {
2767                         draw_mesh_textured(scene, v3d, rv3d, ob, dm, faceselect);
2768                 }
2769
2770                 if(!faceselect) {
2771                         if(base->flag & SELECT)
2772                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2773                         else
2774                                 UI_ThemeColor(TH_WIRE);
2775
2776                         dm->drawLooseEdges(dm);
2777                 }
2778         }
2779         else if(dt==OB_SOLID) {
2780                 if((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire)
2781                         draw_mesh_object_outline(v3d, ob, dm);
2782
2783                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
2784
2785                 glEnable(GL_LIGHTING);
2786                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2787
2788                 dm->drawFacesSolid(dm, GPU_enable_material);
2789                 GPU_disable_material();
2790
2791                 glFrontFace(GL_CCW);
2792                 glDisable(GL_LIGHTING);
2793
2794                 if(base->flag & SELECT) {
2795                         UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2796                 } else {
2797                         UI_ThemeColor(TH_WIRE);
2798                 }
2799                 dm->drawLooseEdges(dm);
2800         }
2801         else if(dt==OB_SHADED) {
2802                 int do_draw= 1; /* to resolve all G.f settings below... */
2803                 
2804                 if(ob==OBACT) {
2805                         do_draw= 0;
2806                         if(ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2807                                 /* enforce default material settings */
2808                                 GPU_enable_material(0, NULL);
2809                                 
2810                                 /* but set default spec */
2811                                 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
2812                                 glEnable(GL_COLOR_MATERIAL);    /* according manpages needed */
2813                                 glColor3ub(120, 120, 120);
2814                                 glDisable(GL_COLOR_MATERIAL);
2815                                 /* diffuse */
2816                                 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2817                                 glEnable(GL_LIGHTING);
2818                                 glEnable(GL_COLOR_MATERIAL);
2819
2820                                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1);
2821                                 glDisable(GL_COLOR_MATERIAL);
2822                                 glDisable(GL_LIGHTING);
2823
2824                                 GPU_disable_material();
2825                         }
2826                         else if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_TEXTURE_PAINT)) {
2827                                 if(me->mcol)
2828                                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1);
2829                                 else {
2830                                         glColor3f(1.0f, 1.0f, 1.0f);
2831                                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0);
2832                                 }
2833                         }
2834                         else do_draw= 1;
2835                 }
2836                 if(do_draw) {
2837                         dl = ob->disp.first;
2838                         if (!dl || !dl->col1) {
2839                                 /* release and reload derivedmesh because it might be freed in
2840                                    shadeDispList due to a different datamask */
2841                                 dm->release(dm);
2842                                 shadeDispList(scene, base);
2843                                 dl = find_displist(&ob->disp, DL_VERTCOL);
2844                                 dm= mesh_get_derived_final(scene, ob, v3d->customdata_mask);
2845                         }
2846
2847                         if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) {
2848                                 draw_mesh_object_outline(v3d, ob, dm);
2849                         }
2850
2851                                 /* False for dupliframe objects */
2852                         if (dl) {
2853                                 unsigned int *obCol1 = dl->col1;
2854                                 unsigned int *obCol2 = dl->col2;
2855
2856                                 dm->drawFacesColored(dm, me->flag&ME_TWOSIDED, (unsigned char*) obCol1, (unsigned char*) obCol2);
2857                         }
2858
2859                         if(base->flag & SELECT) {
2860                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2861                         } else {
2862                                 UI_ThemeColor(TH_WIRE);
2863                         }
2864                         dm->drawLooseEdges(dm);
2865                 }
2866         }
2867         
2868         /* set default draw color back for wire or for draw-extra later on */
2869         if (dt!=OB_WIRE) {
2870                 if(base->flag & SELECT) {
2871                         if(ob==OBACT && ob->flag & OB_FROMGROUP) 
2872                                 UI_ThemeColor(TH_GROUP_ACTIVE);
2873                         else if(ob->flag & OB_FROMGROUP) 
2874                                 UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
2875                         else if(flag!=DRAW_CONSTCOLOR)
2876                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2877                         else
2878                                 glColor3ub(80,80,80);
2879                 } else {
2880                         if (ob->flag & OB_FROMGROUP) 
2881                                 UI_ThemeColor(TH_GROUP);
2882                         else {
2883                                 if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
2884                                         glColor3ub(80,80,80);
2885                                 else
2886                                         UI_ThemeColor(TH_WIRE);
2887                         }
2888                 }
2889         }
2890         if (draw_wire) {
2891                         /* If drawing wire and drawtype is not OB_WIRE then we are
2892                                 * overlaying the wires.
2893                                 *
2894                                 * UPDATE bug #10290 - With this wire-only objects can draw
2895                                 * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
2896                                 * 
2897                                 * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
2898                                 * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
2899                                 */
2900                 if (dt!=OB_WIRE && draw_wire==2) {
2901                         bglPolygonOffset(rv3d->dist, 1.0);
2902                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2903                 }
2904                 
2905                 dm->drawEdges(dm, (dt==OB_WIRE || totface==0));
2906                 
2907                 if (dt!=OB_WIRE && draw_wire==2) {
2908                         glDepthMask(1);
2909                         bglPolygonOffset(rv3d->dist, 0.0);
2910                 }
2911         }
2912
2913         dm->release(dm);
2914 }
2915
2916 /* returns 1 if nothing was drawn, for detecting to draw an object center */
2917 static int draw_mesh_object(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2918 {
2919         Object *ob= base->object;
2920         Object *obedit= scene->obedit;
2921         Mesh *me= ob->data;
2922         EditMesh *em= me->edit_mesh;
2923         int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha;
2924         
2925         if(obedit && ob!=obedit && ob->data==obedit->data) {
2926                 if(ob_get_key(ob));
2927                 else drawlinked= 1;
2928         }
2929         
2930         if(ob==obedit || drawlinked) {
2931                 DerivedMesh *finalDM, *cageDM;
2932                 
2933                 if (obedit!=ob)
2934                         finalDM = cageDM = editmesh_get_derived_base(ob, em);
2935                 else
2936                         cageDM = editmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,