soc-2008-mxcurioni: implemented (without testing) StrokeShader, Stroke and MediumType...
[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         float v1[3], v2[3], v3[3], v4[3];
1887         float fvec[3];
1888         char val[32]; /* Stores the measurement display text here */
1889         char conv_float[5]; /* Use a float conversion matching the grid size */
1890         float area, col[3]; /* area of the face,  color of the text to draw */
1891         
1892         /* make the precission of the pronted value proportionate to the gridsize */
1893         if ((G.vd->grid) < 0.01)
1894                 strcpy(conv_float, "%.6f");
1895         else if ((G.vd->grid) < 0.1)
1896                 strcpy(conv_float, "%.5f");
1897         else if ((G.vd->grid) < 1.0)
1898                 strcpy(conv_float, "%.4f");
1899         else if ((G.vd->grid) < 10.0)
1900                 strcpy(conv_float, "%.3f");
1901         else
1902                 strcpy(conv_float, "%.2f");
1903         
1904         
1905         if(G.vd->zbuf && (G.vd->flag & V3D_ZBUF_SELECT)==0)
1906                 glDisable(GL_DEPTH_TEST);
1907
1908         if(G.vd->zbuf) bglPolygonOffset(5.0);
1909         
1910         if(G.f & G_DRAW_EDGELEN) {
1911                 BIF_GetThemeColor3fv(TH_TEXT, col);
1912                 /* make color a bit more red */
1913                 if(col[0]> 0.5) {col[1]*=0.7; col[2]*= 0.7;}
1914                 else col[0]= col[0]*0.7 + 0.3;
1915                 glColor3fv(col);
1916                 
1917                 for(eed= em->edges.first; eed; eed= eed->next) {
1918                         /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
1919                         if((eed->h != EM_FGON) && ((eed->f & SELECT) || (G.moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
1920                                 VECCOPY(v1, eed->v1->co);
1921                                 VECCOPY(v2, eed->v2->co);
1922                                 
1923                                 glRasterPos3f( 0.5*(v1[0]+v2[0]),  0.5*(v1[1]+v2[1]),  0.5*(v1[2]+v2[2]));
1924                                 
1925                                 if(G.vd->flag & V3D_GLOBAL_STATS) {
1926                                         Mat4MulVecfl(ob->obmat, v1);
1927                                         Mat4MulVecfl(ob->obmat, v2);
1928                                 }
1929                                 
1930                                 sprintf(val, conv_float, VecLenf(v1, v2));
1931                                 BMF_DrawString( G.fonts, val);
1932                         }
1933                 }
1934         }
1935
1936         if(G.f & G_DRAW_FACEAREA) {
1937                 extern int faceselectedOR(EditFace *efa, int flag);             // editmesh.h shouldn't be in this file... ok for now?
1938                 
1939                 BIF_GetThemeColor3fv(TH_TEXT, col);
1940                 /* make color a bit more green */
1941                 if(col[1]> 0.5) {col[0]*=0.7; col[2]*= 0.7;}
1942                 else col[1]= col[1]*0.7 + 0.3;
1943                 glColor3fv(col);
1944                 
1945                 for(efa= em->faces.first; efa; efa= efa->next) {
1946                         if((efa->f & SELECT) || (G.moving && faceselectedOR(efa, SELECT)) ) {
1947                                 VECCOPY(v1, efa->v1->co);
1948                                 VECCOPY(v2, efa->v2->co);
1949                                 VECCOPY(v3, efa->v3->co);
1950                                 if (efa->v4) {
1951                                         VECCOPY(v4, efa->v4->co);
1952                                 }
1953                                 if(G.vd->flag & V3D_GLOBAL_STATS) {
1954                                         Mat4MulVecfl(ob->obmat, v1);
1955                                         Mat4MulVecfl(ob->obmat, v2);
1956                                         Mat4MulVecfl(ob->obmat, v3);
1957                                         if (efa->v4) Mat4MulVecfl(ob->obmat, v4);
1958                                 }
1959                                 
1960                                 if (efa->v4)
1961                                         area=  AreaQ3Dfl(v1, v2, v3, v4);
1962                                 else
1963                                         area = AreaT3Dfl(v1, v2, v3);
1964
1965                                 sprintf(val, conv_float, area);
1966                                 glRasterPos3fv(efa->cent);
1967                                 BMF_DrawString( G.fonts, val);
1968                         }
1969                 }
1970         }
1971
1972         if(G.f & G_DRAW_EDGEANG) {
1973                 EditEdge *e1, *e2, *e3, *e4;
1974                 
1975                 BIF_GetThemeColor3fv(TH_TEXT, col);
1976                 /* make color a bit more blue */
1977                 if(col[2]> 0.5) {col[0]*=0.7; col[1]*= 0.7;}
1978                 else col[2]= col[2]*0.7 + 0.3;
1979                 glColor3fv(col);
1980                 
1981                 for(efa= em->faces.first; efa; efa= efa->next) {
1982                         VECCOPY(v1, efa->v1->co);
1983                         VECCOPY(v2, efa->v2->co);
1984                         VECCOPY(v3, efa->v3->co);
1985                         if(efa->v4) {
1986                                 VECCOPY(v4, efa->v4->co); 
1987                         }
1988                         else {
1989                                 VECCOPY(v4, v3);
1990                         }
1991                         if(G.vd->flag & V3D_GLOBAL_STATS) {
1992                                 Mat4MulVecfl(ob->obmat, v1);
1993                                 Mat4MulVecfl(ob->obmat, v2);
1994                                 Mat4MulVecfl(ob->obmat, v3);
1995                                 Mat4MulVecfl(ob->obmat, v4);
1996                         }
1997                         
1998                         e1= efa->e1;
1999                         e2= efa->e2;
2000                         e3= efa->e3;
2001                         if(efa->e4) e4= efa->e4; else e4= e3;
2002                         
2003                         /* Calculate the angles */
2004                                 
2005                         if( (e4->f & e1->f & SELECT) || (G.moving && (efa->v1->f & SELECT)) ) {
2006                                 /* Vec 1 */
2007                                 sprintf(val,"%.3f", VecAngle3(v4, v1, v2));
2008                                 VecLerpf(fvec, efa->cent, efa->v1->co, 0.8);
2009                                 glRasterPos3fv(fvec);
2010                                 BMF_DrawString( G.fonts, val);
2011                         }
2012                         if( (e1->f & e2->f & SELECT) || (G.moving && (efa->v2->f & SELECT)) ) {
2013                                 /* Vec 2 */
2014                                 sprintf(val,"%.3f", VecAngle3(v1, v2, v3));
2015                                 VecLerpf(fvec, efa->cent, efa->v2->co, 0.8);
2016                                 glRasterPos3fv(fvec);
2017                                 BMF_DrawString( G.fonts, val);
2018                         }
2019                         if( (e2->f & e3->f & SELECT) || (G.moving && (efa->v3->f & SELECT)) ) {
2020                                 /* Vec 3 */
2021                                 if(efa->v4) 
2022                                         sprintf(val,"%.3f", VecAngle3(v2, v3, v4));
2023                                 else
2024                                         sprintf(val,"%.3f", VecAngle3(v2, v3, v1));
2025                                 VecLerpf(fvec, efa->cent, efa->v3->co, 0.8);
2026                                 glRasterPos3fv(fvec);
2027                                 BMF_DrawString( G.fonts, val);
2028                         }
2029                                 /* Vec 4 */
2030                         if(efa->v4) {
2031                                 if( (e3->f & e4->f & SELECT) || (G.moving && (efa->v4->f & SELECT)) ) {
2032                                         sprintf(val,"%.3f", VecAngle3(v3, v4, v1));
2033                                         VecLerpf(fvec, efa->cent, efa->v4->co, 0.8);
2034                                         glRasterPos3fv(fvec);
2035                                         BMF_DrawString( G.fonts, val);
2036                                 }
2037                         }
2038                 }
2039         }    
2040         
2041         if(G.vd->zbuf) {
2042                 glEnable(GL_DEPTH_TEST);
2043                 bglPolygonOffset(0.0);
2044         }
2045 }
2046
2047 static int draw_em_fancy__setFaceOpts(void *userData, int index, int *drawSmooth_r)
2048 {
2049         EditFace *efa = EM_get_face_for_index(index);
2050
2051         if (efa->h==0) {
2052                 set_gl_material(efa->mat_nr+1);
2053                 return 1;
2054         } else {
2055                 return 0;
2056         }
2057 }
2058 static void draw_em_fancy(Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2059 {
2060         Mesh *me = ob->data;
2061         EditFace *efa_act = EM_get_actFace(0); /* annoying but active faces is stored differently */
2062         EditEdge *eed_act = NULL;
2063         EditVert *eve_act = NULL;
2064         
2065         if (G.editMesh->selected.last) {
2066                 EditSelection *ese = G.editMesh->selected.last;
2067                 /* face is handeled above */
2068                 /*if (ese->type == EDITFACE ) {
2069                         efa_act = (EditFace *)ese->data;
2070                 } else */ if ( ese->type == EDITEDGE ) {
2071                         eed_act = (EditEdge *)ese->data;
2072                 } else if ( ese->type == EDITVERT ) {
2073                         eve_act = (EditVert *)ese->data;
2074                 }
2075         }
2076         
2077         EM_init_index_arrays(1, 1, 1);
2078
2079         if(dt>OB_WIRE) {
2080                 if( CHECK_OB_DRAWTEXTURE(G.vd, dt) ) {
2081                         draw_mesh_textured(ob, finalDM, 0);
2082                 } else {
2083                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2084
2085                         glEnable(GL_LIGHTING);
2086                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2087
2088                         finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, 0, 0);
2089
2090                         glFrontFace(GL_CCW);
2091                         glDisable(GL_LIGHTING);
2092                 }
2093                         
2094                 // Setup for drawing wire over, disable zbuffer
2095                 // write to show selected edge wires better
2096                 BIF_ThemeColor(TH_WIRE);
2097
2098                 bglPolygonOffset(1.0);
2099                 glDepthMask(0);
2100         } 
2101         else {
2102                 if (cageDM!=finalDM) {
2103                         BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2104                         finalDM->drawEdges(finalDM, 1);
2105                 }
2106         }
2107         
2108         if((G.f & (G_DRAWFACES)) || FACESEL_PAINT_TEST) {       /* transp faces */
2109                 unsigned char col1[4], col2[4], col3[4];
2110                         
2111                 BIF_GetThemeColor4ubv(TH_FACE, (char *)col1);
2112                 BIF_GetThemeColor4ubv(TH_FACE_SELECT, (char *)col2);
2113                 BIF_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2114                 
2115                 glEnable(GL_BLEND);
2116                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2117                 
2118                 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2119                 if CHECK_OB_DRAWTEXTURE(G.vd, dt)
2120                         col1[3] = 0;
2121                 
2122                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2123
2124                 glDisable(GL_BLEND);
2125                 glDepthMask(1);         // restore write in zbuffer
2126         } else if (efa_act) {
2127                 /* even if draw faces is off it would be nice to draw the stipple face
2128                  * Make all other faces zero alpha except for the active
2129                  * */
2130                 unsigned char col1[4], col2[4], col3[4];
2131                 col1[3] = col2[3] = 0; /* dont draw */
2132                 BIF_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2133                 
2134                 glEnable(GL_BLEND);
2135                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2136                 
2137                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2138
2139                 glDisable(GL_BLEND);
2140                 glDepthMask(1);         // restore write in zbuffer
2141                 
2142         }
2143
2144         /* here starts all fancy draw-extra over */
2145         if((G.f & G_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(G.vd, dt)) {
2146                 /* we are drawing textures and 'G_DRAWEDGES' is disabled, dont draw any edges */
2147                 
2148                 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2149                 draw_em_fancy_edges(cageDM, 1, eed_act);
2150                 
2151         } else {
2152                 if(G.f & G_DRAWSEAMS) {
2153                         BIF_ThemeColor(TH_EDGE_SEAM);
2154                         glLineWidth(2);
2155         
2156                         draw_dm_edges_seams(cageDM);
2157         
2158                         glColor3ub(0,0,0);
2159                         glLineWidth(1);
2160                 }
2161                 
2162                 if(G.f & G_DRAWSHARP) {
2163                         BIF_ThemeColor(TH_EDGE_SHARP);
2164                         glLineWidth(2);
2165         
2166                         draw_dm_edges_sharp(cageDM);
2167         
2168                         glColor3ub(0,0,0);
2169                         glLineWidth(1);
2170                 }
2171         
2172                 if(G.f & G_DRAWCREASES) {
2173                         draw_dm_creases(cageDM);
2174                 }
2175                 if(G.f & G_DRAWBWEIGHTS) {
2176                         draw_dm_bweights(cageDM);
2177                 }
2178         
2179                 draw_em_fancy_edges(cageDM, 0, eed_act);
2180         }
2181         if(ob==G.obedit) {
2182                 retopo_matrix_update(G.vd);
2183
2184                 draw_em_fancy_verts(em, cageDM, eve_act);
2185
2186                 if(G.f & G_DRAWNORMALS) {
2187                         BIF_ThemeColor(TH_NORMAL);
2188                         draw_dm_face_normals(cageDM);
2189                 }
2190                 if(G.f & G_DRAW_VNORMALS) {
2191                         BIF_ThemeColor(TH_NORMAL);
2192                         draw_dm_vert_normals(cageDM);
2193                 }
2194
2195                 if(G.f & (G_DRAW_EDGELEN|G_DRAW_FACEAREA|G_DRAW_EDGEANG))
2196                         draw_em_measure_stats(ob, em);
2197 #ifdef WITH_VERSE
2198                 if(em->vnode && (G.f & G_DRAW_VERSE_DEBUG))
2199                         draw_verse_debug(ob, em);
2200 #endif
2201         }
2202
2203         if(dt>OB_WIRE) {
2204                 glDepthMask(1);
2205                 bglPolygonOffset(0.0);
2206         }
2207
2208         EM_free_index_arrays();
2209 }
2210
2211 /* Mesh drawing routines */
2212
2213 static void draw_mesh_object_outline(Object *ob, DerivedMesh *dm)
2214 {
2215         
2216         if(G.vd->transp==0) {   // not when we draw the transparent pass
2217                 glLineWidth(2.0);
2218                 glDepthMask(0);
2219                 
2220                 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2221                    drawFacesSolid() doesn't draw the transparent faces */
2222                 if(ob->dtx & OB_DRAWTRANSP) {
2223                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2224                         dm->drawFacesSolid(dm, set_gl_material);
2225                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2226                 }
2227                 else {
2228                         dm->drawEdges(dm, 0);
2229                 }
2230                                         
2231                 glLineWidth(1.0);
2232                 glDepthMask(1);
2233         }
2234 }
2235
2236 static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
2237 {
2238         *drawSmooth_r = 1;
2239         return 1;
2240 }
2241
2242 static void draw_mesh_fancy(Base *base, int dt, int flag)
2243 {
2244         Object *ob= base->object;
2245         Mesh *me = ob->data;
2246         Material *ma= give_current_material(ob, 1);
2247         int hasHaloMat = (ma && (ma->mode&MA_HALO));
2248         int draw_wire = 0;
2249         int totvert, totedge, totface;
2250         DispList *dl;
2251         DerivedMesh *dm= mesh_get_derived_final(ob, get_viewedit_datamask());
2252
2253         if(!dm)
2254                 return;
2255         
2256         if (ob->dtx&OB_DRAWWIRE) {
2257                 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
2258         }
2259         
2260 #ifdef WITH_VERSE
2261         if(me->vnode) {
2262                 struct VNode *vnode = (VNode*)me->vnode;
2263                 struct VLayer *vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
2264                 struct VLayer *face_vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
2265
2266                 if(vert_vlayer) totvert = vert_vlayer->dl.da.count;
2267                 else totvert = 0;
2268                 totedge = 0;    /* total count of edge needn't to be zero, but verse doesn't know edges */
2269                 if(face_vlayer) totface = face_vlayer->dl.da.count;
2270                 else totface = 0;
2271         }
2272         else {
2273                 totvert = dm->getNumVerts(dm);
2274                 totedge = dm->getNumEdges(dm);
2275                 totface = dm->getNumFaces(dm);
2276         }
2277 #else
2278         totvert = dm->getNumVerts(dm);
2279         totedge = dm->getNumEdges(dm);
2280         totface = dm->getNumFaces(dm);
2281 #endif
2282         
2283         /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2284         if(dt!=OB_SHADED)
2285                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2286
2287                 // Unwanted combination.
2288         if (ob==OBACT && FACESEL_PAINT_TEST) draw_wire = 0;
2289
2290         if(dt==OB_BOUNDBOX) {
2291                 draw_bounding_volume(ob);
2292         }
2293         else if(hasHaloMat || (totface==0 && totedge==0)) {
2294                 glPointSize(1.5);
2295                 dm->drawVerts(dm);
2296                 glPointSize(1.0);
2297         }
2298         else if(dt==OB_WIRE || totface==0) {
2299                 draw_wire = 1; /* draw wire only, no depth buffer stuff  */
2300         }
2301         else if(        (ob==OBACT && (G.f & G_TEXTUREPAINT || FACESEL_PAINT_TEST)) ||
2302                                 CHECK_OB_DRAWTEXTURE(G.vd, dt))
2303         {
2304                 int faceselect= (ob==OBACT && FACESEL_PAINT_TEST);
2305
2306                 if ((G.vd->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !(G.f&G_PICKSEL || FACESEL_PAINT_TEST) && !draw_wire) {
2307                         draw_mesh_object_outline(ob, dm);
2308                 }
2309
2310                 draw_mesh_textured(ob, dm, faceselect);
2311
2312                 if(!faceselect) {
2313                         if(base->flag & SELECT)
2314                                 BIF_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2315                         else
2316                                 BIF_ThemeColor(TH_WIRE);
2317
2318                         dm->drawLooseEdges(dm);
2319                 }
2320         }
2321         else if(dt==OB_SOLID ) {
2322                 
2323                 if ((G.vd->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) {
2324                         draw_mesh_object_outline(ob, dm);
2325                 }
2326
2327                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
2328
2329                 glEnable(GL_LIGHTING);
2330                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2331
2332                 dm->drawFacesSolid(dm, set_gl_material);
2333
2334                 glFrontFace(GL_CCW);
2335                 glDisable(GL_LIGHTING);
2336
2337                 if(base->flag & SELECT) {
2338                         BIF_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2339                 } else {
2340                         BIF_ThemeColor(TH_WIRE);
2341                 }
2342                 dm->drawLooseEdges(dm);
2343         }
2344         else if(dt==OB_SHADED) {
2345                 int do_draw= 1; /* to resolve all G.f settings below... */
2346                 
2347                 if(ob==OBACT) {
2348                         do_draw= 0;
2349                         if( (G.f & G_WEIGHTPAINT)) {
2350                                 set_gl_material(0);             /* enforce defmaterial settings */
2351                                 
2352                                 /* but set default spec */
2353                                 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
2354                                 glEnable(GL_COLOR_MATERIAL);    /* according manpages needed */
2355                                 glColor3ub(120, 120, 120);
2356                                 glDisable(GL_COLOR_MATERIAL);
2357                                 /* diffuse */
2358                                 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2359                                 glEnable(GL_LIGHTING);
2360                                 glEnable(GL_COLOR_MATERIAL);
2361
2362                                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1);
2363                                 glDisable(GL_COLOR_MATERIAL);
2364                                 glDisable(GL_LIGHTING);
2365                         }
2366                         else if((G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) && me->mcol) {
2367                                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1);
2368                         }
2369                         else if(G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) {
2370                                 glColor3f(1.0f, 1.0f, 1.0f);
2371                                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0);
2372                         }
2373                         else do_draw= 1;
2374                 }
2375                 if(do_draw) {
2376                         dl = ob->disp.first;
2377                         if (!dl || !dl->col1) {
2378                                 /* release and reload derivedmesh because it might be freed in
2379                                    shadeDispList due to a different datamask */
2380                                 dm->release(dm);
2381                                 shadeDispList(base);
2382                                 dl = find_displist(&ob->disp, DL_VERTCOL);
2383                             dm= mesh_get_derived_final(ob, get_viewedit_datamask());
2384                         }
2385
2386                         if ((G.vd->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) {
2387                                 draw_mesh_object_outline(ob, dm);
2388                         }
2389
2390                                 /* False for dupliframe objects */
2391                         if (dl) {
2392                                 unsigned int *obCol1 = dl->col1;
2393                                 unsigned int *obCol2 = dl->col2;
2394
2395                                 dm->drawFacesColored(dm, me->flag&ME_TWOSIDED, (unsigned char*) obCol1, (unsigned char*) obCol2);
2396                         }
2397
2398                         if(base->flag & SELECT) {
2399                                 BIF_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2400                         } else {
2401                                 BIF_ThemeColor(TH_WIRE);
2402                         }
2403                         dm->drawLooseEdges(dm);
2404                 }
2405         }
2406         
2407         /* set default draw color back for wire or for draw-extra later on */
2408         if (dt!=OB_WIRE) {
2409                 if(base->flag & SELECT) {
2410                         if(ob==OBACT && ob->flag & OB_FROMGROUP) 
2411                                 BIF_ThemeColor(TH_GROUP_ACTIVE);
2412                         else if(ob->flag & OB_FROMGROUP) 
2413                                 BIF_ThemeColorShade(TH_GROUP_ACTIVE, -16);
2414                         else if(flag!=DRAW_CONSTCOLOR)
2415                                 BIF_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2416                         else
2417                                 glColor3ub(80,80,80);
2418                 } else {
2419                         if (ob->flag & OB_FROMGROUP) 
2420                                 BIF_ThemeColor(TH_GROUP);
2421                         else {
2422                                 if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
2423                                         glColor3ub(80,80,80);
2424                                 else
2425                                         BIF_ThemeColor(TH_WIRE);
2426                         }
2427                 }
2428         }
2429         if (draw_wire) {
2430                         /* If drawing wire and drawtype is not OB_WIRE then we are
2431                                 * overlaying the wires.
2432                                 *
2433                                 * UPDATE bug #10290 - With this wire-only objects can draw
2434                                 * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
2435                                 * 
2436                                 * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
2437                                 * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
2438                                 */
2439                 if (dt!=OB_WIRE && draw_wire==2) {
2440                         bglPolygonOffset(1.0);
2441                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2442                 }
2443                 
2444                 dm->drawEdges(dm, (dt==OB_WIRE || totface==0));
2445                 
2446                 if (dt!=OB_WIRE && draw_wire==2) {
2447                         glDepthMask(1);
2448                         bglPolygonOffset(0.0);
2449                 }
2450         }
2451
2452         dm->release(dm);
2453 }
2454
2455 /* returns 1 if nothing was drawn, for detecting to draw an object center */
2456 static int draw_mesh_object(Base *base, int dt, int flag)
2457 {
2458         Object *ob= base->object;
2459         Mesh *me= ob->data;
2460         int has_alpha= 0, drawlinked= 0, retval= 0;
2461         
2462         if(G.obedit && ob!=G.obedit && ob->data==G.obedit->data) {
2463                 if(ob_get_key(ob));
2464                 else drawlinked= 1;
2465         }
2466         
2467         if(ob==G.obedit || drawlinked) {
2468                 DerivedMesh *finalDM, *cageDM;
2469                 
2470                 if (G.obedit!=ob)
2471                         finalDM = cageDM = editmesh_get_derived_base();
2472                 else
2473                         cageDM = editmesh_get_derived_cage_and_final(&finalDM,
2474                                                         get_viewedit_datamask());
2475
2476                 if(dt>OB_WIRE) init_gl_materials(ob, 0);        // no transp in editmode, the fancy draw over goes bad then
2477                 draw_em_fancy(ob, G.editMesh, cageDM, finalDM, dt);
2478
2479                 if (G.obedit!=ob && finalDM)
2480                         finalDM->release(finalDM);
2481         }
2482         else if(!G.obedit && (G.f & G_SCULPTMODE) &&(G.scene->sculptdata.flags & SCULPT_DRAW_FAST) &&
2483                 OBACT==ob && !sculpt_modifiers_active(ob)) {
2484                 sculptmode_draw_mesh(0);
2485         }
2486         else {
2487                 /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */
2488                 if(me->totface<=4 || boundbox_clip(ob->obmat, (ob->bb)? ob->bb: me->bb)) {
2489                         if(dt==OB_SOLID) has_alpha= init_gl_materials(ob, (base->flag & OB_FROMDUPLI)==0);
2490                         draw_mesh_fancy(base, dt, flag);
2491                         
2492                         if(me->totvert==0) retval= 1;
2493                 }
2494         }
2495         
2496         /* init_gl_materials did the proper checking if this is needed */
2497         if(has_alpha) add_view3d_after(G.vd, base, V3D_TRANSP, flag);
2498         
2499         return retval;
2500 }
2501
2502 /* ************** DRAW DISPLIST ****************** */
2503
2504 static int draw_index_wire= 1;
2505 static int index3_nors_incr= 1;
2506
2507 /* returns 1 when nothing was drawn */
2508 static int drawDispListwire(ListBase *dlbase)
2509 {
2510         DispList *dl;
2511         int parts, nr;
2512         float *data;
2513
2514         if(dlbase==NULL) return 1;
2515         
2516         glDisableClientState(GL_NORMAL_ARRAY);
2517         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2518
2519         for(dl= dlbase->first; dl; dl= dl->next) {
2520                 if(dl->parts==0 || dl->nr==0)
2521                         continue;
2522                 
2523                 data= dl->verts;
2524         
2525                 switch(dl->type) {
2526                 case DL_SEGM:
2527                         
2528                         glVertexPointer(3, GL_FLOAT, 0, data);
2529                         
2530                         for(parts=0; parts<dl->parts; parts++)
2531                                 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2532                                 
2533                         break;
2534                 case DL_POLY:
2535                         
2536                         glVertexPointer(3, GL_FLOAT, 0, data);
2537                         
2538                         for(parts=0; parts<dl->parts; parts++)
2539                                 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2540                         
2541                         break;
2542                 case DL_SURF:
2543                         
2544                         glVertexPointer(3, GL_FLOAT, 0, data);
2545                         
2546                         for(parts=0; parts<dl->parts; parts++) {
2547                                 if(dl->flag & DL_CYCL_U) 
2548                                         glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2549                                 else
2550                                         glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2551                         }
2552                         
2553                         for(nr=0; nr<dl->nr; nr++) {
2554                                 int ofs= 3*dl->nr;
2555                                 
2556                                 data= (  dl->verts )+3*nr;
2557                                 parts= dl->parts;
2558
2559                                 if(dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP);
2560                                 else glBegin(GL_LINE_STRIP);
2561                                 
2562                                 while(parts--) {
2563                                         glVertex3fv(data);
2564                                         data+=ofs;
2565                                 }
2566                                 glEnd();
2567                                 
2568                                 /* (ton) this code crashes for me when resolv is 86 or higher... no clue */
2569 //                              glVertexPointer(3, GL_FLOAT, sizeof(float)*3*dl->nr, data + 3*nr);
2570 //                              if(dl->flag & DL_CYCL_V) 
2571 //                                      glDrawArrays(GL_LINE_LOOP, 0, dl->parts);
2572 //                              else
2573 //                                      glDrawArrays(GL_LINE_STRIP, 0, dl->parts);
2574                         }
2575                         break;
2576                         
2577                 case DL_INDEX3:
2578                         if(draw_index_wire) {
2579                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2580                                 glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2581                         }
2582                         break;
2583                         
2584                 case DL_INDEX4:
2585                         if(draw_index_wire) {
2586                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2587                                 glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2588                         }
2589                         break;
2590                 }
2591         }
2592         
2593         glEnableClientState(GL_NORMAL_ARRAY);
2594         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 
2595         
2596         return 0;
2597 }
2598
2599 static void drawDispListsolid(ListBase *lb, Object *ob)
2600 {
2601         DispList *dl;
2602         float *data, curcol[4];
2603         float *ndata;
2604         
2605         if(lb==NULL) return;
2606         
2607         /* for drawing wire */
2608         glGetFloatv(GL_CURRENT_COLOR, curcol);
2609
2610         glEnable(GL_LIGHTING);
2611         
2612         if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
2613         else glFrontFace(GL_CCW);
2614         
2615         if(ob->type==OB_MBALL) {        // mball always smooth shaded
2616                 glShadeModel(GL_SMOOTH);
2617         }
2618         
2619         dl= lb->first;
2620         while(dl) {
2621                 data= dl->verts;
2622                 ndata= dl->nors;
2623
2624                 switch(dl->type) {
2625                 case DL_SEGM:
2626                         if(ob->type==OB_SURF) {
2627                                 int nr;
2628
2629                                 glDisable(GL_LIGHTING);
2630                                 glColor3fv(curcol);
2631                                 
2632                                 // glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2633                                 // glDrawArrays(GL_LINE_STRIP, 0, dl->nr);
2634
2635                                 glBegin(GL_LINE_STRIP);
2636                                 for(nr= dl->nr; nr; nr--, data+=3)
2637                                         glVertex3fv(data);
2638                                 glEnd();
2639
2640                                 glEnable(GL_LIGHTING);
2641                         }
2642                         break;
2643                 case DL_POLY:
2644                         if(ob->type==OB_SURF) {
2645                                 int nr;
2646                                 
2647                                 BIF_ThemeColor(TH_WIRE);
2648                                 glDisable(GL_LIGHTING);
2649                                 
2650                                 /* for some reason glDrawArrays crashes here in half of the platforms (not osx) */
2651                                 //glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2652                                 //glDrawArrays(GL_LINE_LOOP, 0, dl->nr);
2653                                 
2654                                 glBegin(GL_LINE_LOOP);
2655                                 for(nr= dl->nr; nr; nr--, data+=3)
2656                                         glVertex3fv(data);
2657                                 glEnd();
2658                                 
2659                                 glEnable(GL_LIGHTING);
2660                                 break;
2661                         }
2662                 case DL_SURF:
2663                         
2664                         if(dl->index) {
2665                                 set_gl_material(dl->col+1);
2666                                 
2667                                 if(dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH);
2668                                 else glShadeModel(GL_FLAT);
2669                                 
2670                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2671                                 glNormalPointer(GL_FLOAT, 0, dl->nors);
2672                                 glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
2673                         }                       
2674                         break;
2675
2676                 case DL_INDEX3:
2677                 
2678                         set_gl_material(dl->col+1);
2679                         
2680                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2681                         
2682                         /* voor polys only one normal needed */
2683                         if(index3_nors_incr==0) {
2684                                 glDisableClientState(GL_NORMAL_ARRAY);
2685                                 glNormal3fv(ndata);
2686                         }
2687                         else
2688                                 glNormalPointer(GL_FLOAT, 0, dl->nors);
2689                         
2690                         glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2691                         
2692                         if(index3_nors_incr==0)
2693                                 glEnableClientState(GL_NORMAL_ARRAY);
2694
2695                         break;
2696
2697                 case DL_INDEX4:
2698
2699                         set_gl_material(dl->col+1);
2700                         
2701                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2702                         glNormalPointer(GL_FLOAT, 0, dl->nors);
2703                         glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2704                         
2705                         break;
2706                 }
2707                 dl= dl->next;
2708         }
2709
2710         glShadeModel(GL_FLAT);
2711         glDisable(GL_LIGHTING);
2712         glFrontFace(GL_CCW);
2713 }
2714
2715 static void drawDispListshaded(ListBase *lb, Object *ob)
2716 {
2717         DispList *dl, *dlob;
2718         unsigned int *cdata;
2719
2720         if(lb==NULL) return;
2721
2722         glShadeModel(GL_SMOOTH);
2723         glDisableClientState(GL_NORMAL_ARRAY);
2724         glEnableClientState(GL_COLOR_ARRAY);
2725         
2726         dl= lb->first;
2727         dlob= ob->disp.first;
2728         while(dl && dlob) {
2729                 
2730                 cdata= dlob->col1;
2731                 if(cdata==NULL) break;
2732                 
2733                 switch(dl->type) {
2734                 case DL_SURF:
2735                         if(dl->index) {
2736                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2737                                 glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2738                                 glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
2739                         }                       
2740                         break;
2741
2742                 case DL_INDEX3:
2743                         
2744                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2745                         glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2746                         glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2747                         break;
2748
2749                 case DL_INDEX4:
2750                         
2751                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2752                         glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2753                         glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2754                         break;
2755                 }
2756                 
2757                 dl= dl->next;
2758                 dlob= dlob->next;
2759         }
2760         
2761         glShadeModel(GL_FLAT);
2762         glEnableClientState(GL_NORMAL_ARRAY);
2763         glDisableClientState(GL_COLOR_ARRAY);
2764 }
2765
2766 /* returns 1 when nothing was drawn */
2767 static int drawDispList(Base *base, int dt)
2768 {
2769         Object *ob= base->object;
2770         ListBase *lb=0;
2771         DispList *dl;
2772         Curve *cu;
2773         int solid, retval= 0;
2774         
2775         solid= (dt > OB_WIRE);
2776
2777         switch(ob->type) {
2778         case OB_FONT:
2779         case OB_CURVE:
2780                 cu= ob->data;
2781                 
2782                 lb= &cu->disp;
2783                 
2784                 if(solid) {
2785                         dl= lb->first;
2786                         if(dl==NULL) return 1;
2787                         
2788                         if(dl->nors==0) addnormalsDispList(ob, lb);
2789                         index3_nors_incr= 0;
2790                         
2791                         if( displist_has_faces(lb)==0) {
2792                                 draw_index_wire= 0;
2793                                 drawDispListwire(lb);
2794                                 draw_index_wire= 1;
2795                         }
2796                         else {
2797                                 if(dt==OB_SHADED) {
2798                                         if(ob->disp.first==0) shadeDispList(base);
2799                                         drawDispListshaded(lb, ob);
2800                                 }
2801                                 else {
2802                                         init_gl_materials(ob, 0);
2803                                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2804                                         drawDispListsolid(lb, ob);
2805                                 }
2806                                 if(ob==G.obedit && cu->bevobj==NULL && cu->taperobj==NULL && cu->ext1 == 0.0 && cu->ext2 == 0.0) {
2807                                         cpack(0);
2808                                         draw_index_wire= 0;
2809                                         drawDispListwire(lb);
2810                                         draw_index_wire= 1;
2811                                 }
2812                         }
2813                         index3_nors_incr= 1;
2814                 }
2815                 else {
2816                         draw_index_wire= 0;
2817                         retval= drawDispListwire(lb);
2818                         draw_index_wire= 1;
2819                 }
2820                 break;
2821         case OB_SURF:
2822         
2823                 lb= &((Curve *)ob->data)->disp;
2824                 
2825                 if(solid) {
2826                         dl= lb->first;
2827                         if(dl==NULL) return 1;
2828                         
2829                         if(dl->nors==NULL) addnormalsDispList(ob, lb);
2830                         
2831                         if(dt==OB_SHADED) {
2832                                 if(ob->disp.first==NULL) shadeDispList(base);
2833                                 drawDispListshaded(lb, ob);
2834                         }
2835                         else {
2836                                 init_gl_materials(ob, 0);
2837                                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2838                         
2839                                 drawDispListsolid(lb, ob);
2840                         }
2841                 }
2842                 else {
2843                         retval= drawDispListwire(lb);
2844                 }
2845                 break;
2846         case OB_MBALL:
2847                 
2848                 if( is_basis_mball(ob)) {
2849                         lb= &ob->disp;
2850                         if(lb->first==NULL) makeDispListMBall(ob);
2851                         if(lb->first==NULL) return 1;
2852                         
2853                         if(solid) {
2854                                 
2855                                 if(dt==OB_SHADED) {
2856                                         dl= lb->first;
2857                                         if(dl && dl->col1==0) shadeDispList(base);
2858                                         drawDispListshaded(lb, ob);
2859                                 }
2860                                 else {
2861                                         init_gl_materials(ob, 0);
2862                                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2863                                 
2864                                         drawDispListsolid(lb, ob);      
2865                                 }
2866                         }
2867                         else{
2868                                 /* MetaBalls use DL_INDEX4 type of DispList */
2869                                 retval= drawDispListwire(lb);
2870                         }
2871                 }
2872                 break;
2873         }
2874         
2875         return retval;
2876 }
2877
2878 /* unified drawing of all new particle systems draw types except dupli ob & group       */
2879 /* mostly tries to use vertex arrays for speed                                                                          */
2880
2881 /* 1. check that everything is ok & updated */
2882 /* 2. start initialising things                         */
2883 /* 3. initialize according to draw type         */
2884 /* 4. allocate drawing data arrays                      */
2885 /* 5. start filling the arrays                          */
2886 /* 6. draw the arrays                                           */
2887 /* 7. clean up                                                          */
2888 static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt)
2889 {
2890         View3D *v3d= G.vd;
2891         Object *ob=base->object;
2892         ParticleSystemModifierData *psmd;
2893         ParticleSettings *part;
2894         ParticleData *pars, *pa;
2895         ParticleKey state, *states=0;
2896         ParticleCacheKey *cache=0;
2897         Material *ma;
2898         Object *bb_ob=0;
2899         float vel[3], vec[3], vec2[3], imat[4][4], onevec[3]={0.0f,0.0f,0.0f}, bb_center[3];
2900         float timestep, pixsize=1.0, pa_size, pa_time, r_tilt;
2901         float cfra=bsystem_time(ob,(float)CFRA,0.0);
2902         float *vdata=0, *vedata=0, *cdata=0, *ndata=0, *vd=0, *ved=0, *cd=0, *nd=0, xvec[3], yvec[3], zvec[3];
2903         int a, k, k_max=0, totpart, totpoint=0, draw_as, path_nbr=0;
2904         int path_possible=0, keys_possible=0, draw_keys=0, totchild=0;
2905         int select=ob->flag&SELECT, create_cdata=0;
2906         GLint polygonmode[2];
2907         char val[32];
2908
2909 /* 1. */
2910         if(psys==0)
2911                 return;
2912
2913         part=psys->part;
2914         pars=psys->particles;
2915
2916         if(part==0 || !psys_check_enabled(ob, psys))
2917                 return;
2918
2919         if(pars==0) return;
2920
2921         if(!G.obedit && psys_in_edit_mode(psys)
2922                 && psys->flag & PSYS_HAIR_DONE && part->draw_as==PART_DRAW_PATH)
2923                 return;
2924                 
2925         if(part->draw_as==PART_DRAW_NOT) return;
2926
2927 /* 2. */
2928         if(part->phystype==PART_PHYS_KEYED){
2929                 if(psys->flag & PSYS_FIRST_KEYED){
2930                         if(psys->flag&PSYS_KEYED){
2931                                 select=psys_count_keyed_targets(ob,psys);
2932                                 if(psys->totkeyed==0)
2933                                         return;
2934                         }
2935                 }
2936                 else
2937                         return;
2938         }
2939
2940         if(select){
2941                 select=0;
2942                 if(psys_get_current(ob)==psys)
2943                         select=1;
2944         }
2945
2946         psys->flag|=PSYS_DRAWING;
2947
2948         if(part->type==PART_HAIR && !psys->childcache)
2949                 totchild=0;
2950         else
2951                 totchild=psys->totchild*part->disp/100;
2952         
2953         ma= give_current_material(ob,part->omat);
2954
2955         if(G.vd->zbuf) glDepthMask(1);
2956
2957         if(select)
2958                 cpack(0xFFFFFF);
2959         else if((ma) && (part->draw&PART_DRAW_MAT_COL)) {
2960                 glColor3f(ma->r,ma->g,ma->b);
2961                 create_cdata = 1;
2962         }
2963         else
2964                 cpack(0);
2965
2966         psmd= psys_get_modifier(ob,psys);
2967
2968         timestep= psys_get_timestep(part);
2969
2970         myloadmatrix(G.vd->viewmat);
2971
2972         if( (base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP) ) {
2973                 float mat[4][4];
2974                 Mat4MulMat4(mat, psys->imat, ob->obmat);
2975                 mymultmatrix(mat);
2976         }
2977
2978         totpart=psys->totpart;
2979         draw_as=part->draw_as;
2980
2981         if(part->flag&PART_ABS_TIME && part->ipo){
2982                 calc_ipo(part->ipo, cfra);
2983                 execute_ipo((ID *)part, part->ipo);
2984         }
2985
2986         if(part->flag&PART_GLOB_TIME)
2987                 cfra=bsystem_time(0,(float)CFRA,0.0);
2988
2989         if(psys->pathcache){
2990                 path_possible=1;
2991                 keys_possible=1;
2992         }
2993         if(draw_as==PART_DRAW_PATH && path_possible==0)
2994                 draw_as=PART_DRAW_DOT;
2995
2996         if(draw_as!=PART_DRAW_PATH && keys_possible && part->draw&PART_DRAW_KEYS){
2997                 path_nbr=part->keys_step;
2998                 draw_keys=1;
2999         }
3000
3001 /* 3. */
3002         switch(draw_as){
3003                 case PART_DRAW_DOT:
3004                         if(part->draw_size)
3005                                 glPointSize(part->draw_size);
3006                         else
3007                                 glPointSize(2.0); /* default dot size */
3008                         break;
3009                 case PART_DRAW_CIRC:
3010                         /* calculate view aligned matrix: */
3011                         Mat4CpyMat4(imat, G.vd->viewinv);
3012                         Normalize(imat[0]);
3013                         Normalize(imat[1]);
3014                         /* no break! */
3015                 case PART_DRAW_CROSS:
3016                 case PART_DRAW_AXIS:
3017                         /* lets calculate the scale: */
3018                         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];
3019                         pixsize*= v3d->pixsize;
3020                         if(part->draw_size==0.0)
3021                                 pixsize*=2.0;
3022                         else
3023                                 pixsize*=part->draw_size;
3024                         break;
3025                 case PART_DRAW_OB:
3026                         if(part->dup_ob==0)
3027                                 draw_as=PART_DRAW_DOT;
3028                         else
3029                                 draw_as=0;
3030                         break;
3031                 case PART_DRAW_GR:
3032                         if(part->dup_group==0)
3033                                 draw_as=PART_DRAW_DOT;
3034                         else
3035                                 draw_as=0;
3036                         break;
3037                 case PART_DRAW_BB:
3038                         if(G.vd->camera==0 && part->bb_ob==0){
3039                                 error("Billboards need an active camera or a target object!");
3040
3041                                 draw_as=part->draw_as=PART_DRAW_DOT;
3042
3043                                 if(part->draw_size)
3044                                         glPointSize(part->draw_size);
3045                                 else
3046                                         glPointSize(2.0); /* default dot size */
3047                         }
3048                         else if(part->bb_ob)
3049                                 bb_ob=part->bb_ob;
3050                         else
3051                                 bb_ob=G.vd->camera;
3052
3053                         if(part->bb_align<PART_BB_VIEW)
3054                                 onevec[part->bb_align]=1.0f;
3055                         break;
3056                 case PART_DRAW_PATH:
3057                         break;
3058         }
3059         if(part->draw & PART_DRAW_SIZE && part->draw_as!=PART_DRAW_CIRC){
3060                 Mat4CpyMat4(imat, G.vd->viewinv);
3061                 Normalize(imat[0]);
3062                 Normalize(imat[1]);
3063         }
3064
3065 /* 4. */
3066         if(draw_as && draw_as!=PART_DRAW_PATH){
3067                 if(draw_as!=PART_DRAW_CIRC){
3068                         switch(draw_as){
3069                                 case PART_DRAW_AXIS:
3070                                 case PART_DRAW_CROSS:
3071                                         if(draw_as!=PART_DRAW_CROSS || create_cdata)
3072                                                 cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*6*3*sizeof(float), "particle_cdata");
3073                                         vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*6*3*sizeof(float), "particle_vdata");
3074                                         break;
3075                                 case PART_DRAW_LINE:
3076                                         if(create_cdata)
3077                                                 cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*2*3*sizeof(float), "particle_cdata");
3078                                         vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*2*3*sizeof(float), "particle_vdata");
3079                                         break;
3080                                 case PART_DRAW_BB:
3081                                         if(create_cdata)
3082                                                 cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_cdata");
3083                                         vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_vdata");
3084                                         ndata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_vdata");
3085                                         break;
3086                                 default:
3087                                         if(create_cdata)
3088                                                 cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*3*sizeof(float), "particle_cdata");
3089                                         vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*3*sizeof(float), "particle_vdata");
3090                         }
3091                 }
3092
3093                 if(part->draw&PART_DRAW_VEL && draw_as!=PART_DRAW_LINE)
3094                         vedata=MEM_callocN((totpart+totchild)*2*3*(path_nbr+1)*sizeof(float), "particle_vedata");
3095
3096                 vd=vdata;
3097                 ved=vedata;
3098                 cd=cdata;
3099                 nd=ndata;
3100
3101                 psys->lattice=psys_get_lattice(ob,psys);
3102         }
3103
3104         if(draw_as){
3105 /* 5. */
3106                 for(a=0,pa=pars; a<totpart+totchild; a++, pa++){
3107                         if(a<totpart){
3108                                 if(totchild && (part->draw&PART_DRAW_PARENT)==0) continue;
3109                                 if(pa->flag & PARS_NO_DISP || pa->flag & PARS_UNEXIST) continue;
3110
3111                                 pa_time=(cfra-pa->time)/pa->lifetime;
3112
3113                                 if((part->flag&PART_ABS_TIME)==0){                              
3114                                         if(ma && ma->ipo){
3115                                                 /* correction for lifetime */
3116                                                 calc_ipo(ma->ipo, 100.0f*pa_time);
3117                                                 execute_ipo((ID *)ma, ma->ipo);
3118                                         }
3119                                         if(part->ipo) {
3120                                                 /* correction for lifetime */
3121                                                 calc_ipo(part->ipo, 100*pa_time);
3122                                                 execute_ipo((ID *)part, part->ipo);
3123                                         }
3124                                 }
3125
3126                                 pa_size=pa->size;
3127
3128                                 r_tilt=1.0f+pa->r_ave[0];
3129
3130                                 if(path_nbr){
3131                                         cache=psys->pathcache[a];
3132                                         k_max=(int)(cache->steps);
3133                                 }
3134                         }
3135                         else{
3136                                 ChildParticle *cpa= &psys->child[a-totpart];
3137
3138                                 pa_time=psys_get_child_time(psys,cpa,cfra);
3139
3140                                 if((part->flag&PART_ABS_TIME)==0) {
3141                                         if(ma && ma->ipo){
3142                                                 /* correction for lifetime */
3143                                                 calc_ipo(ma->ipo, 100.0f*pa_time);
3144                                                 execute_ipo((ID *)ma, ma->ipo);
3145                                         }
3146                                         if(part->ipo) {
3147                                                 /* correction for lifetime */
3148                                                 calc_ipo(part->ipo, 100*pa_time);
3149                                                 execute_ipo((ID *)part, part->ipo);
3150                                         }
3151                                 }
3152
3153                                 pa_size=psys_get_child_size(psys,cpa,cfra,0);
3154
3155                                 r_tilt=2.0f*cpa->rand[2];
3156                                 if(path_nbr){
3157                                         cache=psys->childcache[a-totpart];
3158                                         k_max=(int)(cache->steps);
3159                                 }
3160                         }
3161
3162                         if(draw_as!=PART_DRAW_PATH){
3163                                 int next_pa=0;
3164                                 for(k=0; k<=path_nbr; k++){
3165                                         if(draw_keys){
3166                                                 state.time=(float)k/(float)path_nbr;
3167                                                 psys_get_particle_on_path(ob,psys,a,&state,1);
3168                                         }
3169                                         else if(path_nbr){
3170                                                 if(k<=k_max){
3171                                                         VECCOPY(state.co,(cache+k)->co);
3172                                                         VECCOPY(state.vel,(cache+k)->vel);
3173                                                         QUATCOPY(state.rot,(cache+k)->rot);
3174                                                 }
3175                                                 else
3176                                                         continue;       
3177                                         }
3178                                         else{
3179                                                 state.time=cfra;
3180                                                 if(psys_get_particle_state(ob,psys,a,&state,0)==0){
3181                                                         next_pa=1;
3182                                                         break;
3183                                                &