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