01bdc1ba941c86fab5036e4c806e1e9f4c397ddf
[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; ARegion *ar; View3D *v3d; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData;
1206         EditVert *eve = EM_get_vert_for_index(index);
1207         short s[2];
1208
1209         if (eve->h==0) {
1210                 if (data->clipVerts) {
1211                         view3d_project_short_clip(data->ar, data->v3d, co, s, data->pmat, data->vmat);
1212                 } else {
1213                         view3d_project_short_noclip(data->ar, co, s, data->pmat);
1214                 }
1215
1216                 data->func(data->userData, eve, s[0], s[1], index);
1217         }
1218 }
1219
1220 void mesh_foreachScreenVert(ARegion *ar, View3D *v3d, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
1221 {
1222         struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ARegion *ar; View3D *v3d; int clipVerts; float pmat[4][4], vmat[4][4]; } data;
1223         DerivedMesh *dm = editmesh_get_derived_cage(CD_MASK_BAREMESH);
1224
1225         data.func = func;
1226         data.userData = userData;
1227         data.ar= ar;
1228         data.v3d= v3d;
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; ARegion *ar; View3D *v3d; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData;
1243         EditEdge *eed = EM_get_edge_for_index(index);
1244         short s[2][2];
1245
1246         if (eed->h==0) {
1247                 if (data->clipVerts==1) {
1248                         view3d_project_short_clip(data->ar, data->v3d, v0co, s[0], data->pmat, data->vmat);
1249                         view3d_project_short_clip(data->ar, data->v3d, v1co, s[1], data->pmat, data->vmat);
1250                 } else {
1251                         view3d_project_short_noclip(data->ar, v0co, s[0], data->pmat);
1252                         view3d_project_short_noclip(data->ar, v1co, s[1], data->pmat);
1253
1254                         if (data->clipVerts==2) {
1255                 if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->ar->winx && s[0][1]<data->ar->winy)) 
1256                                         if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<data->ar->winx && s[1][1]<data->ar->winy)) 
1257                                                 return;
1258                         }
1259                 }
1260
1261                 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
1262         }
1263 }
1264 void mesh_foreachScreenEdge(ARegion *ar, View3D *v3d, void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts)
1265 {
1266         struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ARegion *ar; View3D *v3d; int clipVerts; float pmat[4][4], vmat[4][4]; } data;
1267         DerivedMesh *dm = editmesh_get_derived_cage(CD_MASK_BAREMESH);
1268
1269         data.func = func;
1270         data.ar= ar;
1271         data.v3d= v3d;
1272         data.userData = userData;
1273         data.clipVerts = clipVerts;
1274
1275         view3d_get_object_project_mat(v3d, G.obedit, data.pmat, data.vmat);
1276
1277         EM_init_index_arrays(0, 1, 0);
1278         dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
1279         EM_free_index_arrays();
1280
1281         dm->release(dm);
1282 }
1283
1284 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *no)
1285 {
1286         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ARegion *ar; View3D *v3d; float pmat[4][4], vmat[4][4]; } *data = userData;
1287         EditFace *efa = EM_get_face_for_index(index);
1288         short s[2];
1289
1290         if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
1291                 view3d_project_short_clip(data->ar, data->v3d, cent, s, data->pmat, data->vmat);
1292
1293                 data->func(data->userData, efa, s[0], s[1], index);
1294         }
1295 }
1296 void mesh_foreachScreenFace(ARegion *ar, View3D *v3d, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
1297 {
1298         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ARegion *ar; View3D *v3d; float pmat[4][4], vmat[4][4]; } data;
1299         DerivedMesh *dm = editmesh_get_derived_cage(CD_MASK_BAREMESH);
1300
1301         data.func = func;
1302         data.ar= ar;
1303         data.v3d= v3d;
1304         data.userData = userData;
1305
1306         view3d_get_object_project_mat(v3d, G.obedit, data.pmat, data.vmat);
1307
1308         EM_init_index_arrays(0, 0, 1);
1309         dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
1310         EM_free_index_arrays();
1311
1312         dm->release(dm);
1313 }
1314
1315 void nurbs_foreachScreenVert(ARegion *ar, View3D *v3d, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
1316 {
1317         float pmat[4][4], vmat[4][4];
1318         short s[2];
1319         Nurb *nu;
1320         int i;
1321
1322         view3d_get_object_project_mat(v3d, G.obedit, pmat, vmat);
1323
1324         for (nu= editNurb.first; nu; nu=nu->next) {
1325                 if((nu->type & 7)==CU_BEZIER) {
1326                         for (i=0; i<nu->pntsu; i++) {
1327                                 BezTriple *bezt = &nu->bezt[i];
1328
1329                                 if(bezt->hide==0) {
1330                                         if (G.f & G_HIDDENHANDLES) {
1331                                                 view3d_project_short_clip(ar, v3d, bezt->vec[1], s, pmat, vmat);
1332                                                 if (s[0] != IS_CLIPPED)
1333                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1334                                         } else {
1335                                                 view3d_project_short_clip(ar, v3d, bezt->vec[0], s, pmat, vmat);
1336                                                 if (s[0] != IS_CLIPPED)
1337                                                         func(userData, nu, NULL, bezt, 0, s[0], s[1]);
1338                                                 view3d_project_short_clip(ar, v3d, bezt->vec[1], s, pmat, vmat);
1339                                                 if (s[0] != IS_CLIPPED)
1340                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1341                                                 view3d_project_short_clip(ar, v3d, bezt->vec[2], s, pmat, vmat);
1342                                                 if (s[0] != IS_CLIPPED)
1343                                                         func(userData, nu, NULL, bezt, 2, s[0], s[1]);
1344                                         }
1345                                 }
1346                         }
1347                 }
1348                 else {
1349                         for (i=0; i<nu->pntsu*nu->pntsv; i++) {
1350                                 BPoint *bp = &nu->bp[i];
1351
1352                                 if(bp->hide==0) {
1353                                         view3d_project_short_clip(ar, v3d, bp->vec, s, pmat, vmat);
1354                                         func(userData, nu, bp, NULL, -1, s[0], s[1]);
1355                                 }
1356                         }
1357                 }
1358         }
1359 }
1360
1361 /* ************** DRAW MESH ****************** */
1362
1363 /* First section is all the "simple" draw routines, 
1364  * ones that just pass some sort of primitive to GL,
1365  * with perhaps various options to control lighting,
1366  * color, etc.
1367  *
1368  * These routines should not have user interface related
1369  * logic!!!
1370  */
1371
1372 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
1373 {
1374         Scene *scene= (Scene *)userData;
1375         EditFace *efa = EM_get_face_for_index(index);
1376
1377         if (efa->h==0 && efa->fgonf!=EM_FGON) {
1378                 glVertex3fv(cent);
1379                 glVertex3f(     cent[0] + no[0]*scene->editbutsize,
1380                                         cent[1] + no[1]*scene->editbutsize,
1381                                         cent[2] + no[2]*scene->editbutsize);
1382         }
1383 }
1384 static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm) 
1385 {
1386         glBegin(GL_LINES);
1387         dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
1388         glEnd();
1389 }
1390
1391 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *no)
1392 {
1393         EditFace *efa = EM_get_face_for_index(index);
1394         int sel = *((int*) userData);
1395
1396         if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
1397                 bglVertex3fv(cent);
1398         }
1399 }
1400 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
1401 {
1402         bglBegin(GL_POINTS);
1403         dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
1404         bglEnd();
1405 }
1406
1407 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1408 {
1409         Scene *scene= (Scene *)userData;
1410         EditVert *eve = EM_get_vert_for_index(index);
1411
1412         if (eve->h==0) {
1413                 glVertex3fv(co);
1414
1415                 if (no_f) {
1416                         glVertex3f(     co[0] + no_f[0]*scene->editbutsize,
1417                                                 co[1] + no_f[1]*scene->editbutsize,
1418                                                 co[2] + no_f[2]*scene->editbutsize);
1419                 } else {
1420                         glVertex3f(     co[0] + no_s[0]*scene->editbutsize/32767.0f,
1421                                                 co[1] + no_s[1]*scene->editbutsize/32767.0f,
1422                                                 co[2] + no_s[2]*scene->editbutsize/32767.0f);
1423                 }
1424         }
1425 }
1426 static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm) 
1427 {
1428         glBegin(GL_LINES);
1429         dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
1430         glEnd();
1431 }
1432
1433         /* Draw verts with color set based on selection */
1434 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1435 {
1436         struct { int sel; EditVert *eve_act; } * data = userData;
1437         EditVert *eve = EM_get_vert_for_index(index);
1438
1439         if (eve->h==0 && (eve->f&SELECT)==data->sel) {
1440                 /* draw active larger - need to stop/start point drawing for this :/ */
1441                 if (eve==data->eve_act) {
1442                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1443                         UI_ThemeColor4(TH_EDITMESH_ACTIVE);
1444                         
1445                         bglEnd();
1446                         
1447                         glPointSize(size);
1448                         bglBegin(GL_POINTS);
1449                         bglVertex3fv(co);
1450                         bglEnd();
1451                         
1452                         UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
1453                         glPointSize(size);
1454                         bglBegin(GL_POINTS);
1455                 } else {
1456                         bglVertex3fv(co);
1457                 }
1458         }
1459 }
1460 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
1461 {
1462         struct { int sel; EditVert *eve_act; } data;
1463         data.sel = sel;
1464         data.eve_act = eve_act;
1465         
1466         bglBegin(GL_POINTS);
1467         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
1468         bglEnd();
1469 }
1470
1471         /* Draw edges with color set based on selection */
1472 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
1473 {
1474         EditEdge *eed = EM_get_edge_for_index(index);
1475         //unsigned char **cols = userData, *col;
1476         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
1477         unsigned char *col;
1478
1479         if (eed->h==0) {
1480                 if (eed==data->eed_act) {
1481                         glColor4ubv(data->actCol);
1482                 } else {
1483                         if (eed->f&SELECT) {
1484                                 col = data->selCol;
1485                         } else {
1486                                 col = data->baseCol;
1487                         }
1488                         /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode  */
1489                         if (col[3]==0) return 0;
1490                         
1491                         glColor4ubv(col);
1492                 }
1493                 return 1;
1494         } else {
1495                 return 0;
1496         }
1497 }
1498 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act) 
1499 {
1500         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
1501         
1502         data.baseCol = baseCol;
1503         data.selCol = selCol;
1504         data.actCol = actCol;
1505         data.eed_act = eed_act;
1506         dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
1507 }
1508
1509         /* Draw edges */
1510 static int draw_dm_edges__setDrawOptions(void *userData, int index)
1511 {
1512         return EM_get_edge_for_index(index)->h==0;
1513 }
1514 static void draw_dm_edges(DerivedMesh *dm) 
1515 {
1516         dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
1517 }
1518
1519         /* Draw edges with color interpolated based on selection */
1520 static int draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
1521 {
1522         return EM_get_edge_for_index(index)->h==0;
1523 }
1524 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
1525 {
1526         EditEdge *eed = EM_get_edge_for_index(index);
1527         unsigned char **cols = userData;
1528         unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
1529         unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
1530
1531         glColor4ub(     col0[0] + (col1[0]-col0[0])*t,
1532                                 col0[1] + (col1[1]-col0[1])*t,
1533                                 col0[2] + (col1[2]-col0[2])*t,
1534                                 col0[3] + (col1[3]-col0[3])*t);
1535 }
1536 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
1537 {
1538         unsigned char *cols[2];
1539         cols[0] = baseCol;
1540         cols[1] = selCol;
1541         dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
1542 }
1543
1544         /* Draw only seam edges */
1545 static int draw_dm_edges_seams__setDrawOptions(void *userData, int index)
1546 {
1547         EditEdge *eed = EM_get_edge_for_index(index);
1548
1549         return (eed->h==0 && eed->seam);
1550 }
1551 static void draw_dm_edges_seams(DerivedMesh *dm)
1552 {
1553         dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
1554 }
1555
1556         /* Draw only sharp edges */
1557 static int draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
1558 {
1559         EditEdge *eed = EM_get_edge_for_index(index);
1560
1561         return (eed->h==0 && eed->sharp);
1562 }
1563 static void draw_dm_edges_sharp(DerivedMesh *dm)
1564 {
1565         dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
1566 }
1567
1568
1569         /* Draw faces with color set based on selection
1570          * return 2 for the active face so it renders with stipple enabled */
1571 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *drawSmooth_r)
1572 {
1573         struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
1574         EditFace *efa = EM_get_face_for_index(index);
1575         unsigned char *col;
1576         
1577         if (efa->h==0) {
1578                 if (efa == data->efa_act) {
1579                         glColor4ubv(data->cols[2]);
1580                         return 2; /* stipple */
1581                 } else {
1582                         col = data->cols[(efa->f&SELECT)?1:0];
1583                         if (col[3]==0) return 0;
1584                         glColor4ubv(col);
1585                         return 1;
1586                 }
1587         }
1588         return 0;
1589 }
1590
1591 /* also draws the active face */
1592 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act) 
1593 {
1594         struct { unsigned char *cols[3]; EditFace *efa_act; } data;
1595         data.cols[0] = baseCol;
1596         data.cols[1] = selCol;
1597         data.cols[2] = actCol;
1598         data.efa_act = efa_act;
1599         
1600         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0);
1601 }
1602
1603 static int draw_dm_creases__setDrawOptions(void *userData, int index)
1604 {
1605         EditEdge *eed = EM_get_edge_for_index(index);
1606
1607         if (eed->h==0 && eed->crease!=0.0) {
1608                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->crease);
1609                 return 1;
1610         } else {
1611                 return 0;
1612         }
1613 }
1614 static void draw_dm_creases(DerivedMesh *dm)
1615 {
1616         glLineWidth(3.0);
1617         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
1618         glLineWidth(1.0);
1619 }
1620
1621 static int draw_dm_bweights__setDrawOptions(void *userData, int index)
1622 {
1623         EditEdge *eed = EM_get_edge_for_index(index);
1624
1625         if (eed->h==0 && eed->bweight!=0.0) {
1626                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
1627                 return 1;
1628         } else {
1629                 return 0;
1630         }
1631 }
1632 static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1633 {
1634         EditVert *eve = EM_get_vert_for_index(index);
1635
1636         if (eve->h==0 && eve->bweight!=0.0) {
1637                 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
1638                 bglVertex3fv(co);
1639         }
1640 }
1641 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
1642 {
1643         if (scene->selectmode & SCE_SELECT_VERTEX) {
1644                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
1645                 bglBegin(GL_POINTS);
1646                 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
1647                 bglEnd();
1648         }
1649         else {
1650                 glLineWidth(3.0);
1651                 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
1652                 glLineWidth(1.0);
1653         }
1654 }
1655
1656 /* Second section of routines: Combine first sets to form fancy
1657  * drawing routines (for example rendering twice to get overlays).
1658  *
1659  * Also includes routines that are basic drawing but are too
1660  * specialized to be split out (like drawing creases or measurements).
1661  */
1662
1663 /* EditMesh drawing routines*/
1664
1665 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, EditMesh *em, DerivedMesh *cageDM, EditVert *eve_act)
1666 {
1667         int sel;
1668
1669         if(v3d->zbuf) glDepthMask(0);           // disable write in zbuffer, zbuf select
1670
1671         for (sel=0; sel<2; sel++) {
1672                 char col[4], fcol[4];
1673                 int pass;
1674
1675                 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
1676                 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
1677
1678                 for (pass=0; pass<2; pass++) {
1679                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1680                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
1681
1682                         if (pass==0) {
1683                                 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
1684                                         glDisable(GL_DEPTH_TEST);
1685                                                 
1686                                         glEnable(GL_BLEND);
1687                                 } else {
1688                                         continue;
1689                                 }
1690
1691                                 size = (size>2.1?size/2.0:size);
1692                                 fsize = (fsize>2.1?fsize/2.0:fsize);
1693                                 col[3] = fcol[3] = 100;
1694                         } else {
1695                                 col[3] = fcol[3] = 255;
1696                         }
1697                                 
1698                         if(scene->selectmode & SCE_SELECT_VERTEX) {
1699                                 glPointSize(size);
1700                                 glColor4ubv((GLubyte *)col);
1701                                 draw_dm_verts(cageDM, sel, eve_act);
1702                         }
1703                         
1704                         if( CHECK_OB_DRAWFACEDOT(scene, v3d, G.obedit->dt) ) {
1705                                 glPointSize(fsize);
1706                                 glColor4ubv((GLubyte *)fcol);
1707                                 draw_dm_face_centers(cageDM, sel);
1708                         }
1709                         
1710                         if (pass==0) {
1711                                 glDisable(GL_BLEND);
1712                                 glEnable(GL_DEPTH_TEST);
1713                         }
1714                 }
1715         }
1716
1717         if(v3d->zbuf) glDepthMask(1);
1718         glPointSize(1.0);
1719 }
1720
1721 static void draw_em_fancy_edges(Scene *scene, View3D *v3d, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
1722 {
1723         int pass;
1724         unsigned char wireCol[4], selCol[4], actCol[4];
1725
1726         /* since this function does transparant... */
1727         UI_GetThemeColor4ubv(TH_EDGE_SELECT, (char *)selCol);
1728         UI_GetThemeColor4ubv(TH_WIRE, (char *)wireCol);
1729         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)actCol);
1730         
1731         /* when sel only is used, dont render wire, only selected, this is used for
1732          * textured draw mode when the 'edges' option is disabled */
1733         if (sel_only)
1734                 wireCol[3] = 0;
1735
1736         for (pass=0; pass<2; pass++) {
1737                         /* show wires in transparant when no zbuf clipping for select */
1738                 if (pass==0) {
1739                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
1740                                 glEnable(GL_BLEND);
1741                                 glDisable(GL_DEPTH_TEST);
1742                                 selCol[3] = 85;
1743                                 if (!sel_only) wireCol[3] = 85;
1744                         } else {
1745                                 continue;
1746                         }
1747                 } else {
1748                         selCol[3] = 255;
1749                         if (!sel_only) wireCol[3] = 255;
1750                 }
1751
1752                 if(scene->selectmode == SCE_SELECT_FACE) {
1753                         draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
1754                 }       
1755                 else if( (G.f & G_DRAWEDGES) || (scene->selectmode & SCE_SELECT_EDGE) ) {       
1756                         if(cageDM->drawMappedEdgesInterp && (scene->selectmode & SCE_SELECT_VERTEX)) {
1757                                 glShadeModel(GL_SMOOTH);
1758                                 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
1759                                 glShadeModel(GL_FLAT);
1760                         } else {
1761                                 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
1762                         }
1763                 }
1764                 else {
1765                         if (!sel_only) {
1766                                 glColor4ubv(wireCol);
1767                                 draw_dm_edges(cageDM);
1768                         }
1769                 }
1770
1771                 if (pass==0) {
1772                         glDisable(GL_BLEND);
1773                         glEnable(GL_DEPTH_TEST);
1774                 }
1775         }
1776 }       
1777
1778 static void draw_em_measure_stats(View3D *v3d, Object *ob, EditMesh *em)
1779 {
1780         EditEdge *eed;
1781         EditFace *efa;
1782         float v1[3], v2[3], v3[3], v4[3];
1783         float fvec[3];
1784         char val[32]; /* Stores the measurement display text here */
1785         char conv_float[5]; /* Use a float conversion matching the grid size */
1786         float area, col[3]; /* area of the face,  color of the text to draw */
1787         
1788         if(G.f & (G_RENDER_OGL|G_RENDER_SHADOW))
1789                 return;
1790
1791         /* make the precission of the pronted value proportionate to the gridsize */
1792         if ((v3d->grid) < 0.01)
1793                 strcpy(conv_float, "%.6f");
1794         else if ((v3d->grid) < 0.1)
1795                 strcpy(conv_float, "%.5f");
1796         else if ((v3d->grid) < 1.0)
1797                 strcpy(conv_float, "%.4f");
1798         else if ((v3d->grid) < 10.0)
1799                 strcpy(conv_float, "%.3f");
1800         else
1801                 strcpy(conv_float, "%.2f");
1802         
1803         
1804         if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
1805                 glDisable(GL_DEPTH_TEST);
1806
1807         if(v3d->zbuf) bglPolygonOffset(5.0);
1808         
1809         if(G.f & G_DRAW_EDGELEN) {
1810                 UI_GetThemeColor3fv(TH_TEXT, col);
1811                 /* make color a bit more red */
1812                 if(col[0]> 0.5) {col[1]*=0.7; col[2]*= 0.7;}
1813                 else col[0]= col[0]*0.7 + 0.3;
1814                 glColor3fv(col);
1815                 
1816                 for(eed= em->edges.first; eed; eed= eed->next) {
1817                         /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
1818                         if((eed->h != EM_FGON) && ((eed->f & SELECT) || (G.moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
1819                                 VECCOPY(v1, eed->v1->co);
1820                                 VECCOPY(v2, eed->v2->co);
1821                                 
1822                                 glRasterPos3f( 0.5*(v1[0]+v2[0]),  0.5*(v1[1]+v2[1]),  0.5*(v1[2]+v2[2]));
1823                                 
1824                                 if(v3d->flag & V3D_GLOBAL_STATS) {
1825                                         Mat4MulVecfl(ob->obmat, v1);
1826                                         Mat4MulVecfl(ob->obmat, v2);
1827                                 }
1828                                 
1829                                 sprintf(val, conv_float, VecLenf(v1, v2));
1830                                 BMF_DrawString( G.fonts, val);
1831                         }
1832                 }
1833         }
1834
1835         if(G.f & G_DRAW_FACEAREA) {
1836 // XXX          extern int faceselectedOR(EditFace *efa, int flag);             // editmesh.h shouldn't be in this file... ok for now?
1837                 
1838                 UI_GetThemeColor3fv(TH_TEXT, col);
1839                 /* make color a bit more green */
1840                 if(col[1]> 0.5) {col[0]*=0.7; col[2]*= 0.7;}
1841                 else col[1]= col[1]*0.7 + 0.3;
1842                 glColor3fv(col);
1843                 
1844                 for(efa= em->faces.first; efa; efa= efa->next) {
1845                         if((efa->f & SELECT)) { // XXX || (G.moving && faceselectedOR(efa, SELECT)) ) {
1846                                 VECCOPY(v1, efa->v1->co);
1847                                 VECCOPY(v2, efa->v2->co);
1848                                 VECCOPY(v3, efa->v3->co);
1849                                 if (efa->v4) {
1850                                         VECCOPY(v4, efa->v4->co);
1851                                 }
1852                                 if(v3d->flag & V3D_GLOBAL_STATS) {
1853                                         Mat4MulVecfl(ob->obmat, v1);
1854                                         Mat4MulVecfl(ob->obmat, v2);
1855                                         Mat4MulVecfl(ob->obmat, v3);
1856                                         if (efa->v4) Mat4MulVecfl(ob->obmat, v4);
1857                                 }
1858                                 
1859                                 if (efa->v4)
1860                                         area=  AreaQ3Dfl(v1, v2, v3, v4);
1861                                 else
1862                                         area = AreaT3Dfl(v1, v2, v3);
1863
1864                                 sprintf(val, conv_float, area);
1865                                 glRasterPos3fv(efa->cent);
1866                                 BMF_DrawString( G.fonts, val);
1867                         }
1868                 }
1869         }
1870
1871         if(G.f & G_DRAW_EDGEANG) {
1872                 EditEdge *e1, *e2, *e3, *e4;
1873                 
1874                 UI_GetThemeColor3fv(TH_TEXT, col);
1875                 /* make color a bit more blue */
1876                 if(col[2]> 0.5) {col[0]*=0.7; col[1]*= 0.7;}
1877                 else col[2]= col[2]*0.7 + 0.3;
1878                 glColor3fv(col);
1879                 
1880                 for(efa= em->faces.first; efa; efa= efa->next) {
1881                         VECCOPY(v1, efa->v1->co);
1882                         VECCOPY(v2, efa->v2->co);
1883                         VECCOPY(v3, efa->v3->co);
1884                         if(efa->v4) {
1885                                 VECCOPY(v4, efa->v4->co); 
1886                         }
1887                         else {
1888                                 VECCOPY(v4, v3);
1889                         }
1890                         if(v3d->flag & V3D_GLOBAL_STATS) {
1891                                 Mat4MulVecfl(ob->obmat, v1);
1892                                 Mat4MulVecfl(ob->obmat, v2);
1893                                 Mat4MulVecfl(ob->obmat, v3);
1894                                 Mat4MulVecfl(ob->obmat, v4);
1895                         }
1896                         
1897                         e1= efa->e1;
1898                         e2= efa->e2;
1899                         e3= efa->e3;
1900                         if(efa->e4) e4= efa->e4; else e4= e3;
1901                         
1902                         /* Calculate the angles */
1903                                 
1904                         if( (e4->f & e1->f & SELECT) || (G.moving && (efa->v1->f & SELECT)) ) {
1905                                 /* Vec 1 */
1906                                 sprintf(val,"%.3f", VecAngle3(v4, v1, v2));
1907                                 VecLerpf(fvec, efa->cent, efa->v1->co, 0.8);
1908                                 glRasterPos3fv(fvec);
1909                                 BMF_DrawString( G.fonts, val);
1910                         }
1911                         if( (e1->f & e2->f & SELECT) || (G.moving && (efa->v2->f & SELECT)) ) {
1912                                 /* Vec 2 */
1913                                 sprintf(val,"%.3f", VecAngle3(v1, v2, v3));
1914                                 VecLerpf(fvec, efa->cent, efa->v2->co, 0.8);
1915                                 glRasterPos3fv(fvec);
1916                                 BMF_DrawString( G.fonts, val);
1917                         }
1918                         if( (e2->f & e3->f & SELECT) || (G.moving && (efa->v3->f & SELECT)) ) {
1919                                 /* Vec 3 */
1920                                 if(efa->v4) 
1921                                         sprintf(val,"%.3f", VecAngle3(v2, v3, v4));
1922                                 else
1923                                         sprintf(val,"%.3f", VecAngle3(v2, v3, v1));
1924                                 VecLerpf(fvec, efa->cent, efa->v3->co, 0.8);
1925                                 glRasterPos3fv(fvec);
1926                                 BMF_DrawString( G.fonts, val);
1927                         }
1928                                 /* Vec 4 */
1929                         if(efa->v4) {
1930                                 if( (e3->f & e4->f & SELECT) || (G.moving && (efa->v4->f & SELECT)) ) {
1931                                         sprintf(val,"%.3f", VecAngle3(v3, v4, v1));
1932                                         VecLerpf(fvec, efa->cent, efa->v4->co, 0.8);
1933                                         glRasterPos3fv(fvec);
1934                                         BMF_DrawString( G.fonts, val);
1935                                 }
1936                         }
1937                 }
1938         }    
1939         
1940         if(v3d->zbuf) {
1941                 glEnable(GL_DEPTH_TEST);
1942                 bglPolygonOffset(0.0);
1943         }
1944 }
1945
1946 static int draw_em_fancy__setFaceOpts(void *userData, int index, int *drawSmooth_r)
1947 {
1948         EditFace *efa = EM_get_face_for_index(index);
1949
1950         if (efa->h==0) {
1951                 GPU_enable_material(efa->mat_nr+1, NULL);
1952                 return 1;
1953         }
1954         else
1955                 return 0;
1956 }
1957
1958 static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
1959 {
1960         EditFace *efa = EM_get_face_for_index(index);
1961
1962         return (efa->h==0);
1963 }
1964
1965 static void draw_em_fancy(Scene *scene, View3D *v3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
1966 {
1967         Mesh *me = ob->data;
1968         EditFace *efa_act = EM_get_actFace(0); /* annoying but active faces is stored differently */
1969         EditEdge *eed_act = NULL;
1970         EditVert *eve_act = NULL;
1971         
1972         if (G.editMesh->selected.last) {
1973                 EditSelection *ese = G.editMesh->selected.last;
1974                 /* face is handeled above */
1975                 /*if (ese->type == EDITFACE ) {
1976                         efa_act = (EditFace *)ese->data;
1977                 } else */ if ( ese->type == EDITEDGE ) {
1978                         eed_act = (EditEdge *)ese->data;
1979                 } else if ( ese->type == EDITVERT ) {
1980                         eve_act = (EditVert *)ese->data;
1981                 }
1982         }
1983         
1984         EM_init_index_arrays(1, 1, 1);
1985
1986         if(dt>OB_WIRE) {
1987                 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
1988                         if(draw_glsl_material(scene, ob, v3d, dt)) {
1989                                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
1990
1991                                 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
1992                                         draw_em_fancy__setGLSLFaceOpts, NULL);
1993                                 GPU_disable_material();
1994
1995                                 glFrontFace(GL_CCW);
1996                         }
1997                         else {
1998                                 draw_mesh_textured(scene, v3d, ob, finalDM, 0);
1999                         }
2000                 }
2001                 else {
2002                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2003
2004                         glEnable(GL_LIGHTING);
2005                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2006
2007                         finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, 0, 0);
2008
2009                         glFrontFace(GL_CCW);
2010                         glDisable(GL_LIGHTING);
2011                 }
2012                         
2013                 // Setup for drawing wire over, disable zbuffer
2014                 // write to show selected edge wires better
2015                 UI_ThemeColor(TH_WIRE);
2016
2017                 bglPolygonOffset(1.0);
2018                 glDepthMask(0);
2019         } 
2020         else {
2021                 if (cageDM!=finalDM) {
2022                         UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2023                         finalDM->drawEdges(finalDM, 1);
2024                 }
2025         }
2026         
2027         if((G.f & (G_DRAWFACES)) || FACESEL_PAINT_TEST) {       /* transp faces */
2028                 unsigned char col1[4], col2[4], col3[4];
2029                         
2030                 UI_GetThemeColor4ubv(TH_FACE, (char *)col1);
2031                 UI_GetThemeColor4ubv(TH_FACE_SELECT, (char *)col2);
2032                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2033                 
2034                 glEnable(GL_BLEND);
2035                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2036                 
2037                 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2038                 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2039                         col1[3] = 0;
2040                 
2041                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2042
2043                 glDisable(GL_BLEND);
2044                 glDepthMask(1);         // restore write in zbuffer
2045         } else if (efa_act) {
2046                 /* even if draw faces is off it would be nice to draw the stipple face
2047                  * Make all other faces zero alpha except for the active
2048                  * */
2049                 unsigned char col1[4], col2[4], col3[4];
2050                 col1[3] = col2[3] = 0; /* dont draw */
2051                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2052                 
2053                 glEnable(GL_BLEND);
2054                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2055                 
2056                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2057
2058                 glDisable(GL_BLEND);
2059                 glDepthMask(1);         // restore write in zbuffer
2060                 
2061         }
2062
2063         /* here starts all fancy draw-extra over */
2064         if((G.f & G_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2065                 /* we are drawing textures and 'G_DRAWEDGES' is disabled, dont draw any edges */
2066                 
2067                 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2068                 draw_em_fancy_edges(scene, v3d, cageDM, 1, eed_act);
2069                 
2070         } else {
2071                 if(G.f & G_DRAWSEAMS) {
2072                         UI_ThemeColor(TH_EDGE_SEAM);
2073                         glLineWidth(2);
2074         
2075                         draw_dm_edges_seams(cageDM);
2076         
2077                         glColor3ub(0,0,0);
2078                         glLineWidth(1);
2079                 }
2080                 
2081                 if(G.f & G_DRAWSHARP) {
2082                         UI_ThemeColor(TH_EDGE_SHARP);
2083                         glLineWidth(2);
2084         
2085                         draw_dm_edges_sharp(cageDM);
2086         
2087                         glColor3ub(0,0,0);
2088                         glLineWidth(1);
2089                 }
2090         
2091                 if(G.f & G_DRAWCREASES) {
2092                         draw_dm_creases(cageDM);
2093                 }
2094                 if(G.f & G_DRAWBWEIGHTS) {
2095                         draw_dm_bweights(scene, cageDM);
2096                 }
2097         
2098                 draw_em_fancy_edges(scene, v3d, cageDM, 0, eed_act);
2099         }
2100         if(ob==G.obedit) {
2101 // XXX          retopo_matrix_update(v3d);
2102
2103                 draw_em_fancy_verts(scene, v3d, em, cageDM, eve_act);
2104
2105                 if(G.f & G_DRAWNORMALS) {
2106                         UI_ThemeColor(TH_NORMAL);
2107                         draw_dm_face_normals(scene, cageDM);
2108                 }
2109                 if(G.f & G_DRAW_VNORMALS) {
2110                         UI_ThemeColor(TH_NORMAL);
2111                         draw_dm_vert_normals(scene, cageDM);
2112                 }
2113
2114                 if(G.f & (G_DRAW_EDGELEN|G_DRAW_FACEAREA|G_DRAW_EDGEANG))
2115                         draw_em_measure_stats(v3d, ob, em);
2116         }
2117
2118         if(dt>OB_WIRE) {
2119                 glDepthMask(1);
2120                 bglPolygonOffset(0.0);
2121                 GPU_disable_material();
2122         }
2123
2124         EM_free_index_arrays();
2125 }
2126
2127 /* Mesh drawing routines */
2128
2129 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2130 {
2131         
2132         if(v3d->transp==0) {    // not when we draw the transparent pass
2133                 glLineWidth(2.0);
2134                 glDepthMask(0);
2135                 
2136                 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2137                    drawFacesSolid() doesn't draw the transparent faces */
2138                 if(ob->dtx & OB_DRAWTRANSP) {
2139                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2140                         dm->drawFacesSolid(dm, GPU_enable_material);
2141                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2142                         GPU_disable_material();
2143                 }
2144                 else {
2145                         dm->drawEdges(dm, 0);
2146                 }
2147                                         
2148                 glLineWidth(1.0);
2149                 glDepthMask(1);
2150         }
2151 }
2152
2153 static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
2154 {
2155         *drawSmooth_r = 1;
2156         return 1;
2157 }
2158
2159 static void draw_mesh_fancy(Scene *scene, View3D *v3d, Base *base, int dt, int flag)
2160 {
2161         Object *ob= base->object;
2162         Mesh *me = ob->data;
2163         Material *ma= give_current_material(ob, 1);
2164         int hasHaloMat = (ma && (ma->mode&MA_HALO));
2165         int draw_wire = 0;
2166         int totvert, totedge, totface;
2167         DispList *dl;
2168         DerivedMesh *dm= mesh_get_derived_final(ob, get_viewedit_datamask());
2169
2170         if(!dm)
2171                 return;
2172         
2173         if (ob->dtx&OB_DRAWWIRE) {
2174                 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
2175         }
2176         
2177         totvert = dm->getNumVerts(dm);
2178         totedge = dm->getNumEdges(dm);
2179         totface = dm->getNumFaces(dm);
2180         
2181         /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2182         if(dt!=OB_SHADED)
2183                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2184
2185                 // Unwanted combination.
2186         if (ob==OBACT && FACESEL_PAINT_TEST) draw_wire = 0;
2187
2188         if(dt==OB_BOUNDBOX) {
2189                 draw_bounding_volume(ob);
2190         }
2191         else if(hasHaloMat || (totface==0 && totedge==0)) {
2192                 glPointSize(1.5);
2193                 dm->drawVerts(dm);
2194                 glPointSize(1.0);
2195         }
2196         else if(dt==OB_WIRE || totface==0) {
2197                 draw_wire = 1; /* draw wire only, no depth buffer stuff  */
2198         }
2199         else if(        (ob==OBACT && (G.f & G_TEXTUREPAINT || FACESEL_PAINT_TEST)) ||
2200                                 CHECK_OB_DRAWTEXTURE(v3d, dt))
2201         {
2202                 int faceselect= (ob==OBACT && FACESEL_PAINT_TEST);
2203
2204                 if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !(G.f&G_PICKSEL || FACESEL_PAINT_TEST) && !draw_wire) {
2205                         draw_mesh_object_outline(v3d, ob, dm);
2206                 }
2207
2208                 if(draw_glsl_material(scene, ob, v3d, dt)) {
2209                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2210
2211                         dm->drawFacesGLSL(dm, GPU_enable_material);
2212 //                      if(get_ob_property(ob, "Text"))
2213 // XXX                          draw_mesh_text(ob, 1);
2214                         GPU_disable_material();
2215
2216                         glFrontFace(GL_CCW);
2217                 }
2218                 else {
2219                         draw_mesh_textured(scene, v3d, ob, dm, faceselect);
2220                 }
2221
2222                 if(!faceselect) {
2223                         if(base->flag & SELECT)
2224                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2225                         else
2226                                 UI_ThemeColor(TH_WIRE);
2227
2228                         dm->drawLooseEdges(dm);
2229                 }
2230         }
2231         else if(dt==OB_SOLID) {
2232                 if((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire)
2233                         draw_mesh_object_outline(v3d, ob, dm);
2234
2235                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
2236
2237                 glEnable(GL_LIGHTING);
2238                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2239
2240                 dm->drawFacesSolid(dm, GPU_enable_material);
2241                 GPU_disable_material();
2242
2243                 glFrontFace(GL_CCW);
2244                 glDisable(GL_LIGHTING);
2245
2246                 if(base->flag & SELECT) {
2247                         UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2248                 } else {
2249                         UI_ThemeColor(TH_WIRE);
2250                 }
2251                 dm->drawLooseEdges(dm);
2252         }
2253         else if(dt==OB_SHADED) {
2254                 int do_draw= 1; /* to resolve all G.f settings below... */
2255                 
2256                 if(ob==OBACT) {
2257                         do_draw= 0;
2258                         if( (G.f & G_WEIGHTPAINT)) {
2259                                 /* enforce default material settings */
2260                                 GPU_enable_material(0, NULL);
2261                                 
2262                                 /* but set default spec */
2263                                 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
2264                                 glEnable(GL_COLOR_MATERIAL);    /* according manpages needed */
2265                                 glColor3ub(120, 120, 120);
2266                                 glDisable(GL_COLOR_MATERIAL);
2267                                 /* diffuse */
2268                                 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2269                                 glEnable(GL_LIGHTING);
2270                                 glEnable(GL_COLOR_MATERIAL);
2271
2272                                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1);
2273                                 glDisable(GL_COLOR_MATERIAL);
2274                                 glDisable(GL_LIGHTING);
2275
2276                                 GPU_disable_material();
2277                         }
2278                         else if((G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) && me->mcol) {
2279                                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1);
2280                         }
2281                         else if(G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) {
2282                                 glColor3f(1.0f, 1.0f, 1.0f);
2283                                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0);
2284                         }
2285                         else do_draw= 1;
2286                 }
2287                 if(do_draw) {
2288                         dl = ob->disp.first;
2289                         if (!dl || !dl->col1) {
2290                                 /* release and reload derivedmesh because it might be freed in
2291                                    shadeDispList due to a different datamask */
2292                                 dm->release(dm);
2293                                 shadeDispList(base);
2294                                 dl = find_displist(&ob->disp, DL_VERTCOL);
2295                                 dm= mesh_get_derived_final(ob, get_viewedit_datamask());
2296                         }
2297
2298                         if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) {
2299                                 draw_mesh_object_outline(v3d, ob, dm);
2300                         }
2301
2302                                 /* False for dupliframe objects */
2303                         if (dl) {
2304                                 unsigned int *obCol1 = dl->col1;
2305                                 unsigned int *obCol2 = dl->col2;
2306
2307                                 dm->drawFacesColored(dm, me->flag&ME_TWOSIDED, (unsigned char*) obCol1, (unsigned char*) obCol2);
2308                         }
2309
2310                         if(base->flag & SELECT) {
2311                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2312                         } else {
2313                                 UI_ThemeColor(TH_WIRE);
2314                         }
2315                         dm->drawLooseEdges(dm);
2316                 }
2317         }
2318         
2319         /* set default draw color back for wire or for draw-extra later on */
2320         if (dt!=OB_WIRE) {
2321                 if(base->flag & SELECT) {
2322                         if(ob==OBACT && ob->flag & OB_FROMGROUP) 
2323                                 UI_ThemeColor(TH_GROUP_ACTIVE);
2324                         else if(ob->flag & OB_FROMGROUP) 
2325                                 UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
2326                         else if(flag!=DRAW_CONSTCOLOR)
2327                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2328                         else
2329                                 glColor3ub(80,80,80);
2330                 } else {
2331                         if (ob->flag & OB_FROMGROUP) 
2332                                 UI_ThemeColor(TH_GROUP);
2333                         else {
2334                                 if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
2335                                         glColor3ub(80,80,80);
2336                                 else
2337                                         UI_ThemeColor(TH_WIRE);
2338                         }
2339                 }
2340         }
2341         if (draw_wire) {
2342                         /* If drawing wire and drawtype is not OB_WIRE then we are
2343                                 * overlaying the wires.
2344                                 *
2345                                 * UPDATE bug #10290 - With this wire-only objects can draw
2346                                 * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
2347                                 * 
2348                                 * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
2349                                 * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
2350                                 */
2351                 if (dt!=OB_WIRE && draw_wire==2) {
2352                         bglPolygonOffset(1.0);
2353                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2354                 }
2355                 
2356                 dm->drawEdges(dm, (dt==OB_WIRE || totface==0));
2357                 
2358                 if (dt!=OB_WIRE && draw_wire==2) {
2359                         glDepthMask(1);
2360                         bglPolygonOffset(0.0);
2361                 }
2362         }
2363
2364         dm->release(dm);
2365 }
2366
2367 /* returns 1 if nothing was drawn, for detecting to draw an object center */
2368 static int draw_mesh_object(Scene *scene, View3D *v3d, Base *base, int dt, int flag)
2369 {
2370         Object *ob= base->object;
2371         Mesh *me= ob->data;
2372         int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha;
2373         
2374         if(G.obedit && ob!=G.obedit && ob->data==G.obedit->data) {
2375                 if(ob_get_key(ob));
2376                 else drawlinked= 1;
2377         }
2378         
2379         if(ob==G.obedit || drawlinked) {
2380                 DerivedMesh *finalDM, *cageDM;
2381                 
2382                 if (G.obedit!=ob)
2383                         finalDM = cageDM = editmesh_get_derived_base();
2384                 else
2385                         cageDM = editmesh_get_derived_cage_and_final(&finalDM,
2386                                                         get_viewedit_datamask());
2387
2388                 if(dt>OB_WIRE) {
2389                         // no transp in editmode, the fancy draw over goes bad then
2390                         glsl = draw_glsl_material(scene, ob, v3d, dt);
2391                         GPU_set_object_materials(scene, ob, glsl, NULL);
2392                 }
2393
2394                 draw_em_fancy(scene, v3d, ob, G.editMesh, cageDM, finalDM, dt);
2395
2396                 if (G.obedit!=ob && finalDM)
2397                         finalDM->release(finalDM);
2398         }
2399 //      else if(!G.obedit && (G.f & G_SCULPTMODE) &&(scene->sculptdata.flags & SCULPT_DRAW_FAST) &&
2400 //              OBACT==ob && !sculpt_modifiers_active(ob)) {
2401 // XXX          sculptmode_draw_mesh(0);
2402 //      }
2403         else {
2404                 /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */
2405                 if(me->totface<=4 || boundbox_clip(v3d, ob->obmat, (ob->bb)? ob->bb: me->bb)) {
2406                         glsl = draw_glsl_material(scene, ob, v3d, dt);
2407                         check_alpha = check_material_alpha(base, ob, glsl);
2408
2409                         if(dt==OB_SOLID || glsl) {
2410                                 GPU_set_object_materials(scene, ob, glsl,
2411                                         (check_alpha)? &do_alpha_pass: NULL);
2412                         }
2413
2414                         draw_mesh_fancy(scene, v3d, base, dt, flag);
2415                         
2416                         if(me->totvert==0) retval= 1;
2417                 }
2418         }
2419         
2420         /* GPU_set_object_materials checked if this is needed */
2421         if(do_alpha_pass) add_view3d_after(v3d, base, V3D_TRANSP, flag);
2422         
2423         return retval;
2424 }
2425
2426 /* ************** DRAW DISPLIST ****************** */
2427
2428 static int draw_index_wire= 1;
2429 static int index3_nors_incr= 1;
2430
2431 /* returns 1 when nothing was drawn */
2432 static int drawDispListwire(ListBase *dlbase)
2433 {
2434         DispList *dl;
2435         int parts, nr;
2436         float *data;
2437
2438         if(dlbase==NULL) return 1;
2439         
2440         glDisableClientState(GL_NORMAL_ARRAY);
2441         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2442
2443         for(dl= dlbase->first; dl; dl= dl->next) {
2444                 if(dl->parts==0 || dl->nr==0)
2445                         continue;
2446                 
2447                 data= dl->verts;
2448         
2449                 switch(dl->type) {
2450                 case DL_SEGM:
2451                         
2452                         glVertexPointer(3, GL_FLOAT, 0, data);
2453                         
2454                         for(parts=0; parts<dl->parts; parts++)
2455                                 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2456                                 
2457                         break;
2458                 case DL_POLY:
2459                         
2460                         glVertexPointer(3, GL_FLOAT, 0, data);
2461                         
2462                         for(parts=0; parts<dl->parts; parts++)
2463                                 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2464                         
2465                         break;
2466                 case DL_SURF:
2467                         
2468                         glVertexPointer(3, GL_FLOAT, 0, data);
2469                         
2470                         for(parts=0; parts<dl->parts; parts++) {
2471                                 if(dl->flag & DL_CYCL_U) 
2472                                         glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2473                                 else
2474                                         glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2475                         }
2476                         
2477                         for(nr=0; nr<dl->nr; nr++) {
2478                                 int ofs= 3*dl->nr;
2479                                 
2480                                 data= (  dl->verts )+3*nr;
2481                                 parts= dl->parts;
2482
2483                                 if(dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP);
2484                                 else glBegin(GL_LINE_STRIP);
2485                                 
2486                                 while(parts--) {
2487                                         glVertex3fv(data);
2488                                         data+=ofs;
2489                                 }
2490                                 glEnd();
2491                                 
2492                                 /* (ton) this code crashes for me when resolv is 86 or higher... no clue */
2493 //                              glVertexPointer(3, GL_FLOAT, sizeof(float)*3*dl->nr, data + 3*nr);
2494 //                              if(dl->flag & DL_CYCL_V) 
2495 //                                      glDrawArrays(GL_LINE_LOOP, 0, dl->parts);
2496 //                              else
2497 //                                      glDrawArrays(GL_LINE_STRIP, 0, dl->parts);
2498                         }
2499                         break;
2500                         
2501                 case DL_INDEX3:
2502                         if(draw_index_wire) {
2503                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2504                                 glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2505                         }
2506                         break;
2507                         
2508                 case DL_INDEX4:
2509                         if(draw_index_wire) {
2510                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2511                                 glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2512                         }
2513                         break;
2514                 }
2515         }
2516         
2517         glEnableClientState(GL_NORMAL_ARRAY);
2518         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 
2519         
2520         return 0;
2521 }
2522
2523 static void drawDispListsolid(ListBase *lb, Object *ob, int glsl)
2524 {
2525         DispList *dl;
2526         GPUVertexAttribs gattribs;
2527         float *data, curcol[4];
2528         float *ndata;
2529         
2530         if(lb==NULL) return;
2531         
2532         /* for drawing wire */
2533         glGetFloatv(GL_CURRENT_COLOR, curcol);
2534
2535         glEnable(GL_LIGHTING);
2536         
2537         if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
2538         else glFrontFace(GL_CCW);
2539         
2540         if(ob->type==OB_MBALL) {        // mball always smooth shaded
2541                 glShadeModel(GL_SMOOTH);
2542         }
2543         
2544         dl= lb->first;
2545         while(dl) {
2546                 data= dl->verts;
2547                 ndata= dl->nors;
2548
2549                 switch(dl->type) {
2550                 case DL_SEGM:
2551                         if(ob->type==OB_SURF) {
2552                                 int nr;
2553
2554                                 glDisable(GL_LIGHTING);
2555                                 glColor3fv(curcol);
2556                                 
2557                                 // glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2558                                 // glDrawArrays(GL_LINE_STRIP, 0, dl->nr);
2559
2560                                 glBegin(GL_LINE_STRIP);
2561                                 for(nr= dl->nr; nr; nr--, data+=3)
2562                                         glVertex3fv(data);
2563                                 glEnd();
2564
2565                                 glEnable(GL_LIGHTING);
2566                         }
2567                         break;
2568                 case DL_POLY:
2569                         if(ob->type==OB_SURF) {
2570                                 int nr;
2571                                 
2572                                 UI_ThemeColor(TH_WIRE);
2573                                 glDisable(GL_LIGHTING);
2574                                 
2575                                 /* for some reason glDrawArrays crashes here in half of the platforms (not osx) */
2576                                 //glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2577                                 //glDrawArrays(GL_LINE_LOOP, 0, dl->nr);
2578                                 
2579                                 glBegin(GL_LINE_LOOP);
2580                                 for(nr= dl->nr; nr; nr--, data+=3)
2581                                         glVertex3fv(data);
2582                                 glEnd();
2583                                 
2584                                 glEnable(GL_LIGHTING);
2585                                 break;
2586                         }
2587                 case DL_SURF:
2588                         
2589                         if(dl->index) {
2590                                 GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2591                                 
2592                                 if(dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH);
2593                                 else glShadeModel(GL_FLAT);
2594                                 
2595                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2596                                 glNormalPointer(GL_FLOAT, 0, dl->nors);
2597                                 glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
2598                                 GPU_disable_material();
2599                         }                       
2600                         break;
2601
2602                 case DL_INDEX3:
2603                         GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2604                         
2605                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2606                         
2607                         /* voor polys only one normal needed */
2608                         if(index3_nors_incr==0) {
2609                                 glDisableClientState(GL_NORMAL_ARRAY);
2610                                 glNormal3fv(ndata);
2611                         }
2612                         else
2613                                 glNormalPointer(GL_FLOAT, 0, dl->nors);
2614                         
2615                         glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2616                         GPU_disable_material();
2617                         
2618                         if(index3_nors_incr==0)
2619                                 glEnableClientState(GL_NORMAL_ARRAY);
2620
2621                         break;
2622
2623                 case DL_INDEX4:
2624                         GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2625                         
2626                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2627                         glNormalPointer(GL_FLOAT, 0, dl->nors);
2628                         glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2629
2630                         GPU_disable_material();
2631                         
2632                         break;
2633                 }
2634                 dl= dl->next;
2635         }
2636
2637         glShadeModel(GL_FLAT);
2638         glDisable(GL_LIGHTING);
2639         glFrontFace(GL_CCW);
2640 }
2641
2642 static void drawDispListshaded(ListBase *lb, Object *ob)
2643 {
2644         DispList *dl, *dlob;
2645         unsigned int *cdata;
2646
2647         if(lb==NULL) return;
2648
2649         glShadeModel(GL_SMOOTH);
2650         glDisableClientState(GL_NORMAL_ARRAY);
2651         glEnableClientState(GL_COLOR_ARRAY);
2652         
2653         dl= lb->first;
2654         dlob= ob->disp.first;
2655         while(dl && dlob) {
2656                 
2657                 cdata= dlob->col1;
2658                 if(cdata==NULL) break;
2659                 
2660                 switch(dl->type) {
2661                 case DL_SURF:
2662                         if(dl->index) {
2663                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2664                                 glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2665                                 glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
2666                         }                       
2667                         break;
2668
2669                 case DL_INDEX3:
2670                         
2671                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2672                         glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2673                         glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2674                         break;
2675
2676                 case DL_INDEX4:
2677                         
2678                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2679                         glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2680                         glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2681                         break;
2682                 }
2683                 
2684                 dl= dl->next;
2685                 dlob= dlob->next;
2686         }
2687         
2688         glShadeModel(GL_FLAT);
2689         glEnableClientState(GL_NORMAL_ARRAY);
2690         glDisableClientState(GL_COLOR_ARRAY);
2691 }
2692
2693 /* returns 1 when nothing was drawn */
2694 static int drawDispList(Scene *scene, View3D *v3d, Base *base, int dt)
2695 {
2696         Object *ob= base->object;
2697         ListBase *lb=0;
2698         DispList *dl;
2699         Curve *cu;
2700         int solid, retval= 0;
2701         
2702         solid= (dt > OB_WIRE);
2703
2704         switch(ob->type) {
2705         case OB_FONT:
2706         case OB_CURVE:
2707                 cu= ob->data;
2708                 
2709                 lb= &cu->disp;
2710                 
2711                 if(solid) {
2712                         dl= lb->first;
2713                         if(dl==NULL) return 1;
2714                         
2715                         if(dl->nors==0) addnormalsDispList(ob, lb);
2716                         index3_nors_incr= 0;
2717                         
2718                         if( displist_has_faces(lb)==0) {
2719                                 draw_index_wire= 0;
2720                                 drawDispListwire(lb);
2721                                 draw_index_wire= 1;
2722                         }
2723                         else {
2724                                 if(draw_glsl_material(scene, ob, v3d, dt)) {
2725                                         GPU_set_object_materials(scene, ob, 1, NULL);
2726                                         drawDispListsolid(lb, ob, 1);
2727                                 }
2728                                 else if(dt == OB_SHADED) {
2729                                         if(ob->disp.first==0) shadeDispList(base);
2730                                         drawDispListshaded(lb, ob);
2731                                 }
2732                                 else {
2733                                         GPU_set_object_materials(scene, ob, 0, NULL);
2734                                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2735                                         drawDispListsolid(lb, ob, 0);
2736                                 }
2737                                 if(ob==G.obedit && cu->bevobj==NULL && cu->taperobj==NULL && cu->ext1 == 0.0 && cu->ext2 == 0.0) {
2738                                         cpack(0);
2739                                         draw_index_wire= 0;
2740                                         drawDispListwire(lb);
2741                                         draw_index_wire= 1;
2742                                 }
2743                         }
2744                         index3_nors_incr= 1;
2745                 }
2746                 else {
2747                         draw_index_wire= 0;
2748                         retval= drawDispListwire(lb);
2749                         draw_index_wire= 1;
2750                 }
2751                 break;
2752         case OB_SURF:
2753         
2754                 lb= &((Curve *)ob->data)->disp;
2755                 
2756                 if(solid) {
2757                         dl= lb->first;
2758                         if(dl==NULL) return 1;
2759                         
2760                         if(dl->nors==NULL) addnormalsDispList(ob, lb);
2761                         
2762                         if(draw_glsl_material(scene, ob, v3d, dt)) {
2763                                 GPU_set_object_materials(scene, ob, 1, NULL);
2764                                 drawDispListsolid(lb, ob, 1);
2765                         }
2766                         else if(dt==OB_SHADED) {
2767                                 if(ob->disp.first==NULL) shadeDispList(base);
2768                                 drawDispListshaded(lb, ob);
2769                         }
2770                         else {
2771                                 GPU_set_object_materials(scene, ob, 0, NULL);
2772                                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2773                         
2774                                 drawDispListsolid(lb, ob, 0);
2775                         }
2776                 }
2777                 else {
2778                         retval= drawDispListwire(lb);
2779                 }
2780                 break;
2781         case OB_MBALL:
2782                 
2783                 if( is_basis_mball(ob)) {
2784                         lb= &ob->disp;
2785                         if(lb->first==NULL) makeDispListMBall(ob);
2786                         if(lb->first==NULL) return 1;
2787                         
2788                         if(solid) {
2789                                 
2790                                 if(draw_glsl_material(scene, ob, v3d, dt)) {
2791                                         GPU_set_object_materials(scene, ob, 1, NULL);
2792                                         drawDispListsolid(lb, ob, 1);
2793                                 }
2794                                 else if(dt == OB_SHADED) {
2795                                         dl= lb->first;
2796                                         if(dl && dl->col1==0) shadeDispList(base);
2797                                         drawDispListshaded(lb, ob);
2798                                 }
2799                                 else {
2800                                         GPU_set_object_materials(scene, ob, 0, NULL);
2801                                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2802                                 
2803                                         drawDispListsolid(lb, ob, 0);
2804                                 }
2805                         }
2806                         else{
2807                                 /* MetaBalls use DL_INDEX4 type of DispList */
2808                                 retval= drawDispListwire(lb);
2809                         }
2810                 }
2811                 break;
2812         }
2813         
2814         return retval;
2815 }
2816
2817 /* unified drawing of all new particle systems draw types except dupli ob & group       */
2818 /* mostly tries to use vertex arrays for speed                                                                          */
2819
2820 /* 1. check that everything is ok & updated */
2821 /* 2. start initialising things                         */
2822 /* 3. initialize according to draw type         */
2823 /* 4. allocate drawing data arrays                      */
2824 /* 5. start filling the arrays                          */
2825 /* 6. draw the arrays                                           */
2826 /* 7. clean up                                                          */
2827 static void draw_new_particle_system(View3D *v3d, Base *base, ParticleSystem *psys, int dt)
2828 {
2829         Object *ob=base->object;
2830         ParticleSystemModifierData *psmd;
2831         ParticleSettings *part;
2832         ParticleData *pars, *pa;
2833         ParticleKey state, *states=0;
2834         ParticleCacheKey *cache=0;
2835         Material *ma;
2836         Object *bb_ob=0;
2837         float vel[3], vec[3], vec2[3], imat[4][4], onevec[3]={0.0f,0.0f,0.0f}, bb_center[3];
2838         float timestep, pixsize=1.0, pa_size, pa_time, r_tilt;
2839         float cfra=bsystem_time(ob,(float)CFRA,0.0);
2840         float *vdata=0, *vedata=0, *cdata=0, *ndata=0, *vd=0, *ved=0, *cd=0, *nd=0, xvec[3], yvec[3], zvec[3];
2841         float ma_r=0.0f, ma_g=0.0f, ma_b=0.0f;
2842         int a, k, k_max=0, totpart, totpoint=0, draw_as, path_nbr=0;
2843         int path_possible=0, keys_possible=0, draw_keys=0, totchild=0;
2844         int select=ob->flag&SELECT, create_cdata=0;
2845         GLint polygonmode[2];
2846         char val[32];
2847
2848 /* 1. */
2849         if(psys==0)
2850                 return;
2851
2852         part=psys->part;
2853         pars=psys->particles;
2854
2855         if(part==0 || !psys_check_enabled(ob, psys))
2856                 return;
2857
2858         if(pars==0) return;
2859
2860         if(!G.obedit && psys_in_edit_mode(psys)
2861                 && psys->flag & PSYS_HAIR_DONE && part->draw_as==PART_DRAW_PATH)
2862                 return;
2863                 
2864         if(part->draw_as==PART_DRAW_NOT) return;
2865
2866 /* 2. */
2867         if(part->phystype==PART_PHYS_KEYED){
2868                 if(psys->flag & PSYS_FIRST_KEYED){
2869                         if(psys->flag&PSYS_KEYED){
2870                                 select=psys_count_keyed_targets(ob,psys);
2871                                 if(psys->totkeyed==0)
2872                                         return;
2873                         }
2874                 }
2875                 else
2876                         return;
2877         }
2878
2879         if(select){
2880                 select=0;
2881                 if(psys_get_current(ob)==psys)
2882                         select=1;
2883         }
2884
2885         psys->flag|=PSYS_DRAWING;
2886
2887         if(part->type==PART_HAIR && !psys->childcache)
2888                 totchild=0;
2889         else
2890                 totchild=psys->totchild*part->disp/100;
2891         
2892         ma= give_current_material(ob,part->omat);
2893
2894         if(ma) {
2895                 ma_r = ma->r;
2896                 ma_g = ma->g;
2897                 ma_b = ma->b;
2898         }
2899
2900         if(v3d->zbuf) glDepthMask(1);
2901
2902         if(select)
2903                 cpack(0xFFFFFF);
2904         else if((ma) && (part->draw&PART_DRAW_MAT_COL)) {
2905                 glColor3f(ma->r,ma->g,ma->b);
2906                 create_cdata = 1;
2907         }
2908         else
2909                 cpack(0);
2910
2911         psmd= psys_get_modifier(ob,psys);
2912
2913         timestep= psys_get_timestep(part);
2914
2915         wmLoadMatrix(v3d->viewmat);
2916
2917         if( (base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP) ) {
2918                 float mat[4][4];
2919                 Mat4MulMat4(mat, psys->imat, ob->obmat);
2920                 wmMultMatrix(mat);
2921         }
2922
2923         totpart=psys->totpart;
2924         draw_as=part->draw_as;
2925
2926         if(part->flag&PART_GLOB_TIME)
2927                 cfra=bsystem_time(0,(float)CFRA,0.0);
2928
2929         if(psys->pathcache){
2930                 path_possible=1;
2931                 keys_possible=1;
2932         }
2933         if(draw_as==PART_DRAW_PATH && path_possible==0)
2934                 draw_as=PART_DRAW_DOT;
2935
2936         if(draw_as!=PART_DRAW_PATH && keys_possible && part->draw&PART_DRAW_KEYS){
2937                 path_nbr=part->keys_step;
2938                 draw_keys=1;
2939         }
2940
2941 /* 3. */
2942         switch(draw_as){
2943                 case PART_DRAW_DOT:
2944                         if(part->draw_size)
2945                                 glPointSize(part->draw_size);
2946                         else
2947                                 glPointSize(2.0); /* default dot size */
2948                         break;
2949                 case PART_DRAW_CIRC:
2950                         /* calculate view aligned matrix: */
2951                         Mat4CpyMat4(imat, v3d->viewinv);
2952                         Normalize(imat[0]);
2953                         Normalize(imat[1]);
2954                         /* no break! */
2955                 case PART_DRAW_CROSS:
2956                 case PART_DRAW_AXIS:
2957                         /* lets calculate the scale: */
2958                         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];
2959                         pixsize*= v3d->pixsize;
2960                         if(part->draw_size==0.0)
2961                                 pixsize*=2.0;
2962                         else
2963                                 pixsize*=part->draw_size;
2964                         break;
2965                 case PART_DRAW_OB:
2966                         if(part->dup_ob==0)
2967                                 draw_as=PART_DRAW_DOT;
2968                         else
2969                                 draw_as=0;
2970                         break;
2971                 case PART_DRAW_GR:
2972                         if(part->dup_group==0)
2973                                 draw_as=PART_DRAW_DOT;
2974                         else
2975                                 draw_as=0;
2976                         break;
2977                 case PART_DRAW_BB:
2978                         if(v3d->camera==0 && part->bb_ob==0){
2979                                 printf("Billboards need an active camera or a target object!\n");
2980
2981                                 draw_as=part->draw_as=PART_DRAW_DOT;
2982
2983                                 if(part->draw_size)
2984                                         glPointSize(part->draw_size);
2985                                 else
2986                                         glPointSize(2.0); /* default dot size */
2987                         }
2988                         else if(part->bb_ob)
2989                                 bb_ob=part->bb_ob;
2990                         else
2991                                 bb_ob=v3d->camera;
2992
2993                         if(part->bb_align<PART_BB_VIEW)
2994                                 onevec[part->bb_align]=1.0f;
2995                         break;
2996                 case PART_DRAW_PATH:
2997                         break;
2998         }
2999         if(part->draw & PART_DRAW_SIZE && part->draw_as!=PART_DRAW_CIRC){
3000                 Mat4CpyMat4(imat, v3d->viewinv);
3001                 Normalize(imat[0]);
3002                 Normalize(imat[1]);
3003         }
3004
3005 /* 4. */
3006         if(draw_as && draw_as!=PART_DRAW_PATH){
3007                 if(draw_as!=PART_DRAW_CIRC){
3008                         switch(draw_as){
3009                                 case PART_DRAW_AXIS:
3010                                 case PART_DRAW_CROSS:
3011                                         if(draw_as!=PART_DRAW_CROSS || create_cdata)
3012                                                 cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*6*3*sizeof(float), "particle_cdata");
3013                                         vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*6*3*sizeof(float), "particle_vdata");
3014                                         break;
3015                                 case PART_DRAW_LINE:
3016                                         if(create_cdata)
3017                                                 cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*2*3*sizeof(float), "particle_cdata");
3018                                         vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*2*3*sizeof(float), "particle_vdata");
3019                                         break;
3020                                 case PART_DRAW_BB:
3021                                         if(create_cdata)
3022                                                 cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_cdata");
3023                                         vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_vdata");
3024                                         ndata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_vdata");
3025                                         break;
3026                                 default:
3027                                         if(create_cdata)
3028                                                 cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*3*sizeof(float), "particle_cdata");
3029                                         vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*3*sizeof(float), "particle_vdata");
3030                         }
3031                 }
3032
3033                 if(part->draw&PART_DRAW_VEL && draw_as!=PART_DRAW_LINE)
3034                         vedata=MEM_callocN((totpart+totchild)*2*3*(path_nbr+1)*sizeof(float), "particle_vedata");
3035
3036                 vd=vdata;
3037                 ved=vedata;
3038                 cd=cdata;
3039                 nd=ndata;
3040
3041                 psys->lattice=psys_get_lattice(ob,psys);
3042         }
3043
3044         if(draw_as){
3045 /* 5. */
3046                 for(a=0,pa=pars; a<totpart+totchild; a++, pa++){
3047                         if(a<totpart){