Minor Fixes:
[blender.git] / source / gameengine / GamePlayer / common / GPC_PolygonMaterial.cpp
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 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36
37 #ifdef WIN32
38 #include <windows.h>
39 #endif // WIN32
40 #ifdef __APPLE__
41 #include <OpenGL/gl.h>
42 #include <OpenGL/glu.h>
43 #else
44 #include <GL/gl.h>
45 #include <GL/glu.h>
46 #endif
47
48
49
50 #include "GPC_PolygonMaterial.h"
51 #include "MT_Vector3.h"
52 #include "RAS_IRasterizer.h"
53 #include "RAS_GLExtensionManager.h"
54
55 /* This list includes only data type definitions */
56 #include "DNA_object_types.h"
57 #include "DNA_material_types.h"
58 #include "DNA_image_types.h"
59 #include "DNA_lamp_types.h"
60 #include "DNA_group_types.h"
61 #include "DNA_scene_types.h"
62 #include "DNA_camera_types.h"
63 #include "DNA_property_types.h"
64 #include "DNA_text_types.h"
65 #include "DNA_sensor_types.h"
66 #include "DNA_controller_types.h"
67 #include "DNA_actuator_types.h"
68 #include "DNA_mesh_types.h"
69 #include "DNA_meshdata_types.h"
70 #include "DNA_view3d_types.h"
71 #include "DNA_world_types.h"
72
73 #include "BKE_global.h"
74 #include "BKE_image.h"
75 #include "BKE_mesh.h"
76
77 #include "MEM_guardedalloc.h"
78
79 #include "IMB_imbuf_types.h"
80 /* end of blender include block */
81
82 static Image *fCurpage=0;
83 static int fCurtile=0, fCurmode=0, fCurTileXRep=0, fCurTileYRep=0;
84 static short fTexWindx, fTexWindy, fTexWinsx, fTexWinsy;
85 static int fDoMipMap = 1;
86 static int fLinearMipMap=1;
87 static int fAlphamode= -1;
88
89 using namespace bgl;
90         /* (n&(n-1)) zeros the least significant bit of n */
91 static int is_pow2(int num) {
92         return ((num)&(num-1))==0;
93 }
94 static int smaller_pow2(int num) {
95         while (!is_pow2(num))
96                 num= num&(num-1);
97         return num;     
98 }
99
100 static void my_make_repbind(Image *ima)
101 {
102         if(ima==0 || ima->ibuf==0) return;
103
104         if(ima->repbind) {
105                 glDeleteTextures(ima->totbind, (GLuint*)ima->repbind);
106                 delete (ima->repbind);
107                 ima->repbind= 0;
108         }
109         ima->totbind= ima->xrep*ima->yrep;
110         if(ima->totbind>1) {
111                 ima->repbind= (unsigned int *) malloc(sizeof(int)*ima->totbind);
112                 for (int i=0;i<ima->totbind;i++)
113                         ((int*)ima->repbind)[i] = 0;
114         }
115 }
116
117
118 static int my_set_tpage(TFace *tface)
119 {       
120         static TFace *lasttface= 0;
121         Image *ima;
122         unsigned int *rect, *bind;
123         int tpx, tpy, tilemode, tileXRep,tileYRep;
124
125         /* disable */
126         if(tface==0) {
127                 if(lasttface==0) return 0;
128                 
129                 lasttface= 0;
130                 fCurtile= 0;
131                 fCurpage= 0;
132                 if(fCurmode!=0) {
133                         glMatrixMode(GL_TEXTURE);
134                         glLoadIdentity();
135                         glMatrixMode(GL_MODELVIEW);
136                 }
137                 fCurmode= 0;
138                 fCurTileXRep=0;
139                 fCurTileYRep=0;
140                 fAlphamode= -1;
141                 
142                 glDisable(GL_BLEND);
143                 glDisable(GL_TEXTURE_2D);
144                 glDisable(GL_TEXTURE_GEN_S);
145                 glDisable(GL_TEXTURE_GEN_T);
146                 return 0;
147         }
148         lasttface= tface;
149
150         if( fAlphamode != tface->transp) {
151                 fAlphamode= tface->transp;
152
153                 if(fAlphamode) {
154                         glEnable(GL_BLEND);
155                         
156                         if(fAlphamode==TF_ADD) {
157                                 glBlendFunc(GL_ONE, GL_ONE);
158                         /*      glBlendEquationEXT(GL_FUNC_ADD_EXT); */
159                         }
160                         else if(fAlphamode==TF_ALPHA) {
161                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
162                         /*      glBlendEquationEXT(GL_FUNC_ADD_EXT); */
163                         }
164                         /* else { */
165                         /*      glBlendFunc(GL_ONE, GL_ONE); */
166                         /*      glBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT); */
167                         /* } */
168                 }
169                 else glDisable(GL_BLEND);
170         }
171
172         ima= (struct Image *) tface->tpage;
173
174         /* Enable or disable environment mapping */
175         if (ima && (ima->flag & IMA_REFLECT)){
176
177                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
178                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
179
180                 glEnable(GL_TEXTURE_GEN_S);
181                 glEnable(GL_TEXTURE_GEN_T);
182         }
183         else{
184                 glDisable(GL_TEXTURE_GEN_S);
185                 glDisable(GL_TEXTURE_GEN_T);
186         }
187
188         tilemode= tface->mode & TF_TILES;
189         tileXRep = 0;
190         tileYRep = 0;
191         if (ima)
192         {
193                 tileXRep = ima->xrep;
194                 tileYRep = ima->yrep;
195         }
196
197
198         if(ima==fCurpage && fCurtile==tface->tile && tilemode==fCurmode && fCurTileXRep==tileXRep && fCurTileYRep == tileYRep) return ima!=0;
199
200         if(tilemode!=fCurmode || fCurTileXRep!=tileXRep || fCurTileYRep != tileYRep)
201         {
202                 glMatrixMode(GL_TEXTURE);
203                 glLoadIdentity();
204                 
205                 if(tilemode && ima!=0)
206                         glScalef(ima->xrep, ima->yrep, 1.0);
207
208                 glMatrixMode(GL_MODELVIEW);
209         }
210
211         if(ima==0 || ima->ok==0) {
212                 glDisable(GL_TEXTURE_2D);
213                 
214                 fCurtile= tface->tile;
215                 fCurpage= 0;
216                 fCurmode= tilemode;
217                 fCurTileXRep = tileXRep;
218                 fCurTileYRep = tileYRep;
219
220                 return 0;
221         }
222
223         if(ima->ibuf==0) {      
224                 load_image(ima, IB_rect, "", 0);
225                 
226                 if(ima->ibuf==0) {
227                         ima->ok= 0;
228
229                         fCurtile= tface->tile;
230                         fCurpage= 0;
231                         fCurmode= tilemode;
232                         fCurTileXRep = tileXRep;
233                         fCurTileYRep = tileYRep;
234                         
235                         glDisable(GL_TEXTURE_2D);
236                         return 0;
237                 }
238                 
239         }
240
241         if(ima->tpageflag & IMA_TWINANIM)       fCurtile= ima->lastframe;
242         else fCurtile= tface->tile;
243
244         if(tilemode) {
245                 
246                 if(ima->repbind==0) my_make_repbind(ima);
247                 
248                 if(fCurtile>=ima->totbind) fCurtile= 0;
249                 
250                 /* this happens when you change repeat buttons */
251                 if(ima->repbind) bind= ima->repbind+fCurtile;
252                 else bind= &ima->bindcode;
253                 
254                 if(*bind==0) {
255                         
256                         fTexWindx= ima->ibuf->x/ima->xrep;
257                         fTexWindy= ima->ibuf->y/ima->yrep;
258                         
259                         if(fCurtile>=ima->xrep*ima->yrep) fCurtile= ima->xrep*ima->yrep-1;
260         
261                         fTexWinsy= fCurtile / ima->xrep;
262                         fTexWinsx= fCurtile - fTexWinsy*ima->xrep;
263         
264                         fTexWinsx*= fTexWindx;
265                         fTexWinsy*= fTexWindy;
266         
267                         tpx= fTexWindx;
268                         tpy= fTexWindy;
269
270                         rect= ima->ibuf->rect + fTexWinsy*ima->ibuf->x + fTexWinsx;
271                 }
272         }
273         else {
274                 bind= &ima->bindcode;
275                 
276                 if(*bind==0) {
277                         tpx= ima->ibuf->x;
278                         tpy= ima->ibuf->y;
279                         rect= ima->ibuf->rect;
280                 }
281         }
282
283         if(*bind==0) {
284                 int rectw= tpx, recth= tpy;
285                 unsigned int *tilerect= NULL, *scalerect= NULL;
286
287                 /*
288                  * Maarten:
289                  * According to Ton this code is not needed anymore. It was used only
290                  * in really old Blenders.
291                  * Reevan:
292                  * Actually it is needed for backwards compatibility.  Simpledemo 6 does not display correctly without it.
293                  */
294 #if 1
295                  if (tilemode) {
296                         int y;
297                                 
298                         tilerect= (unsigned int*)MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect");
299                         for (y=0; y<recth; y++) {
300                                 unsigned int *rectrow= &rect[y*ima->ibuf->x];
301                                 unsigned int *tilerectrow= &tilerect[y*rectw];
302                                         
303                                 memcpy(tilerectrow, rectrow, tpx*sizeof(*rectrow));
304                         }
305                                 
306                         rect= tilerect;
307                 }
308 #endif
309                 if (!is_pow2(rectw) || !is_pow2(recth)) {
310                         rectw= smaller_pow2(rectw);
311                         recth= smaller_pow2(recth);
312                         
313                         scalerect= (unsigned int *)MEM_mallocN(rectw*recth*sizeof(*scalerect), "scalerect");
314                         gluScaleImage(GL_RGBA, tpx, tpy, GL_UNSIGNED_BYTE, rect, rectw, recth, GL_UNSIGNED_BYTE, scalerect);
315                         rect= scalerect;
316                 }
317
318                 glGenTextures(1, (GLuint*)bind);
319
320                 /*
321                 if(G.f & G_DEBUG) {
322                         printf("var1: %s\n", ima->id.name+2);
323                         printf("var1: %d, var2: %d\n", *bind, tpx);
324                         printf("var1: %d, var2: %d\n", fCurtile, tilemode);
325                 }
326                 */
327                 glBindTexture( GL_TEXTURE_2D, *bind);
328                 
329                 if (!fDoMipMap)
330                 {
331                         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,  rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
332                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
333                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
334                 } else
335                 {
336                         int minfilter= fLinearMipMap?GL_LINEAR_MIPMAP_LINEAR:GL_LINEAR_MIPMAP_NEAREST;
337                         
338                         gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect);
339                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minfilter);
340                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
341                 }
342
343                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
344
345                 if (tilerect)
346                         MEM_freeN(tilerect);
347                 if (scalerect)
348                         MEM_freeN(scalerect);
349         }
350         else glBindTexture( GL_TEXTURE_2D, *bind);
351         
352         
353
354         glEnable(GL_TEXTURE_2D);
355
356         fCurpage= ima;
357         fCurmode= tilemode;
358         fCurTileXRep = tileXRep;
359         fCurTileYRep = tileYRep;
360
361         return 1;
362 }
363
364
365 GPC_PolygonMaterial::GPC_PolygonMaterial(const STR_String& texname, bool ba, const STR_String& matname,
366                         int tile, int tileXrep, int tileYrep, int mode, bool transparant, bool zsort,
367                         int lightlayer, bool bIsTriangle, void* clientobject, void* tpage) :
368                         RAS_IPolyMaterial(texname, ba, matname, tile, tileXrep, tileYrep, mode,
369                         transparant, zsort, lightlayer, bIsTriangle, clientobject), m_tface((struct TFace*)tpage)
370 {
371         // clear local caching info
372         my_set_tpage(0);
373 }
374
375
376 GPC_PolygonMaterial::~GPC_PolygonMaterial(void)
377 {
378 }
379
380
381 void GPC_PolygonMaterial::Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingInfo) const
382 {
383         if (GetCachingInfo() != cachingInfo)
384         {
385                 if (!cachingInfo)
386                 {
387                         my_set_tpage(0);
388                 }
389                 cachingInfo = GetCachingInfo();
390
391                 if ((m_drawingmode & 4)&& (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) )
392                 {
393                         update_realtime_texture((struct TFace*) m_tface, rasty->GetTime());
394                         my_set_tpage(m_tface);
395                         rasty->EnableTextures(true);
396                 } else
397                 {
398                         my_set_tpage(0);
399                         rasty->EnableTextures(false);
400                 }
401         
402                 //TF_TWOSIDE == 512, todo, make this a ketsji enum
403                 if(m_drawingmode & 512) {
404                         rasty->SetCullFace(false);
405                 }
406                         
407                 else
408                 {
409                         rasty->SetCullFace(true);//glEnable(GL_CULL_FACE);
410                         //else glDisable(GL_CULL_FACE);
411                 }
412         }
413         rasty->SetSpecularity(m_specular[0],m_specular[1],m_specular[2],m_specularity);
414         rasty->SetShinyness(m_shininess);
415         rasty->SetDiffuse(m_diffuse[0], m_diffuse[1],m_diffuse[2], 1.0);
416 }
417
418
419 void GPC_PolygonMaterial::SetMipMappingEnabled(bool enabled)
420 {
421         fDoMipMap = enabled ? 1 : 0;
422 }