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