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