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