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