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