Main Page | Class Hierarchy | Class List | Directories | File List | Class Members | Related Pages

texture.cpp

00001 /***************************************************************************
00002                         texture.cpp    -  description
00003                             -------------------
00004     begin                : ven 2 jui 2004
00005     copyright            : (C) 2004-2006 by Duong-Khang NGUYEN
00006     email                : neoneurone @ users sourceforge net
00007     
00008     $Id: texture.cpp 63 2006-10-17 20:45:12Z neoneurone $
00009  ***************************************************************************/
00010 
00011 /***************************************************************************
00012  *                                                                         *
00013  *   This program is free software; you can redistribute it and/or modify  *
00014  *   it under the terms of the GNU General Public License as published by  *
00015  *   the Free Software Foundation; either version 2 of the License, or     *
00016  *   any later version.                                                    *
00017  *                                                                         *
00018  ***************************************************************************/
00019 
00020 #include "texture.h"
00021 
00022 #include "SDL_image.h"
00023 
00024 
00025    /*=====================================================================*/
00026 Texture::Texture():
00027 uiWidth( 0 ),
00028 uiHeight( 0 ),
00029 uiTexture( 0 )
00030 {
00031     OPENCITY_DEBUG("ctor");
00032 }
00033 
00034 
00035    /*=====================================================================*/
00036 Texture::Texture( const string & rcFile )
00037 {
00038     OPENCITY_DEBUG("param ctor");
00039     this->uiTexture = Texture::Load( rcFile, this->uiWidth, this->uiHeight );
00040 }
00041 
00042 
00043    /*=====================================================================*/
00044 Texture::~Texture()
00045 {
00046     OPENCITY_DEBUG("dtor");
00047 
00048 // Silently ignore invalid texture
00049     glDeleteTextures( 1, &this->uiTexture );
00050 }
00051 
00052 
00053    //========================================================================
00054    //                       PRIVATE STATIC METHODS
00055    //========================================================================
00056 const GLuint
00057 Texture::Load( const string & rcFile )
00058 {
00059     uint w, h;
00060     return Texture::Load( rcFile, w, h );
00061 }
00062 
00063 
00064    /*=====================================================================*/
00065 const GLuint
00066 Texture::Load
00067 (
00068     const string & rcFile,
00069     uint & ruiW,
00070     uint & ruiH
00071 )
00072 {
00073     SDL_Surface* pImage = NULL;
00074     SDL_Surface* pMirror = NULL;
00075     GLuint uiTexture = 0;   // tell glIsTexture that this is not a texture name
00076 
00077     OPENCITY_DEBUG( rcFile.c_str() );
00078 
00079 // TODO: error checking
00080 // load the image to the SDL surface
00081     pImage = IMG_Load( rcFile.c_str() );
00082     assert( pImage != NULL );
00083 
00084 // Return the width and height
00085     ruiW = pImage->w;
00086     ruiH = pImage->h;
00087 
00088 // Check the bytes per pixel
00089 //  cout << "Bytes per pixel: " << (int)pImage->format->BytesPerPixel << endl;
00090     assert( pImage->format->BytesPerPixel == 4 );
00091 
00092 // note: the texture coordinates are flipped in the vertical direction
00093 //       because the SDL_image library reads the image's pixels
00094 //       from the upper left corner, left to right, to the bottom right
00095 //       corner whereas the glTexImage2D builds the texture from
00096 //       the bottom left corner, left to right, to the upper right corner
00097 // Take the horizontal mirror of current image
00098 //  pMirror = Texture::HorizontalMirror( pConverted );
00099     pMirror = Texture::HorizontalMirror( pImage );
00100 
00101 // convert the surface to texture
00102 // create the new texture if needed
00103     Texture::Surface2Texture( pMirror, uiTexture );
00104     SDL_FreeSurface( pImage );
00105     SDL_FreeSurface( pMirror );
00106 
00107     return uiTexture;
00108 }
00109 
00110 
00111    /*=====================================================================*/
00112 SDL_Surface*
00113 Texture::HorizontalMirror(
00114     const SDL_Surface* const psurface
00115 )
00116 {
00117     SDL_Surface* psNew = NULL;
00118     int h, iBytesPerRow;
00119     OC_CHAR* pPixelDest;
00120     OC_CHAR* pPixelSrc;
00121 
00122 // IF the surface needs locking THEN
00123     if (SDL_MUSTLOCK( psurface )) {
00124         SDL_LockSurface( const_cast<SDL_Surface*>(psurface) );
00125     }
00126 
00127 // Create the new surface, then lock it
00128     psNew = SDL_CreateRGBSurface(
00129         SDL_SWSURFACE,
00130         psurface->w,
00131         psurface->h,
00132         psurface->format->BitsPerPixel,
00133         psurface->format->Rmask,
00134         psurface->format->Gmask,
00135         psurface->format->Bmask,
00136         psurface->format->Amask );
00137     assert( psNew != NULL );
00138     SDL_LockSurface( psNew );
00139 
00140 // Variables initialization
00141     iBytesPerRow = psurface->w * psurface->format->BytesPerPixel;
00142     pPixelDest = (OC_CHAR*)psNew->pixels;
00143     pPixelSrc = (OC_CHAR*)psurface->pixels + ((psurface->h-1) * iBytesPerRow);
00144 //debug cout << "BPR: " << iBytesPerRow << endl;
00145 
00146 // Copy the pixels
00147     for ( h = psurface->h-1; h >= 0; h-- ) {
00148         memcpy( pPixelDest, pPixelSrc, iBytesPerRow );
00149         pPixelDest += iBytesPerRow;
00150         pPixelSrc -= iBytesPerRow;
00151 //debug cout << "bla: " << h << endl;
00152     }
00153 
00154     SDL_UnlockSurface( psNew );
00155 
00156 // IF the surface needs locking THEN
00157     if (SDL_MUSTLOCK( psurface )) {
00158         SDL_UnlockSurface( const_cast<SDL_Surface*>(psurface) );
00159     }
00160 
00161     return psNew;
00162 }
00163 
00164 
00165    /*=====================================================================*/
00166 void
00167 Texture::Surface2Texture(
00168     const SDL_Surface* const psurface,
00169     GLuint & ruiTexture )
00170 {
00171     uint glW, glH;
00172     void* pPixels = NULL;
00173 
00174 // delete the existing texture
00175     if (glIsTexture( ruiTexture ) == GL_TRUE)
00176         glDeleteTextures( 1, &ruiTexture );
00177 
00178 // create the texture to hold the image
00179     glGenTextures( 1, &ruiTexture );
00180     glBindTexture( GL_TEXTURE_2D, ruiTexture );
00181 //  glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
00182     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00183     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00184     //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00185     //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00186 
00187 //debug cout << "Tex W: " << psurface->w << " / H: " << psurface->h << endl;
00188 
00189     SDL_LockSurface( const_cast<SDL_Surface*>(psurface) );
00190 
00191 // Fix the image size
00192     Texture::GetCorrectSize( psurface->w, psurface->h, glW, glH );
00193 
00194 // If the image doesn't have the correct size then scale it before converting
00195     if ((psurface->w != (int)glW) || (psurface->h != (int)glH)) {
00196         OPENCITY_DEBUG("Texture's size has been fixed");
00197         pPixels = malloc( glW * glH * psurface->format->BytesPerPixel );
00198 
00199     // Scale the input image
00200         (void)gluScaleImage(
00201             GL_RGBA,            // Image format
00202             psurface->w,        // The image's size
00203             psurface->h,
00204             GL_UNSIGNED_BYTE,   // The data type of the input pixel
00205             psurface->pixels,   // The pixels' data
00206             glW,                // The wanted scaled image's size
00207             glH,
00208             GL_UNSIGNED_BYTE,   // The data type of the output pixel
00209             pPixels             // The pointer which will holds the output data
00210         );
00211 
00212     // Convert the scaled image to texture
00213         glTexImage2D(
00214             GL_TEXTURE_2D,      // texture 2D
00215             0,                  // base image
00216             GL_RGBA,            // internal format
00217             glW,                // texture width, must be 2n >= 64
00218             glH,                // texture height, must be 2n >= 64
00219             0,                  // no border
00220             GL_RGBA,            // pixel format
00221             GL_UNSIGNED_BYTE,   // pixel data format
00222             pPixels             // point to the pixels' data
00223             );
00224 
00225         free( pPixels );
00226         pPixels = NULL;         // Safe
00227     }
00228     else {
00229     // Convert the surface to the OpenGL texture
00230         glTexImage2D(
00231             GL_TEXTURE_2D,      // texture 2D
00232             0,                  // base image
00233             GL_RGBA,            // internal format
00234             psurface->w,        // texture width, must be 2n >= 64
00235             psurface->h,        // texture height, must be 2n >= 64
00236             0,                  // no border
00237             GL_RGBA,            // pixel format
00238             GL_UNSIGNED_BYTE,   // pixel data format
00239             psurface->pixels    // point to the pixels' data
00240             );
00241     }
00242 
00243     SDL_UnlockSurface( const_cast<SDL_Surface*>(psurface) );
00244 
00245 // GL error checking
00246     GLenum glError = glGetError();
00247     if (glError != GL_NO_ERROR) {
00248         GLint maxTexSize;
00249         glGetIntegerv( GL_MAX_TEXTURE_SIZE, &maxTexSize );
00250 
00251         OPENCITY_DEBUG( "CRITIC GL ERROR while loading texture" );
00252         cout << "Max texture size is: " << maxTexSize << endl;
00253         cout << "GL error code: 0x";
00254         cout.flags( cout.hex );
00255         cout << glError << endl;
00256         cout.flags( cout.dec );
00257     }
00258 }
00259 
00260 
00261    /*=====================================================================*/
00262 void
00263 Texture::GetCorrectSize(
00264     const uint w, const uint h,
00265     uint & rW,    uint & rH )
00266 {
00267     rW = 64;
00268     while (rW < w) rW = rW << 1;
00269 
00270     rH = 64;
00271     while (rH < h) rH = rH << 1;
00272 }
00273 
00274 
00275 
00276 
00277 
00278 
00279 
00280 
00281 
00282 
00283 
00284 
00285 
00286 
00287 
00288 
00289 
00290 
00291 
00292 
00293 
00294 
00295 
00296 
00297 
00298 
00299 
00300 
00301 

Generated on Sat Nov 11 10:21:10 2006 for OpenCity by  doxygen 1.4.2