Updated the Sun ifdef's basically I standardized them so they
[blender-staging.git] / source / blender / src / drawmesh.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 #ifdef WIN32
41 #include "BLI_winstuff.h"
42 #endif
43
44 #include "MEM_guardedalloc.h"
45
46 #include "BLI_blenlib.h"
47 #include "BLI_arithb.h"
48
49 #include "IMB_imbuf_types.h"
50
51 #include "DNA_image_types.h"
52 #include "DNA_lamp_types.h"
53 #include "DNA_material_types.h"
54 #include "DNA_mesh_types.h"
55 #include "DNA_object_types.h"
56 #include "DNA_property_types.h"
57 #include "DNA_scene_types.h"
58 #include "DNA_view3d_types.h"
59
60 #include "BKE_bmfont.h"
61 #include "BKE_main.h"
62 #include "BKE_mesh.h"
63 #include "BKE_image.h"
64 #include "BKE_property.h"
65 #include "BKE_global.h"
66 #include "BKE_displist.h"
67 #include "BKE_object.h"
68 #include "BKE_material.h"
69
70 #include "BIF_gl.h"
71 #include "BIF_mywindow.h"
72
73 #include "BDR_editface.h"
74 #include "BDR_vpaint.h"
75 #include "BDR_drawmesh.h"
76
77 #include "BSE_drawview.h"
78
79 #include "blendef.h"
80 #include "nla.h"
81
82 //#include "glext.h"
83 /* some local functions */
84 static void draw_hide_tfaces(Object *ob, Mesh *me);
85
86 #if defined(GL_EXT_texture_object) && (!defined(__sun__) || (!defined(__sun))) && !defined(__APPLE__)
87
88         /* exception for mesa... not according th opengl specs */
89         #ifndef __linux__
90                 #define glBindTexture(A,B)     glBindTextureEXT(A,B)
91         #endif
92
93         #define glGenTextures(A,B)     glGenTexturesEXT(A,B)
94         #define glDeleteTextures(A,B)  glDeleteTexturesEXT(A,B)
95         #define glPolygonOffset(A,B)  glPolygonOffsetEXT(A,B)
96
97 #else
98
99 /* #define GL_FUNC_ADD_EXT                                      GL_FUNC_ADD */
100 /* #define GL_FUNC_REVERSE_SUBTRACT_EXT GL_FUNC_REVERSE_SUBTRACT */
101 /* #define GL_POLYGON_OFFSET_EXT                        GL_POLYGON_OFFSET */
102
103 #endif
104
105         /* (n&(n-1)) zeros the least significant bit of n */
106 static int is_pow2(int num) {
107         return ((num)&(num-1))==0;
108 }
109 static int smaller_pow2(int num) {
110         while (!is_pow2(num))
111                 num= num&(num-1);
112         return num;     
113 }
114
115 static int fCurtile=0, fCurmode=0,fCurtileXRep=0,fCurtileYRep=0;
116 static Image *fCurpage=0;
117 static short fTexwindx, fTexwindy, fTexwinsx, fTexwinsy;
118 static int fDoMipMap = 1;
119 static int fLinearMipMap = 0;
120
121 /*  static int source, dest; also not used */
122
123 /**
124  * Enables or disable mipmapping for realtime images.
125  * @param mipmap Turn mipmapping on (mipmap!=0) or off (mipmap==0).
126  */
127 void set_mipmap(int mipmap)
128 {
129         if (fDoMipMap != (mipmap != 0)) {
130                 free_all_realtime_images();
131                 fDoMipMap = mipmap != 0;
132         }
133 }
134
135
136 /**
137  * Returns the current setting for mipmapping.
138  */
139 int get_mipmap(void)
140 {
141         return fDoMipMap;
142 }
143
144 /**
145  * Enables or disable linear mipmap setting for realtime images (textures).
146  * Note that this will will destroy all texture bindings in OpenGL.
147  * @see free_realtime_image()
148  * @param mipmap Turn linear mipmapping on (linear!=0) or off (linear==0).
149  */
150 void set_linear_mipmap(int linear)
151 {
152         if (fLinearMipMap != (linear != 0)) {
153                 free_all_realtime_images();
154                 fLinearMipMap = linear != 0;
155         }
156 }
157
158 /**
159  * Returns the current setting for linear mipmapping.
160  */
161 int get_linear_mipmap(void)
162 {
163         return fLinearMipMap;
164 }
165
166
167 /**
168  * Resets the realtime image cache variables.
169  */
170 void clear_realtime_image_cache()
171 {
172         fCurpage = NULL;
173         fCurtile = 0;
174         fCurmode = 0;
175         fCurtileXRep = 0;
176         fCurtileYRep = 0;
177 }
178
179 /* REMEMBER!  Changes here must go into my_set_tpage() as well */
180 int set_tpage(TFace *tface)
181 {       
182         static int alphamode= -1;
183         static TFace *lasttface= 0;
184         Image *ima;
185         unsigned int *rect=NULL, *bind;
186         int tpx=0, tpy=0, tilemode, tileXRep,tileYRep;
187         
188         /* disable */
189         if(tface==0) {
190                 if(lasttface==0) return 0;
191                 
192                 lasttface= 0;
193                 fCurtile= 0;
194                 fCurpage= 0;
195                 if(fCurmode!=0) {
196                         glMatrixMode(GL_TEXTURE);
197                         glLoadIdentity();
198                         glMatrixMode(GL_MODELVIEW);
199                 }
200                 fCurmode= 0;
201                 fCurtileXRep=0;
202                 fCurtileYRep=0;
203                 alphamode= -1;
204                 
205                 glDisable(GL_BLEND);
206                 glDisable(GL_TEXTURE_2D);
207                 glDisable(GL_TEXTURE_GEN_S);
208                 glDisable(GL_TEXTURE_GEN_T);
209
210                 return 0;
211         }
212         lasttface= tface;
213
214         if( alphamode != tface->transp) {
215                 alphamode= tface->transp;
216
217                 if(alphamode) {
218                         glEnable(GL_BLEND);
219                         
220                         if(alphamode==TF_ADD) {
221                                 glBlendFunc(GL_ONE, GL_ONE);
222                         /*      glBlendEquationEXT(GL_FUNC_ADD_EXT); */
223                         }
224                         else if(alphamode==TF_ALPHA) {
225                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
226                         /*      glBlendEquationEXT(GL_FUNC_ADD_EXT); */
227                         }
228                         /* else { */
229                         /*      glBlendFunc(GL_ONE, GL_ONE); */
230                         /*      glBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT); */
231                         /* } */
232                 }
233                 else glDisable(GL_BLEND);
234         }
235
236         ima= tface->tpage;
237
238         /* Enable or disable reflection mapping */
239         if (ima && (ima->flag & IMA_REFLECT)){
240
241 //              glActiveTextureARB(GL_TEXTURE0_ARB);
242                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
243                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
244
245                 glEnable(GL_TEXTURE_GEN_S);
246                 glEnable(GL_TEXTURE_GEN_T);
247
248                 /* Handle multitexturing here */
249         }
250         else{
251                 glDisable(GL_TEXTURE_GEN_S);
252                 glDisable(GL_TEXTURE_GEN_T);
253         }
254
255         tilemode= tface->mode & TF_TILES;
256         tileXRep = 0;
257         tileYRep = 0;
258         if (ima)
259         {
260                 tileXRep = ima->xrep;
261                 tileYRep = ima->yrep;
262         }
263
264
265         if(ima==fCurpage && fCurtile==tface->tile && tilemode==fCurmode && fCurtileXRep==tileXRep && fCurtileYRep == tileYRep) return ima!=0;
266
267         if(tilemode!=fCurmode || fCurtileXRep!=tileXRep || fCurtileYRep != tileYRep)
268         {
269                 glMatrixMode(GL_TEXTURE);
270                 glLoadIdentity();
271                 
272                 if(tilemode && ima!=0)
273                         glScalef(ima->xrep, ima->yrep, 1.0);
274
275                 glMatrixMode(GL_MODELVIEW);
276         }
277
278         if(ima==0 || ima->ok==0) {
279                 glDisable(GL_TEXTURE_2D);
280                 
281                 fCurtile= tface->tile;
282                 fCurpage= 0;
283                 fCurmode= tilemode;
284                 fCurtileXRep = tileXRep;
285                 fCurtileYRep = tileYRep;
286
287                 return 0;
288         }
289
290         if(ima->ibuf==0) {
291                 load_image(ima, IB_rect, G.sce, G.scene->r.cfra);
292                 
293                 if(ima->ibuf==0) {
294                         ima->ok= 0;
295
296                         fCurtile= tface->tile;
297                         fCurpage= 0;
298                         fCurmode= tilemode;
299                         fCurtileXRep = tileXRep;
300                         fCurtileYRep = tileYRep;
301                         
302                         glDisable(GL_TEXTURE_2D);
303                         return 0;
304                 }
305                 
306         }
307
308         if(ima->tpageflag & IMA_TWINANIM) fCurtile= ima->lastframe;
309         else fCurtile= tface->tile;
310
311         if(tilemode) {
312
313                 if(ima->repbind==0) make_repbind(ima);
314                 
315                 if(fCurtile>=ima->totbind) fCurtile= 0;
316                 
317                 /* this happens when you change repeat buttons */
318                 if(ima->repbind) bind= ima->repbind+fCurtile;
319                 else bind= &ima->bindcode;
320                 
321                 if(*bind==0) {
322                         
323                         fTexwindx= ima->ibuf->x/ima->xrep;
324                         fTexwindy= ima->ibuf->y/ima->yrep;
325                         
326                         if(fCurtile>=ima->xrep*ima->yrep) fCurtile= ima->xrep*ima->yrep-1;
327         
328                         fTexwinsy= fCurtile / ima->xrep;
329                         fTexwinsx= fCurtile - fTexwinsy*ima->xrep;
330         
331                         fTexwinsx*= fTexwindx;
332                         fTexwinsy*= fTexwindy;
333         
334                         tpx= fTexwindx;
335                         tpy= fTexwindy;
336
337                         rect= ima->ibuf->rect + fTexwinsy*ima->ibuf->x + fTexwinsx;
338                 }
339         }
340         else {
341                 bind= &ima->bindcode;
342                 
343                 if(*bind==0) {
344                         tpx= ima->ibuf->x;
345                         tpy= ima->ibuf->y;
346                         rect= ima->ibuf->rect;
347                 }
348         }
349
350         if(*bind==0) {
351                 int rectw= tpx, recth= tpy;
352                 unsigned int *tilerect= NULL, *scalerect= NULL;
353
354                 /*
355                  * Maarten:
356                  * According to Ton this code is not needed anymore. It was used only
357                  * in really old Blenders.
358                  * Reevan:
359                  * Actually it is needed for backwards compatibility.  Simpledemo 6 does not display correctly without it.
360                  */
361 #if 1
362                 if (tilemode) {
363                         int y;
364                                 
365                         tilerect= MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect");
366                         for (y=0; y<recth; y++) {
367                                 unsigned int *rectrow= &rect[y*ima->ibuf->x];
368                                 unsigned int *tilerectrow= &tilerect[y*rectw];
369                                         
370                                 memcpy(tilerectrow, rectrow, tpx*sizeof(*rectrow));
371                         }
372                                 
373                         rect= tilerect;
374                 }
375 #endif
376                 if (!is_pow2(rectw) || !is_pow2(recth)) {
377                         rectw= smaller_pow2(rectw);
378                         recth= smaller_pow2(recth);
379                         
380                         scalerect= MEM_mallocN(rectw*recth*sizeof(*scalerect), "scalerect");
381                         gluScaleImage(GL_RGBA, tpx, tpy, GL_UNSIGNED_BYTE, rect, rectw, recth, GL_UNSIGNED_BYTE, scalerect);
382                         rect= scalerect;
383                 }
384
385                 glGenTextures(1, (GLuint *)bind);
386                 
387                 if(G.f & G_DEBUG) {
388                         printf("var1: %s\n", ima->id.name+2);
389                         printf("var1: %d, var2: %d\n", *bind, tpx);
390                         printf("var1: %d, var2: %d\n", fCurtile, tilemode);
391                 }
392                 glBindTexture( GL_TEXTURE_2D, *bind);
393
394                 if (!fDoMipMap)
395                 {
396                         glTexImage2D(GL_TEXTURE_2D, 0,  GL_RGBA,  rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
397                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
398                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
399                 } else
400                 {
401                         int minfilter= fLinearMipMap?GL_LINEAR_MIPMAP_LINEAR:GL_LINEAR_MIPMAP_NEAREST;
402                         
403                         gluBuild2DMipmaps(GL_TEXTURE_2D, 4, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect);
404                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minfilter);
405                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
406                 }
407
408                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
409                         
410                 if (tilerect)
411                         MEM_freeN(tilerect);
412                 if (scalerect)
413                         MEM_freeN(scalerect);
414         }
415         else glBindTexture( GL_TEXTURE_2D, *bind);
416         
417         
418
419         glEnable(GL_TEXTURE_2D);
420
421         fCurpage= ima;
422         fCurmode= tilemode;
423         fCurtileXRep = tileXRep;
424         fCurtileYRep = tileYRep;
425
426         return 1;
427 }
428
429 void free_realtime_image(Image *ima)
430 {
431         if(ima->bindcode) {
432                 glDeleteTextures(1, (GLuint *)&ima->bindcode);
433                 ima->bindcode= 0;
434         }
435         if(ima->repbind) {
436                 glDeleteTextures(ima->totbind, (GLuint *)ima->repbind);
437         
438                 MEM_freeN(ima->repbind);
439                 ima->repbind= 0;
440         }
441 }
442
443 void free_all_realtime_images(void)
444 {
445         Image* ima;
446
447         ima= G.main->image.first;
448         while(ima) {
449                 free_realtime_image(ima);
450                 ima= ima->id.next;
451         }
452 }
453
454 void make_repbind(Image *ima)
455 {
456         if(ima==0 || ima->ibuf==0) return;
457
458         if(ima->repbind) {
459                 glDeleteTextures(ima->totbind, (GLuint *)ima->repbind);
460                 MEM_freeN(ima->repbind);
461                 ima->repbind= 0;
462         }
463         ima->totbind= ima->xrep*ima->yrep;
464         if(ima->totbind>1) {
465                 ima->repbind= MEM_callocN(sizeof(int)*ima->totbind, "repbind");
466         }
467 }
468
469 void update_realtime_textures()
470 {
471         Image *ima;
472         
473         ima= G.main->image.first;
474         while(ima) {
475                 if(ima->tpageflag & IMA_TWINANIM) {
476                         if(ima->twend >= ima->xrep*ima->yrep) ima->twend= ima->xrep*ima->yrep-1;
477                 
478                         /* check: is bindcode not in the array? Free. (to do) */
479                         
480                         ima->lastframe++;
481                         if(ima->lastframe > ima->twend) ima->lastframe= ima->twsta;
482                         
483                 }
484                 ima= ima->id.next;
485         }
486 }
487
488
489 void spack(unsigned int ucol)
490 {
491         char *cp= (char *)&ucol;
492         
493         glColor3ub(cp[3], cp[2], cp[1]);
494 }
495
496 static void draw_hide_tfaces(Object *ob, Mesh *me)
497 {
498         TFace *tface;
499         MFace *mface;
500         float *v1, *v2, *v3, *v4;
501         int a;
502         
503         if(me==0 || me->tface==0) return;
504
505         mface= me->mface;
506         tface= me->tface;
507
508         cpack(0x0);
509         setlinestyle(1);
510         for(a=me->totface; a>0; a--, mface++, tface++) {
511                 if(mface->v3==0) continue;
512                 
513                 if( (tface->flag & TF_HIDE)) {
514
515                         v1= (me->mvert+mface->v1)->co;
516                         v2= (me->mvert+mface->v2)->co;
517                         v3= (me->mvert+mface->v3)->co;
518                         if(mface->v4) v4= (me->mvert+mface->v4)->co; else v4= 0;
519                 
520                         glBegin(GL_LINE_LOOP);
521                                 glVertex3fv( v1 );
522                                 glVertex3fv( v2 );
523                                 glVertex3fv( v3 );
524                                 if(mface->v4) glVertex3fv( v4 );
525                         glEnd();                        
526                 }
527         }
528         setlinestyle(0);
529 }
530
531
532 void draw_tfaces3D(Object *ob, Mesh *me)
533 {
534         MFace *mface;
535         TFace *tface;
536         DispList *dl;
537         float *v1, *v2, *v3, *v4, *extverts= NULL;
538         int a;
539         
540         if(me==0 || me->tface==0) return;
541
542         glDisable(GL_DEPTH_TEST);
543
544         mface= me->mface;
545         tface= me->tface;
546
547         dl= find_displist(&ob->disp, DL_VERTS);
548         if (dl) extverts= dl->verts;
549         
550         /* SELECT faces */
551         for(a=me->totface; a>0; a--, mface++, tface++) {
552                 if(mface->v3==0) continue;
553                 if(tface->flag & TF_HIDE) continue;
554                 
555                 if( tface->flag & (TF_ACTIVE|TF_SELECT) ) {
556                         if (extverts) {
557                                 v1= extverts+3*mface->v1;
558                                 v2= extverts+3*mface->v2;
559                                 v3= extverts+3*mface->v3;
560                                 v4= mface->v4?(extverts+3*mface->v4):NULL;
561                         } else {
562                                 v1= (me->mvert+mface->v1)->co;
563                                 v2= (me->mvert+mface->v2)->co;
564                                 v3= (me->mvert+mface->v3)->co;
565                                 v4= mface->v4?(me->mvert+mface->v4)->co:NULL;
566                         }
567
568                         if(tface->flag & TF_ACTIVE) {
569                                 /* colors: R=x G=y */
570                                 cpack(0xFF);
571                                 glBegin(GL_LINE_STRIP); glVertex3fv(v1); if(v4) glVertex3fv(v4); else glVertex3fv(v3); glEnd();
572                                 cpack(0xFF00);
573                                 glBegin(GL_LINE_STRIP); glVertex3fv(v1); glVertex3fv(v2); glEnd();
574                                 cpack(0x0);
575                                 glBegin(GL_LINE_STRIP); glVertex3fv(v2); glVertex3fv(v3); if(v4) glVertex3fv(v4); glEnd();
576                         }
577                         else {
578                                 cpack(0x0);
579                                 glBegin(GL_LINE_LOOP);
580                                         glVertex3fv( v1 );
581                                         glVertex3fv( v2 );
582                                         glVertex3fv( v3 );
583                                         if(v4) glVertex3fv( v4 );
584                                 glEnd();
585                         }
586                         
587                         if(tface->flag & TF_SELECT) {
588                                 cpack(0xFFFFFF);
589                                 setlinestyle(1);
590                                 glBegin(GL_LINE_LOOP);
591                                         glVertex3fv( v1 );
592                                         glVertex3fv( v2 );
593                                         glVertex3fv( v3 );
594                                         if(v4) glVertex3fv( v4 );
595                                 glEnd();
596                                 setlinestyle(0);
597                         }
598                 }
599         }
600
601         glEnable(GL_DEPTH_TEST);
602 }
603
604 static int set_gl_light(Object *ob)
605 {
606         Base *base;
607         Lamp *la;
608         int count;
609         /* float zero[4]= {0.0, 0.0, 0.0, 0.0};  */
610         float vec[4];
611         
612         vec[3]= 1.0;
613         
614         for(count=0; count<8; count++) glDisable(GL_LIGHT0+count);
615         
616         count= 0;
617         
618         base= FIRSTBASE;
619         while(base) {
620                 if(base->object->type==OB_LAMP ) {
621                         if(base->lay & G.vd->lay) {
622                                 if(base->lay & ob->lay) 
623                                 {
624                                         la= base->object->data;
625                                         
626                                         glPushMatrix();
627                                         glLoadMatrixf((float *)G.vd->viewmat);
628                                         
629                                         where_is_object_simul(base->object);
630                                         VECCOPY(vec, base->object->obmat[3]);
631                                         
632                                         if(la->type==LA_SUN) {
633                                                 vec[0]= base->object->obmat[2][0];
634                                                 vec[1]= base->object->obmat[2][1];
635                                                 vec[2]= base->object->obmat[2][2];
636                                                 vec[3]= 0.0;
637                                                 glLightfv(GL_LIGHT0+count, GL_POSITION, vec); 
638                                         }
639                                         else {
640                                                 vec[3]= 1.0;
641                                                 glLightfv(GL_LIGHT0+count, GL_POSITION, vec); 
642                                                 glLightf(GL_LIGHT0+count, GL_CONSTANT_ATTENUATION, 1.0);
643                                                 glLightf(GL_LIGHT0+count, GL_LINEAR_ATTENUATION, la->att1/la->dist);
644                                                 /* without this next line it looks backward compatible. attennuation still is acceptable */
645                                                 /* glLightf(GL_LIGHT0+count, GL_QUADRATIC_ATTENUATION, la->att2/(la->dist*la->dist)); */
646                                                 
647                                                 if(la->type==LA_SPOT) {
648                                                         vec[0]= -base->object->obmat[2][0];
649                                                         vec[1]= -base->object->obmat[2][1];
650                                                         vec[2]= -base->object->obmat[2][2];
651                                                         glLightfv(GL_LIGHT0+count, GL_SPOT_DIRECTION, vec);
652                                                         glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, la->spotsize/2.0);
653                                                         glLightf(GL_LIGHT0+count, GL_SPOT_EXPONENT, 128.0*la->spotblend);
654                                                 }
655                                                 else glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, 180.0);
656                                         }
657                                         
658                                         vec[0]= la->energy*la->r;
659                                         vec[1]= la->energy*la->g;
660                                         vec[2]= la->energy*la->b;
661                                         vec[3]= 1.0;
662                                         glLightfv(GL_LIGHT0+count, GL_DIFFUSE, vec); 
663                                         glLightfv(GL_LIGHT0+count, GL_SPECULAR, vec);//zero); 
664                                         glEnable(GL_LIGHT0+count);
665                                         
666                                         glPopMatrix();                                  
667                                         
668                                         count++;
669                                         if(count>7) break;
670                                 }
671                         }
672                 }
673                 base= base->next;
674         }
675
676         return count;
677 }
678
679 static Material *give_current_material_or_def(Object *ob, int matnr)
680 {
681         extern Material defmaterial;
682         Material *ma= give_current_material(ob, matnr);
683
684         return ma?ma:&defmaterial;
685 }
686
687 static int set_draw_settings_cached(int clearcache, int textured, TFace *texface, int lit, Object *litob, int litmatnr, int doublesided)
688 {
689         static int c_textured;
690         static int c_lit;
691         static int c_doublesided;
692         static TFace *c_texface;
693         static Object *c_litob;
694         static int c_litmatnr;
695         static int c_badtex;
696
697         if (clearcache) {
698                 c_textured= c_lit= c_doublesided= -1;
699                 c_texface= (TFace*) -1;
700                 c_litob= (Object*) -1;
701                 c_litmatnr= -1;
702                 c_badtex= 0;
703         }
704
705         if (doublesided!=c_doublesided) {
706                 if (doublesided) glDisable(GL_CULL_FACE);
707                 else glEnable(GL_CULL_FACE);
708
709                 c_doublesided= doublesided;
710         }
711
712         if (textured!=c_textured || texface!=c_texface) {
713                 if (textured) {
714                         c_badtex= !set_tpage(texface);
715                 } else {
716                         set_tpage(0);
717                         c_badtex= 0;
718                 }
719                 c_textured= textured;
720                 c_texface= texface;
721         }
722
723         if (c_badtex) lit= 0;
724         if (lit!=c_lit || litob!=c_litob || litmatnr!=c_litmatnr) {
725                 if (lit) {
726                         Material *ma= give_current_material_or_def(litob, litmatnr);
727                         float spec[4];
728
729                         spec[0]= ma->spec*ma->specr;
730                         spec[1]= ma->spec*ma->specg;
731                         spec[2]= ma->spec*ma->specb;
732                         spec[3]= 1.0;
733
734                         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
735                         glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
736                         glEnable(GL_LIGHTING);
737                         glEnable(GL_COLOR_MATERIAL);
738                 }
739                 else {
740                         glDisable(GL_LIGHTING); 
741                         glDisable(GL_COLOR_MATERIAL);
742                 }
743                 c_lit= lit;
744                 c_litob= litob;
745                 c_litmatnr= litmatnr;
746         }
747
748         return c_badtex;
749 }
750
751 void draw_tface_mesh(Object *ob, Mesh *me, int dt)
752 /* maximum dt (drawtype): exactly according values that have been set */
753 {
754         TFace *tface=NULL;
755         MFace *mface=NULL;
756         float *extverts= NULL;
757         unsigned char obcol[4];
758         int a, mode;
759         short islight, istex;
760         
761         if (!me || !me->tface) return;
762
763
764         glShadeModel(GL_SMOOTH);
765
766         islight= set_gl_light(ob);
767         
768         obcol[0]= CLAMPIS(ob->col[0]*255, 0, 255);
769         obcol[1]= CLAMPIS(ob->col[1]*255, 0, 255);
770         obcol[2]= CLAMPIS(ob->col[2]*255, 0, 255);
771         obcol[3]= CLAMPIS(ob->col[3]*255, 0, 255);
772         
773         /* first all texture polys */
774         
775         glCullFace(GL_BACK); glEnable(GL_CULL_FACE);
776         if(G.vd->drawtype==OB_TEXTURE) istex= 1;
777         else istex= 0;
778
779         set_draw_settings_cached(1, 0, 0, 0, 0, 0, 0);
780
781         if(dt > OB_SOLID) {
782                 bProperty *prop = get_property(ob, "Text");
783                 MFaceInt *mfaceint= NULL;
784                 int editing= (G.f & (G_VERTEXPAINT+G_FACESELECT+G_TEXTUREPAINT+G_WEIGHTPAINT)) && (ob==((G.scene->basact) ? (G.scene->basact->object) : 0));
785                 MVert *mvert=NULL;
786                 int totface;
787
788                 if(mesh_uses_displist(me) && editing==0) {
789                         DispList *dl= find_displist(&me->disp, DL_MESH);
790                         DispListMesh *dlm= dl->mesh;
791                         
792                         totface= dlm->totface;
793                         
794                         if (!dl)
795                                 totface= 0;
796                         else {
797                                 totface= dlm->totface;
798                                 mvert= dlm->mvert;
799                                 mfaceint= dlm->mface;
800                                 tface= dlm->tface;
801                         }
802                 } 
803                 else {
804                         DispList *dl= find_displist(&ob->disp, DL_VERTS);
805                         if (dl) extverts= dl->verts;
806                         
807                         totface= me->totface;
808                         mvert= me->mvert;
809                         mface= me->mface;
810                         tface= me->tface;
811                 }
812                 
813                 for (a=0; a<totface; a++, tface++) {
814                         int v1idx, v2idx, v3idx, v4idx, mf_smooth, matnr, badtex;
815                         float *v1, *v2, *v3, *v4;
816
817                         if (mfaceint) {
818                                 MFaceInt *mf= &mfaceint[a];
819
820                                 v1idx= mf->v1;
821                                 v2idx= mf->v2;
822                                 v3idx= mf->v3;
823                                 v4idx= mf->v4;
824                                 mf_smooth= mf->flag & ME_SMOOTH;
825                                 matnr= mf->mat_nr;
826                         } else {
827                                 MFace *mf= &mface[a];
828
829                                 v1idx= mf->v1;
830                                 v2idx= mf->v2;
831                                 v3idx= mf->v3;
832                                 v4idx= mf->v4;
833                                 mf_smooth= mf->flag & ME_SMOOTH;
834                                 matnr= mf->mat_nr;
835                         }
836                         
837                         if(v3idx==0) continue;
838                         if(tface->flag & TF_HIDE) continue;
839                         if(tface->mode & TF_INVISIBLE) continue;
840                         
841                         mode= tface->mode;
842
843                         if (extverts) {
844                                 v1= extverts+3*v1idx;
845                                 v2= extverts+3*v2idx;
846                                 v3= extverts+3*v3idx;
847                                 v4= v4idx?(extverts+3*v4idx):NULL;
848                         } else {
849                                 v1= (mvert+v1idx)->co;
850                                 v2= (mvert+v2idx)->co;
851                                 v3= (mvert+v3idx)->co;
852                                 v4= v4idx?(mvert+v4idx)->co:NULL;
853                         }
854
855                         badtex= set_draw_settings_cached(0, istex && (mode&TF_TEX), tface, islight && (mode&TF_LIGHT), ob, matnr, mode&TF_TWOSIDE);
856
857                         if (prop && !badtex && !editing && (mode & TF_BMFONT)) {
858                                 char string[MAX_PROPSTRING];
859                                 int characters, index;
860                                 Image *ima;
861                                 float curpos;
862
863                                 // The BM_FONT handling code is duplicated in the gameengine
864                                 // Search for 'Frank van Beek' ;-)
865
866                                 // string = "Frank van Beek";
867
868                                 set_property_valstr(prop, string);
869                                 characters = strlen(string);
870                                 
871                                 ima = tface->tpage;
872                                 if (ima == NULL) {
873                                         characters = 0;
874                                 }
875
876                                 if (1 || !mf_smooth) {
877                                         float nor[3];
878
879                                         CalcNormFloat(v1, v2, v3, nor);
880
881                                         glNormal3fv(nor);
882                                 }
883
884                                 curpos= 0.0;
885                                 glBegin(v4?GL_QUADS:GL_TRIANGLES);
886                                 for (index = 0; index < characters; index++) {
887                                         float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance;
888                                         int character = string[index];
889                                         char *cp= NULL;
890
891                                         // lets calculate offset stuff
892                                         // space starts at offset 1
893                                         // character = character - ' ' + 1;
894                                         
895                                         matrixGlyph(ima->ibuf, character, & centerx, &centery, &sizex, &sizey, &transx, &transy, &movex, &movey, &advance);
896                                         movex+= curpos;
897
898                                         if (mode & TF_OBCOL) glColor3ubv(obcol);
899                                         else cp= (char *)&(tface->col[0]);
900
901                                         glTexCoord2f((tface->uv[0][0] - centerx) * sizex + transx, (tface->uv[0][1] - centery) * sizey + transy);
902                                         if (cp) glColor3ub(cp[3], cp[2], cp[1]);
903                                         glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]);
904                                         
905                                         glTexCoord2f((tface->uv[1][0] - centerx) * sizex + transx, (tface->uv[1][1] - centery) * sizey + transy);
906                                         if (cp) glColor3ub(cp[7], cp[6], cp[5]);
907                                         glVertex3f(sizex * v2[0] + movex, sizey * v2[1] + movey, v2[2]);
908                 
909                                         glTexCoord2f((tface->uv[2][0] - centerx) * sizex + transx, (tface->uv[2][1] - centery) * sizey + transy);
910                                         if (cp) glColor3ub(cp[11], cp[10], cp[9]);
911                                         glVertex3f(sizex * v3[0] + movex, sizey * v3[1] + movey, v3[2]);
912                 
913                                         if(v4) {
914                                                 glTexCoord2f((tface->uv[3][0] - centerx) * sizex + transx, (tface->uv[3][1] - centery) * sizey + transy);
915                                                 if (cp) glColor3ub(cp[15], cp[14], cp[13]);
916                                                 glVertex3f(sizex * v4[0] + movex, sizey * v4[1] + movey, v4[2]);
917                                         }
918
919                                         curpos+= advance;
920                                 }
921                                 glEnd();
922                         }
923                         else {
924                                 char *cp= NULL;
925                                 
926                                 if (badtex) glColor3ub(0xFF, 0x00, 0xFF);
927                                 else if (mode & TF_OBCOL) glColor3ubv(obcol);
928                                 else cp= (char *)&(tface->col[0]);
929
930                                 if (!mf_smooth) {
931                                         float nor[3];
932
933                                         CalcNormFloat(v1, v2, v3, nor);
934
935                                         glNormal3fv(nor);
936                                 }
937
938                                 glBegin(v4?GL_QUADS:GL_TRIANGLES);
939
940                                 glTexCoord2fv(tface->uv[0]);
941                                 if (cp) glColor3ub(cp[3], cp[2], cp[1]);
942                                 if (mf_smooth) glNormal3sv(mvert[v1idx].no);
943                                 glVertex3fv(v1);
944                                 
945                                 glTexCoord2fv(tface->uv[1]);
946                                 if (cp) glColor3ub(cp[7], cp[6], cp[5]);
947                                 if (mf_smooth) glNormal3sv(mvert[v2idx].no);
948                                 glVertex3fv(v2);
949
950                                 glTexCoord2fv(tface->uv[2]);
951                                 if (cp) glColor3ub(cp[11], cp[10], cp[9]);
952                                 if (mf_smooth) glNormal3sv(mvert[v3idx].no);
953                                 glVertex3fv(v3);
954         
955                                 if(v4) {
956                                         glTexCoord2fv(tface->uv[3]);
957                                         if (cp) glColor3ub(cp[15], cp[14], cp[13]);
958                                         if (mf_smooth) glNormal3sv(mvert[v4idx].no);
959                                         glVertex3fv(v4);
960                                 }
961                                 glEnd();
962                         }
963                 }
964                 
965                 /* switch off textures */
966                 set_tpage(0);
967         }
968
969         glShadeModel(GL_FLAT);
970         glDisable(GL_CULL_FACE);
971         
972         draw_hide_tfaces(ob, me);
973
974         if(ob==OBACT && (G.f & G_FACESELECT)) {
975                 draw_tfaces3D(ob, me);
976         }
977         
978                 /* XXX, bad patch - default_gl_light() calls
979                  * glLightfv(GL_LIGHT_POSITION, ...) which
980                  * is transformed by the current matrix... we
981                  * need to make sure that matrix is identity.
982                  * 
983                  * It would be better if drawmesh.c kept track
984                  * of and restored the light settings it changed.
985                  *  - zr
986                  */
987         glPushMatrix();
988         glLoadIdentity();       
989         default_gl_light();
990         glPopMatrix();
991 }
992
993 void init_realtime_GL(void)
994 {               
995         glMatrixMode(GL_TEXTURE);
996         glLoadIdentity();
997         glMatrixMode(GL_MODELVIEW);
998
999 }
1000