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