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