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