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