home *** CD-ROM | disk | FTP | other *** search
/ Enter 2005 March / ENTER.ISO / files / fwp-0.0.6-win32-installer.exe / Texture.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-12-18  |  8.5 KB  |  261 lines

  1. /*!
  2. \file texture.cpp
  3. \author Karsten Schwenk
  4.  
  5. See header for description (texture.h).
  6. */
  7.  
  8. #include "Texture.h"
  9.  
  10. //#include <stdio.h>    // nur fⁿr debug!
  11. #include "Tokenizer.h"
  12. #include "File.h"
  13.  
  14. #include "log.h"
  15. #include "Renderer.h"
  16.  
  17. /*!
  18. This generates a new texture using the image file \c filename (see texture.h for a list of supported formats).
  19. After the file has been loaded (using #loadImage()), this constructor generates an OpenGL texture object and assigns priority 1.0 to it.
  20. The object can bee used instantly (via #Texture::texName).
  21. \warning In most cases it is better not generate textures directly but to obtain them via #TextureHandler::getTexture(). This prevents multiple loading of the same image file (=the same texture).
  22. \param filename the name of the image file
  23. */
  24. Texture::Texture(const char* filename){
  25.     this->filename = findImageFile(filename);
  26.     image=NULL;
  27.     width=0;
  28.     height=0;
  29.     texName=0;
  30.     texType=0;
  31.     priority=1.0;
  32.     hasAlpha=false;
  33.  
  34.     if(this->filename!=NULL){
  35.         image = ImageLoader::loadImage(this->filename);    // fill the image_t struct
  36.     }
  37.  
  38. //    printf("SCHEISSE!\n");
  39.     
  40.     if(image==NULL){
  41.         error("(in Texture::Texture()): Couldn't load file '%s'.\n\n", filename);
  42.     }else{
  43.         if(setAttribs()){
  44.             generateTextureObject();
  45.             log("Texture loaded: '%s' (%ix%i:%i).\n", this->filename, width, height, image->numChannels);
  46.             freeImage();
  47.         }else{
  48.             error("(in Texture::Texture()): Internal format unknown: '%s'. Texture not registered.\n\n", this->filename);
  49.             freeImage();
  50.         }
  51.     }
  52. }
  53.  
  54. /*!
  55. This generates a new texture using the image file \c filename and assigns the OpenGL priority \c priority to it. The priority becomes important when OpenGL has to decide whether or not to put a texture resident into the graphics card memory; so often used textures should have a high priority and seldomly used textures (like backgrounds) should have a low priority.
  56. The object can bee used instantly (via #Texture::texName).
  57. \warning In most cases it is better not generate textures directly but to obtain them via #TextureHandler::getTexture(). This prevents multiple loading of the same image file (=the same texture) and saves graphics memory.
  58. \param filename the name of the image file
  59. \param priority the priority of the texture (0.0 to 1.0)
  60. */
  61. Texture::Texture(const char* filename, GLclampf priority){
  62.     this->filename=findImageFile(filename);
  63.     image=NULL;
  64.     width=0;
  65.     height=0;
  66.     texName=0;
  67.     texType=0;
  68.     hasAlpha=false;
  69.     this->priority=priority;
  70.  
  71.     if(this->filename!=NULL)
  72.         image=ImageLoader::loadImage(this->filename);
  73.     
  74.     if(image==NULL){
  75.         error("(in Texture::Texture()): Couldn't load file '%s'.\n\n", filename);
  76.     }else{
  77.         if(setAttribs()){
  78.             generateTextureObject();
  79.             log("Texture loaded: '%s' (%ix%i:%i).\n", this->filename, width, height, image->numChannels);
  80.             freeImage();
  81.         }else{
  82.             error("(in Texture::Texture()): Internal format unknown: '%s'.\n\n", this->filename);
  83.             freeImage();
  84.         }
  85.     }
  86. }
  87.  
  88. /*!
  89. This generates a new texture using the #image_s struct \c image.
  90. The object can bee used instantly (via #Texture::texName).
  91. The \c image is not destroyed.
  92. \param image the #image_s struct that carries the picture information.
  93. */
  94. Texture::Texture(image_t* image){
  95.     this->filename=NULL;
  96.     this->image=image;
  97.     width=0;
  98.     height=0;
  99.     texName=0;
  100.     texType=0;
  101.     hasAlpha=false;
  102.     priority=0.0f;
  103.  
  104.     if(image==NULL){
  105.         error("(in Texture::Texture()): Cannot generate a texture from NULL.\n\n");
  106.     }else{
  107.         if(setAttribs()){
  108.             generateTextureObject();
  109.             this->image=NULL;
  110.         }else{
  111.             error("(in Texture::Texture()): Internal format unknown (generated from image_t).\n\n");
  112.             this->image=NULL;
  113.         }
  114.     }
  115. }
  116.  
  117. /*!
  118. This destroys a #Texture object and the corresponding OpenGL texture object.
  119. */
  120. Texture::~Texture(){
  121.     freeImage();
  122.     freeTextureObject();
  123.     delete[] filename;
  124. }
  125.  
  126. /*!
  127. This member function searches an image file. First under the exact filename, then in #RendererInfo::var.textureSearchPath.
  128. If \c filename has no extension the first suitable in #RendererInfo::var.textureExtensions is appended.
  129. This is implemented as a static method, so other objects can search image files without having a #Texture object. (E.g. #TextureHandler uses this.)
  130. \param filename the filename of the image file
  131. \return a pointer to a string with the conplete filename ro \c NULL if no file was found
  132. */
  133. char* Texture::findImageFile(const char* filename){
  134.     Tokenizer t(filename, ".", "");
  135.  
  136.     if(t.tokc<=1){    // no extension
  137.         char buff[256];
  138.         char* ret;
  139.  
  140.         Tokenizer t2(Renderer::info.var.textureExtensions, ";", "");
  141.         for(int i=0;i<t2.tokc;i++){    // try all extensions
  142.             strcpy(buff, filename);
  143.             strcat(buff, t2.tokv[i]);
  144.             ret=File::searchAndCreatePath(buff, Renderer::info.var.textureSearchPath);
  145.             if(ret!=NULL){
  146.                 return ret;
  147.             }
  148.         }
  149. //        error("(in Texture::findImageFile()): Couldn't find any suitable extension for filename '%s'.\n\n", filename);
  150.         return NULL;
  151.     }
  152.  
  153.     return File::searchAndCreatePath(filename, Renderer::info.var.textureSearchPath);
  154. }
  155.  
  156. /*!
  157. This member function reloads a texture and assigns a new OpenGL texture object name to it. This is useful after the texture object has been destroyed or the OpenGL-context was lost. In FWP, for example, this is called during every change of resolutions.
  158. */
  159. void Texture::reload(){
  160.     if(filename==NULL){    // texture was generated from an image_s struct
  161.         return;
  162.     }
  163.  
  164.     image=ImageLoader::loadImage(filename);
  165.     
  166.     if(image==NULL){
  167.         error("(in Texture::reload()): couldn't load file '%s'.\n\n", filename);
  168.     }else{
  169.         if(setAttribs()){
  170.             generateTextureObject();
  171.             freeImage();
  172.         }else{
  173.             error("(in Texture::reload()): internal format unknown: '%s'.\n\n", filename);
  174.             freeImage();
  175.         }
  176.     }
  177. }
  178.  
  179.  
  180. /*!
  181. This member function sets some important attributes after the image has been loaded and before the OpenGL texture object is generated.
  182. They are namely: #width, #height, #hasAlpha, #texType.
  183. \return \c false if #image is \c NULL, \c true on success
  184. */
  185. bool Texture::setAttribs(){
  186.     if(image==NULL)
  187.         return false;
  188.  
  189.     if(image->numChannels==1)    // set texType
  190.         texType=GL_LUMINANCE;
  191.     else if(image->numChannels==2)
  192.         texType=GL_LUMINANCE_ALPHA;
  193.     else if(image->numChannels==3)
  194.         texType=GL_RGB;
  195.     else if(image->numChannels==4)
  196.         texType=GL_RGBA;
  197.     else
  198.         return false;
  199.  
  200.     width=image->width;
  201.     height=image->height;
  202.  
  203.     hasAlpha=(texType==GL_LUMINANCE || texType==GL_LUMINANCE_ALPHA || texType==GL_RGBA);
  204.  
  205.     return true;
  206. }
  207.  
  208. /*!
  209. This member function generates the OpenGL texture object (#texName) that is used to bind the texture, etc.
  210. It automatically generates mipmaps and sets some OpenGL texture object attributes like \c GLTEXTURE_WRAP and \c GL_TEXTURE_FILTER, too.
  211. Wrapping is set to repeat and the texture filters are set according to #RendererInfo::var.textureMinFilter or #RendererInfo::var.textureMinFilter respectively.
  212. Of course these values can be changed later with the OpenGL functions.
  213. \bug mipmap generation doesn't work for some (uneven) sizes under linux
  214. \return \c texName or 0 on errors
  215. */
  216. GLuint Texture::generateTextureObject(){
  217.     if(image==NULL)
  218.         return 0;
  219.  
  220.     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);    // THINKABOUTME: n÷tig??
  221.  
  222.     glGenTextures(1, &texName);
  223.     glBindTexture(GL_TEXTURE_2D, texName);
  224.  
  225.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  226.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  227.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Renderer::info.var.textureMagFilter);    // THINKABOUTME: besser unabhΣngig von renderer halten?
  228.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Renderer::info.var.textureMinFilter);    // THINKABOUTME
  229.  
  230. //     printf("numC: %i, x: %i, y: %i, type: %i\n", image->numChannels, image->xSize, image->ySize, texType);
  231.     gluBuild2DMipmaps(GL_TEXTURE_2D, image->numChannels, image->width, image->height, texType, GL_UNSIGNED_BYTE, image->data);
  232. //    int r=gluBuild2DMipmaps(GL_TEXTURE_2D, image->numChannels, image->width, image->height, texType, GL_UNSIGNED_BYTE, image->data);
  233.     //if(r!=0){
  234.     //    error("SCHEISSE!!!!!\n\n");
  235.     //}
  236.  
  237.     glPrioritizeTextures(1, &texName, &priority);
  238.  
  239.     return texName;
  240. }
  241.  
  242. /*!
  243. Frees the #image struct that has been allocated by #loadImage() during loading. This is not longer used after we have an OpenGL texture object.
  244. */
  245. void Texture::freeImage(){
  246.     if(image!=NULL){
  247.         delete[] image->data;
  248.         delete image;
  249.         image=NULL;
  250.     }
  251. }
  252.  
  253. /*!
  254. Frees the OpenGL texture object. This is done during #reload() or when destroying the object.
  255. */
  256. void Texture::freeTextureObject(){
  257.     glDeleteTextures(1, &texName);
  258.     texName=0;
  259. }
  260.  
  261.