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