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