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