/* ************************************************************************* ArmageTron -- Just another Tron Lightcycle Game in 3D. Copyright (C) 2000 Manuel Moos (manuel@moosnet.de) ************************************************************************** This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *************************************************************************** */ #include "config.h" #include "rTexture.h" #include "tString.h" #include "rScreen.h" #include "tDirectories.h" #include "tLocale.h" #ifndef DEDICATED #include "rRender.h" #include "rGL.h" #include "rSDL.h" // Load the right SDL_IMAGE header #ifdef _MSC_VER #include #else #ifdef HAVE_SDL_IMG_H #include #else #ifdef HAVE_SDL_SDL_IMAGE_H #include #else #ifdef HAVE_IMG_H #include #else #ifdef HAVE_SDL_IMG_H #include #else #ifdef HAVE_LIBSDL #include #else #ifdef HAVE_LIBIMG #include #else // if the following include ( or one of the earlier ones ) fails, you don't have SDL_image properly installed. #include #endif #endif #endif #endif #endif #endif #endif #endif bool rTexture::s_reportErrors=false;//true; tList rTexture::s_textures; int TextureMode[rTEX_GROUPS]; char *TextureGroupDescription[rTEX_GROUPS]={ "$texture_mode_0_help", "$texture_mode_1_help", "$texture_mode_2_help", "$texture_mode_3_help", }; bool sr_storageHack = false; //rTexture ArmageTron_eWall("wWall.png",1,0); //rTexture ArmageTron_dir_eWall("wall.png",1,0); rTexture::rTexture(int g,const char *f,bool rx,bool ry,bool s_a) :group(g),id(-1),textureModeLast(-100), repx(rx),repy(ry),fileName(f),used(false),loaded(false){ //std::cerr << "creating texture " << f << "\n"; // storeAlpha=s_a; storeAlpha=true; } void rTexture::StoreAlpha(){ if (!storeAlpha){ storeAlpha=true; Unload(); } } rTexture::~rTexture(){ Unload(); //std::cerr << "deleting texture " << fileName << "\n"; int oldid = id; s_textures.Remove(this,id); if (oldid < s_textures.Len() && oldid > 0) s_textures(oldid)->Unload(); } void rTexture::Unload(){ #ifndef DEDICATED if (sr_glOut && used){ //std::cerr << "unloading texture " << fileName << ':' << tint << "\n"; glBindTexture(GL_TEXTURE_2D,tint); glDeleteTextures(1,&tint); } used=0; textureModeLast=-100; #endif } void rTexture::Select(bool enforce){ #ifndef DEDICATED if(sr_glOut){ if (id<0) s_textures.Add(this,id); int texmod=::TextureMode[group]; if (enforce && texmod<0) texmod=GL_NEAREST_MIPMAP_NEAREST; if(!used || static_cast(id) != tint || textureModeLast!=texmod){ if ((used && (static_cast(id) != tint) || (textureModeLast>0 && texmod<0))) glDeleteTextures(1,&tint); if (texmod>0){ tint=static_cast(id); RenderEnd(true); glBindTexture(GL_TEXTURE_2D,tint); if (!used || textureModeLast<0){ sr_LockSDL(); tString s = tDirectories::Data().GetReadPath( fileName ); used=1; // quick hack using SDL and IMG-Lib... IMG_InvertAlpha(true); SDL_Surface *tex=IMG_Load(s); if (tex){ loaded = true; GLenum texformat; // int i; bool texalpha=tex->format->Amask; switch (tex->format->BytesPerPixel){ case 1: texformat = GL_LUMINANCE; break; case 2: texformat = GL_LUMINANCE8_ALPHA8; break; case 3: texformat = GL_RGB; break; case 4: texformat = GL_RGBA; break; default: { // fallback: convert the texture into a known format. SDL_Surface *dummy = SDL_CreateRGBSurface(SDL_SWSURFACE, 1, 1, 32, 0x0000FF, 0x00FF00, 0xFF0000 ,0xFF000000); SDL_Surface *convtex = SDL_ConvertSurface(tex, dummy->format, SDL_SWSURFACE); SDL_FreeSurface(tex); tex = convtex; SDL_FreeSurface(dummy); texformat = GL_RGBA; } break; } ProcessImage(tex); if(repx) glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); else glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP); if(repy) glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); else glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP); int format; if (sr_texturesTruecolor) if (sr_storageHack || ( storeAlpha && texalpha ) ) format=GL_RGBA8; else format=GL_RGB8; else if (sr_storageHack || ( storeAlpha && texalpha ) ) format=GL_RGBA4; else format=GL_RGB5; gluBuild2DMipmaps(GL_TEXTURE_2D,format,tex->w,tex->h, texformat,GL_UNSIGNED_BYTE,tex->pixels); SDL_FreeSurface(tex); } else { if (s_reportErrors) { tERR_ERROR("\n\nTexture file " << fileName << " could not be loaded. Are you \n" "running " << tOutput("$program_name") << " from the right directory?\n\n"); } } sr_UnlockSDL(); } //glEnable(GL_TEXTURE); glEnable(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, texmod); switch(texmod){ case GL_NEAREST: case GL_NEAREST_MIPMAP_NEAREST: glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_NEAREST); break; default: glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR); break; } } else{ //glDisable(GL_TEXTURE); glDisable(GL_TEXTURE_2D); } } else{ glBindTexture(GL_TEXTURE_2D,tint); if (texmod>0){ // glEnable(GL_TEXTURE); glEnable(GL_TEXTURE_2D); } else{ // glDisable(GL_TEXTURE); glDisable(GL_TEXTURE_2D); } } textureModeLast=texmod; } #endif } void rTexture::UnloadAll(){ for(int i=s_textures.Len()-1;i>=0;i--) s_textures(i)->Unload(); } void rTexture::LoadAll(){ s_reportErrors=false; for(int i=s_textures.Len()-1;i>=0;i--){ s_textures(i)->Select(); if (i>=s_textures.Len()) i=s_textures.Len()-1; } s_reportErrors=true; } void rTexture::SetIcon(){ #ifndef DEDICATED SDL_Surface *tex=IMG_Load("textures/icon.png"); if (tex) SDL_WM_SetIcon(tex,NULL); #endif } static rCallbackBeforeScreenModeChange unload(&rTexture::UnloadAll); static rCallbackAfterScreenModeChange load(&rTexture::LoadAll);