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