src/render/rTexture.cpp

Go to the documentation of this file.
00001 /*
00002 
00003 *************************************************************************
00004 
00005 ArmageTron -- Just another Tron Lightcycle Game in 3D.
00006 Copyright (C) 2000  Manuel Moos (manuel@moosnet.de)
00007 
00008 **************************************************************************
00009 
00010 This program is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 as published by the Free Software Foundation; either version 2
00013 of the License, or (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00023 
00024 ***************************************************************************
00025 
00026 */
00027 
00028 #include "rSDL.h"
00029 
00030 #include "aa_config.h"
00031 
00032 #include "rTexture.h"
00033 #include "rDisplayList.h"
00034 #include "tString.h"
00035 #include "rScreen.h"
00036 #include "tDirectories.h"
00037 #include "tLocale.h"
00038 #include "tConsole.h"
00039 #include "tException.h"
00040 #include "tResourceManager.h"
00041 
00042 #include <sstream>
00043 
00044 #ifndef DEDICATED
00045 #include "rRender.h"
00046 #include "rGL.h"
00047 
00048 // Load the right SDL_IMAGE header
00049 
00050 #ifdef _MSC_VER
00051 #include <SDL_image.h>
00052 #else
00053 #ifdef __MINGW32__
00054 #include <SDL_image.h>
00055 #else
00056 #ifdef HAVE_SDL_IMG_H
00057 #include <SDL_image.h>
00058 #else
00059 #ifdef HAVE_SDL_SDL_IMAGE_H
00060 #include <SDL/SDL_image.h>
00061 #else
00062 #ifdef HAVE_IMG_H
00063 #include <IMG.h>
00064 #else
00065 #ifdef HAVE_SDL_IMG_H
00066 #include <SDL/IMG.h>
00067 #else
00068 #ifdef HAVE_LIBSDL
00069 #include <SDL_image.h>
00070 #else
00071 #ifdef HAVE_LIBIMG
00072 #include <IMG.h>
00073 #else
00074 // if the following include ( or one of the earlier ones ) fails, you don't have SDL_image properly installed.
00075 #include <SDL_image.h>
00076 #endif
00077 #endif
00078 #endif
00079 #endif
00080 #endif
00081 #endif
00082 #endif
00083 #endif
00084 #endif
00085 
00086 // MS OpenGL headers don't include this define
00087 #ifndef GL_CLAMP_TO_EDGE
00088 #define GL_CLAMP_TO_EDGE GL_CLAMP
00089 #endif
00090 
00091 // ******************************************************************************************
00092 // *
00093 // *    rSurface
00094 // *
00095 // ******************************************************************************************
00099 // ******************************************************************************************
00100 
00101 rSurface::rSurface( char const * fileName, tPath const * path )
00102 {
00103     Init();
00104     Create( fileName, path );
00105 }
00106 
00107 // ******************************************************************************************
00108 // *
00109 // *    ~rSurface
00110 // *
00111 // ******************************************************************************************
00114 // ******************************************************************************************
00115 
00116 rSurface::~rSurface( void )
00117 {
00118     Clear();
00119 }
00120 
00121 // ******************************************************************************************
00122 // *
00123 // *    rSurface
00124 // *
00125 // ******************************************************************************************
00128 // ******************************************************************************************
00129 
00130 rSurface::rSurface( void )
00131 {
00132     Init();
00133 }
00134 
00135 // ******************************************************************************************
00136 // *
00137 // *   rSurface
00138 // *
00139 // ******************************************************************************************
00143 // ******************************************************************************************
00144 
00145 rSurface::rSurface( rSurface const & other )
00146 {
00147     Init();
00148     CopyFrom( other );
00149 }
00150 
00151 // ******************************************************************************************
00152 // *
00153 // *   operator =
00154 // *
00155 // ******************************************************************************************
00160 // ******************************************************************************************
00161 
00162 rSurface & rSurface::operator =( rSurface const & other )
00163 {
00164     if ( &other != this )
00165     {
00166         Clear();
00167         CopyFrom( other );
00168     }
00169 
00170     return *this;
00171 }
00172 
00173 // ******************************************************************************************
00174 // *
00175 // *    Init
00176 // *
00177 // ******************************************************************************************
00180 // ******************************************************************************************
00181 
00182 void rSurface::Init( void )
00183 {
00184     surface_ = 0;
00185     format_ = 0;
00186 }
00187 
00188 // ******************************************************************************************
00189 // *
00190 // *   Clear
00191 // *
00192 // ******************************************************************************************
00195 // ******************************************************************************************
00196 
00197 void rSurface::Clear( void )
00198 {
00199 #ifndef DEDICATED
00200     // delete surface
00201     if ( surface_ )
00202         SDL_FreeSurface( surface_ );
00203 
00204 #endif
00205     surface_ = 0;
00206 }
00207 
00208 // ******************************************************************************************
00209 // *
00210 // *    Create
00211 // *
00212 // ******************************************************************************************
00216 // ******************************************************************************************
00217 
00218 void rSurface::Create( char const * fileName, tPath const *path )
00219 {
00220 #ifndef DEDICATED
00221     sr_LockSDL();
00222 
00223     IMG_InvertAlpha(true);
00224 
00225     // find path of image and load it
00226     SDL_Surface *surface;
00227     if(path) {
00228         tString s = path->GetReadPath( fileName );
00229         surface = IMG_Load(s);
00230     } else {
00231         surface = IMG_Load(fileName);
00232     }
00233     Create(surface);
00234 
00235     //if ( surface_ )
00236     //    std::cerr << "loaded surface " << fileName << "\n";
00237 
00238     sr_UnlockSDL();
00239 #endif
00240 }
00241 
00242 // ******************************************************************************************
00243 // *
00244 // *    Create
00245 // *
00246 // ******************************************************************************************
00250 // ******************************************************************************************
00251 
00252 void rSurface::Create( SDL_Surface * surface )
00253 {
00254 #ifndef DEDICATED
00255     // clear previous surface
00256     Clear();
00257 
00258     // take ownership
00259     surface_ = surface;
00260 
00261     // determine texture format
00262     if ( surface_ )
00263     {
00264         switch (surface_->format->BytesPerPixel){
00265         case 1:
00266             format_ = GL_LUMINANCE;
00267             break;
00268 
00269         case 2:
00270             format_ = GL_LUMINANCE8_ALPHA8;
00271             break;
00272 
00273         case 3:
00274             format_ = GL_RGB;
00275             break;
00276 
00277         case 4:
00278             format_ = GL_RGBA;
00279             break;
00280 
00281         default:
00282             {
00283                 // fallback: convert the texture into a known format.
00284 
00285                 SDL_Surface *dummy =
00286                     SDL_CreateRGBSurface(SDL_SWSURFACE, 1, 1,
00287                                          32,
00288                                          0x0000FF, 0x00FF00,
00289                                          0xFF0000 ,0xFF000000);
00290 
00291                 SDL_Surface *convtex =
00292                     SDL_ConvertSurface(surface_, dummy->format, SDL_SWSURFACE);
00293 
00294                 SDL_FreeSurface(surface_);
00295                 surface_ = convtex;
00296                 SDL_FreeSurface(dummy);
00297 
00298                 format_ = GL_RGBA;
00299             }
00300             break;
00301         }
00302     }
00303 #endif
00304 }
00305 
00306 // ******************************************************************************************
00307 // *
00308 // *    CopyFrom
00309 // *
00310 // ******************************************************************************************
00314 // ******************************************************************************************
00315 
00316 void rSurface::CopyFrom( rSurface const & other )
00317 {
00318 #ifndef DEDICATED
00319     tASSERT( 0 == surface_ );
00320     tASSERT( other.surface_ );
00321 
00322     // copy surface
00323     surface_ = SDL_ConvertSurface(other.surface_, other.surface_->format, SDL_SWSURFACE);
00324 
00325     // copy flags
00326     format_ = other.format_;
00327 #endif
00328 }
00329 
00330 // ******************************************************************************************
00331 // *
00332 // *    ~rITexture
00333 // *
00334 // ******************************************************************************************
00337 // ******************************************************************************************
00338 
00339 rITexture::~rITexture( void )
00340 {
00341     s_textures_.Remove(this,id_);
00342 }
00343 
00344 // ******************************************************************************************
00345 // *
00346 // *    UnloadAll
00347 // *
00348 // ******************************************************************************************
00351 // ******************************************************************************************
00352 
00353 void rITexture::UnloadAll( void )
00354 {
00355     for(int i=s_textures_.Len()-1;i>=0;i--)
00356     {
00357         s_textures_(i)->Unload();
00358     }
00359 }
00360 
00361 // ******************************************************************************************
00362 // *
00363 // *    LoadAll
00364 // *
00365 // ******************************************************************************************
00368 // ******************************************************************************************
00369 
00370 void rITexture::LoadAll( void )
00371 {
00372     // s_reportErrors=false;
00373     for(int i=s_textures_.Len()-1;i>=0;i--)
00374     {
00375         s_textures_(i)->Select();
00376         //if (i>=s_textures.Len())
00377         //    i=s_textures.Len()-1;
00378     }
00379     // s_reportErrors=true;
00380 }
00381 
00382 // ******************************************************************************************
00383 // *
00384 // *    rITexture
00385 // *
00386 // ******************************************************************************************
00389 // ******************************************************************************************
00390 
00391 rITexture::rITexture( void )
00392         : id_( -1 )
00393 {
00394 }
00395 
00396 // ******************************************************************************************
00397 // *
00398 // *    OnSelect
00399 // *
00400 // ******************************************************************************************
00404 // ******************************************************************************************
00405 
00406 void rITexture::OnSelect( bool enforce )
00407 {
00408     if ( id_ < 0 )
00409         s_textures_.Add(this,id_);
00410 }
00411 
00412 // ******************************************************************************************
00413 // *
00414 // *    OnUnload
00415 // *
00416 // ******************************************************************************************
00419 // ******************************************************************************************
00420 
00421 void rITexture::OnUnload( void )
00422 {
00423 }
00424 
00425 // ******************************************************************************************
00426 // *
00427 // *    rISurfaceTexture
00428 // *
00429 // ******************************************************************************************
00436 // ******************************************************************************************
00437 
00438 rISurfaceTexture::rISurfaceTexture( int group, bool repx, bool repy, bool storeAlpha )
00439         : group_( group ), textureModeLast_( -1), repx_( repx ), repy_( repy ), storeAlpha_( storeAlpha )
00440 {
00441 }
00442 
00443 // ******************************************************************************************
00444 // *
00445 // *    ~rISurfaceTexture
00446 // *
00447 // ******************************************************************************************
00450 // ******************************************************************************************
00451 
00452 rISurfaceTexture::~rISurfaceTexture( void )
00453 {
00454     if (tint_.IsValid() )
00455     {
00456         rDisplayList::ClearAll();
00457     }
00458 }
00459 
00460 // ******************************************************************************************
00461 // *
00462 // *    ProcessImage
00463 // *
00464 // ******************************************************************************************
00468 // ******************************************************************************************
00469 
00470 void rISurfaceTexture::ProcessImage( SDL_Surface * surface )
00471 {
00472 }
00473 
00474 // ******************************************************************************************
00475 // *
00476 // *    Upload
00477 // *
00478 // ******************************************************************************************
00482 // ******************************************************************************************
00483 
00484 void rISurfaceTexture::Upload( rSurface & surface )
00485 {
00486 #ifndef DEDICATED
00487     sr_LockSDL();
00488     GLenum texformat = surface.GetFormat();
00489     SDL_Surface * tex = surface.GetSurface();
00490     tASSERT( tex );
00491 
00492     bool texalpha=tex->format->Amask;
00493 
00494     ProcessImage(tex);
00495 
00496     if(repx_)
00497         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
00498     else
00499         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
00500     if(repy_)
00501         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
00502     else
00503         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
00504 
00505     int format;
00506     if (sr_texturesTruecolor)
00507         if (storageHack_ || ( storeAlpha_ && texalpha ) )
00508             format=GL_RGBA8;
00509         else
00510             format=GL_RGB8;
00511     else
00512         if (storageHack_ || ( storeAlpha_ && texalpha ) )
00513             format=GL_RGBA4;
00514         else
00515             format=GL_RGB5;
00516 
00517     gluBuild2DMipmaps(GL_TEXTURE_2D,format,tex->w,tex->h,
00518                       texformat,GL_UNSIGNED_BYTE,tex->pixels);
00519 
00520     sr_UnlockSDL();
00521  #endif
00522 }
00523 
00524 // ******************************************************************************************
00525 // *
00526 // *    OnSelect
00527 // *
00528 // ******************************************************************************************
00532 // ******************************************************************************************
00533 
00534 void rISurfaceTexture::OnSelect( bool enforce )
00535 {
00536 #ifndef DEDICATED
00537     if(sr_glOut)
00538     {
00539         RenderEnd(true);
00540 
00541         int texmod=rTextureGroups::TextureMode[group_];
00542         if (enforce && texmod<0) texmod=GL_NEAREST_MIPMAP_NEAREST;
00543 
00544         if(textureModeLast_!=texmod)
00545         {
00546             // unload texture if the mode changed
00547             Unload();
00548             // std::cerr << "loading texture " << fileName << ':' << tint << "\n";
00549 
00550             if (texmod>0){
00551                 // don't generate textures inside display lists
00552                 rDisplayList::Cancel();
00553 
00554                 glBindTexture(GL_TEXTURE_2D,tint_);
00555 
00556                 if (textureModeLast_<0)
00557                 {
00558                     // delegate core loading work to derived class
00559                     OnSelect();
00560                 }
00561 
00562                 //glEnable(GL_TEXTURE);
00563                 glEnable(GL_TEXTURE_2D);
00564 
00565                 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,
00566                                 texmod);
00567 
00568                 switch(texmod)
00569                 {
00570                 case GL_NEAREST:
00571                 case GL_NEAREST_MIPMAP_NEAREST:
00572                     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,
00573                                     GL_NEAREST);
00574                     break;
00575                 default:
00576                     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,
00577                                     GL_LINEAR);
00578                     break;
00579                 }
00580 
00581             }
00582             else
00583             {
00584                 glDisable(GL_TEXTURE_2D);
00585             }
00586         }
00587         else
00588         {
00589             glBindTexture(GL_TEXTURE_2D,tint_);
00590             if (texmod>0)
00591             {
00592                 glEnable(GL_TEXTURE_2D);
00593             }
00594             else
00595             {
00596                 glDisable(GL_TEXTURE_2D);
00597             }
00598         }
00599         textureModeLast_=texmod;
00600     }
00601     rITexture::OnSelect(enforce);
00602 #endif
00603 }
00604 
00605 // ******************************************************************************************
00606 // *
00607 // * OnSelect
00608 // *
00609 // ******************************************************************************************
00614 // ******************************************************************************************
00615 
00616 void rISurfaceTexture::OnSelect()
00617 {
00618 }
00619 
00620 // ******************************************************************************************
00621 // *
00622 // *    OnUnload
00623 // *
00624 // ******************************************************************************************
00627 // ******************************************************************************************
00628 
00629 void rISurfaceTexture::OnUnload( void )
00630 {
00631 #ifndef DEDICATED
00632     if ( tint_.IsValid() )
00633     {
00634         rDisplayList::ClearAll();
00635     }
00636 
00637     tint_.Delete();
00638     textureModeLast_=-100;
00639     rITexture::OnUnload();
00640 #endif
00641 }
00642 
00643 // ******************************************************************************************
00644 // *
00645 // *    StoreAlpha
00646 // *
00647 // ******************************************************************************************
00650 // ******************************************************************************************
00651 
00652 void rISurfaceTexture::StoreAlpha( void )
00653 {
00654     storeAlpha_ = true;
00655 }
00656 
00657 // ******************************************************************************************
00658 // *
00659 // *    rFileTexture
00660 // *
00661 // ******************************************************************************************
00669 // ******************************************************************************************
00670 
00671 rFileTexture::rFileTexture( int group, char const * fileName, bool repx, bool repy, bool storeAlpha, tPath const *path )
00672         : rISurfaceTexture( group, repx, repy, storeAlpha )
00673         ,  fileName_( fileName )
00674         ,  path_(path)
00675 {
00676 }
00677 
00678 // ******************************************************************************************
00679 // *
00680 // *    ~rFileTexture
00681 // *
00682 // ******************************************************************************************
00685 // ******************************************************************************************
00686 
00687 rFileTexture::~rFileTexture( void )
00688 {
00689 }
00690 
00691 // ******************************************************************************************
00692 // *
00693 // *    OnSelect
00694 // *
00695 // ******************************************************************************************
00698 // ******************************************************************************************
00699 
00700 void rFileTexture::OnSelect()
00701 {
00702 #ifndef DEDICATED
00703     // std::cerr << "loading texture " << fileName_ << "\n";
00704     rSurface surface( fileName_, path_ );
00705     if ( surface.GetSurface() )
00706     {
00707         this->Upload( surface );
00708     }
00709     else if (s_reportErrors_)
00710     {
00711         throw tGenericException( tOutput( "$texture_error_filenotfound", fileName_ ), tOutput("$texture_error_filenotfound_title") );
00712     }
00713     rISurfaceTexture::OnSelect();
00714 #endif
00715 }
00716 
00717 // ******************************************************************************************
00718 // *
00719 // *    rSurfaceTexture
00720 // *
00721 // ******************************************************************************************
00729 // ******************************************************************************************
00730 
00731 rSurfaceTexture::rSurfaceTexture( int group, rSurface const & surface, bool repx, bool repy, bool storeAlpha )
00732         : rISurfaceTexture( group, repx, repy, storeAlpha )
00733         , surface_( surface )
00734 {
00735 }
00736 
00737 // ******************************************************************************************
00738 // *
00739 // *    ~rSurfaceTexture
00740 // *
00741 // ******************************************************************************************
00744 // ******************************************************************************************
00745 
00746 rSurfaceTexture::~rSurfaceTexture( void )
00747 {
00748 }
00749 
00750 // ******************************************************************************************
00751 // *
00752 // *    OnSelect
00753 // *
00754 // ******************************************************************************************
00757 // ******************************************************************************************
00758 
00759 void rSurfaceTexture::OnSelect()
00760 {
00761 #ifndef DEDICATED
00762     // upload a copy of the surface ( it may get modified )
00763     if ( surface_.GetSurface() )
00764     {
00765         rSurface copy( surface_ );
00766         this->Upload( copy );
00767         rISurfaceTexture::OnSelect();
00768     }
00769 #endif
00770 }
00771 
00772 
00773 bool rISurfaceTexture::s_reportErrors_=false;
00774 tList<rITexture> rITexture::s_textures_;
00775 
00776 int rTextureGroups::TextureMode[rTextureGroups::TEX_GROUPS];
00777 
00778 char const * rTextureGroups::TextureGroupDescription[rTextureGroups::TEX_GROUPS]=
00779     {
00780         "$texture_mode_0_help",
00781         "$texture_mode_1_help",
00782         "$texture_mode_2_help",
00783         "$texture_mode_3_help",
00784     };
00785 
00786 bool rISurfaceTexture::storageHack_ = false;
00787 
00788 //rTexture ArmageTron_eWall("wWall.png",1,0);
00789 //rTexture ArmageTron_dir_eWall("wall.png",1,0);
00790 
00791 
00792 static rCallbackBeforeScreenModeChange unload(&rITexture::UnloadAll);
00793 
00794 // static rCallbackAfterScreenModeChange load(&rITexture::LoadAll);
00795 
00796 rResourceTexture::texlist_t rResourceTexture::textures;
00797 
00798 rResourceTexture::rResourceTexture(tResourcePath const &path, bool repx, bool repy) : repx_(repx), repy_(repy) {
00799     if(!path.Valid()) {
00800         tex_ = 0;
00801         return;
00802     }
00803     for(texlist_t::iterator iter = textures.begin(); iter != textures.end(); ++iter) {
00804         if((*iter)->path_ == path) {
00805             tex_ = *iter;
00806             tex_->Use();
00807             return;
00808         }
00809     }
00810     tex_ = new tex_t(path);
00811 }
00812 
00813 rResourceTexture::InternalTex::InternalTex(tResourcePath const &path) : rFileTexture(rTextureGroups::TEX_OBJ, tResourceManager::locateResource(path.Path().c_str()).c_str(), true, true, true, 0), use_(1), path_(path) {
00814     textures.push_back(this);
00815 }
00816 
00817 void rResourceTexture::InternalTex::Release() {
00818     if(--use_ < 1) {
00819         for(texlist_t::iterator iter = textures.begin(); iter != textures.end(); ++iter) {
00820             if((*iter)->path_ == path_) {
00821                 textures.erase(iter);
00822                 break;
00823             }
00824         }
00825         Unload();
00826         delete this;
00827     }
00828 }
00829 
00830 rResourceTexture &rResourceTexture::operator=(rResourceTexture const &other) {
00831     if(tex_ != other.tex_) {
00832         repx_ = other.repx_;
00833         repy_ = other.repy_;
00834         if(tex_) {
00835             tex_->Release();
00836         }
00837         tex_ = other.tex_;
00838         if(tex_) {
00839             tex_->Use();
00840         }
00841     }
00842     return *this;
00843 }
00844 
00845 void rResourceTexture::Select() {
00846 #ifndef DEDICATED
00847     if(tex_) {
00848         tex_->Select();
00849         // Override the actual tecture's settings
00850         if(repx_)
00851             glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
00852         else
00853             glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
00854         if(repy_)
00855             glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
00856         else
00857             glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
00858     } else {
00859         tERR_WARN("Trying to select a resource texture that's not loaded");
00860     }
00861 #endif
00862 }

Generated on Sat Mar 15 22:55:53 2008 for Armagetron Advanced by  doxygen 1.5.4