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