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