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