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