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