TexturePainter.cpp

Go to the documentation of this file.
00001 // Copyright (C) 2005 Dave Griffiths
00002 //
00003 // This program is free software; you can redistribute it and/or modify
00004 // it under the terms of the GNU General Public License as published by
00005 // the Free Software Foundation; either version 2 of the License, or
00006 // (at your option) any later version.
00007 //
00008 // This program is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 // GNU General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU General Public License
00014 // along with this program; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00016 
00017 #include "State.h"
00018 #include "TexturePainter.h"
00019 #include "PNGLoader.h"
00020 #include "SearchPaths.h"
00021 #include <assert.h>
00022 
00023 using namespace Fluxus;
00024 
00025 TexturePainter *TexturePainter::m_Singleton=NULL;
00026 
00027 TexturePainter::TexturePainter() 
00028 {
00029 }
00030 
00031 TexturePainter::~TexturePainter()
00032 {
00034 }
00035 
00036 void TexturePainter::Initialise()
00037 {
00038     for (int c=0; c<MAX_TEXTURES; c++)
00039     {
00040         #ifdef ENABLE_MULTITEXTURE
00041         glActiveTexture(GL_TEXTURE0+c);
00042         glClientActiveTexture(GL_TEXTURE0+c);
00043         #endif
00044         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00045                 
00046         glMatrixMode(GL_TEXTURE);
00047         glLoadIdentity();
00048     }
00049     #ifdef ENABLE_MULTITEXTURE
00050     glClientActiveTexture(GL_TEXTURE0);
00051     #endif
00052 }
00053 
00054 void TexturePainter::ClearCache()
00055 {
00056     m_TextureMap.clear();
00057     m_LoadedMap.clear();
00058     m_LoadedCubeMap.clear();
00059 }
00060 
00061 unsigned int TexturePainter::LoadTexture(const string &Filename, CreateParams &params)
00062 {
00063     string Fullpath = SearchPaths::Get()->GetFullPath(Filename);
00064     
00065     if (params.Type==GL_TEXTURE_CUBE_MAP_POSITIVE_X || params.Type==GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
00066         params.Type==GL_TEXTURE_CUBE_MAP_POSITIVE_Y || params.Type==GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
00067         params.Type==GL_TEXTURE_CUBE_MAP_POSITIVE_Z || params.Type==GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
00068     {
00069         return LoadCubeMap(Fullpath, params);
00070     }
00071     
00072     // see if we've loaded this one already
00073     map<string,int>::iterator i=m_LoadedMap.find(Fullpath);
00074     if (i!=m_LoadedMap.end())
00075     {
00076         return i->second;
00077     }
00078     
00079     unsigned char *ImageData;
00080     TextureDesc desc;
00081     ImageData=PNGLoader::Load(Fullpath,desc.Width,desc.Height,desc.Format);
00082     
00083     if (ImageData!=NULL)
00084     {
00085         //\todo support more depths than 8bit
00086         
00087         // upload to card...
00088         glEnable(params.Type);
00089         
00090         if (params.ID==-1) // is this a new texture?
00091         {
00092             GLuint id;
00093             glGenTextures(1,&id);
00094             params.ID=id; // ahem
00095             //\todo this means mipmap levels won't be cached
00096             m_TextureMap[params.ID]=desc;
00097             m_LoadedMap[Fullpath]=params.ID;                    
00098         }
00099                 
00100         UploadTexture(desc,params,ImageData);                                       
00101         delete[] ImageData;
00102         return params.ID;       
00103     }   
00104     m_LoadedMap[Fullpath]=0;
00105     return 0;
00106 }
00107 
00108 unsigned int TexturePainter::LoadCubeMap(const string &Fullpath, CreateParams &params)
00109 {   
00110     // see if we've loaded this one already
00111     map<string,int>::iterator i=m_LoadedCubeMap.find(Fullpath);
00112     if (i!=m_LoadedCubeMap.end())
00113     {
00114         return i->second;
00115     }
00116 
00117     unsigned char *ImageData;
00118     TextureDesc desc;
00119     ImageData=PNGLoader::Load(Fullpath,desc.Width,desc.Height,desc.Format);
00120     
00121     if (ImageData!=NULL)
00122     {
00123         //\todo support more depths than 8bit
00124         
00125         // upload to card...
00126         glEnable(params.Type);
00127         
00128         if (params.ID==-1) // is this a new texture?
00129         {
00130             GLuint id;
00131             glGenTextures(1,&id);
00132             params.ID=id; // ahem
00133             //\todo this means cubemaps won't be cached
00134             m_TextureMap[params.ID]=desc;
00135             m_LoadedCubeMap[Fullpath]=params.ID;
00136                         
00137             CubeMapDesc newcubemap;
00138             m_CubeMapMap[params.ID] = newcubemap;
00139                 
00140             switch (params.Type) // record the cubemap face
00141             {
00142                 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: m_CubeMapMap[params.ID].Positive[0]=params.ID; break;
00143                 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: m_CubeMapMap[params.ID].Negative[0]=params.ID; break;
00144                 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: m_CubeMapMap[params.ID].Positive[1]=params.ID; break;
00145                 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: m_CubeMapMap[params.ID].Negative[1]=params.ID; break;
00146                 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: m_CubeMapMap[params.ID].Positive[2]=params.ID; break;
00147                 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: m_CubeMapMap[params.ID].Negative[2]=params.ID; break;
00148                 default: assert(0); break;
00149             }
00150         }
00151         else // we have an existing texture id specified
00152         {
00153             // make a new texture id for this face
00154             // record the primary cubemap id
00155             unsigned int primary = params.ID;
00156             GLuint id;
00157             glGenTextures(1,&id);
00158             params.ID=id; // ahem
00159             m_TextureMap[params.ID]=desc;
00160             m_LoadedCubeMap[Fullpath]=params.ID;
00161 
00162             switch (params.Type) // record the cubemap face
00163             {
00164                 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: m_CubeMapMap[primary].Positive[0]=params.ID; break;
00165                 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: m_CubeMapMap[primary].Negative[0]=params.ID; break;
00166                 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: m_CubeMapMap[primary].Positive[1]=params.ID; break;
00167                 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: m_CubeMapMap[primary].Negative[1]=params.ID; break;
00168                 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: m_CubeMapMap[primary].Positive[2]=params.ID; break;
00169                 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: m_CubeMapMap[primary].Negative[2]=params.ID; break;
00170                 default: assert(0); break;
00171             }
00172         }
00173             
00174         UploadTexture(desc,params,ImageData);                   
00175         delete[] ImageData;
00176         return params.ID;       
00177     }   
00178     m_LoadedMap[Fullpath]=0;
00179     return 0;
00180 }
00181 
00182 void TexturePainter::UploadTexture(TextureDesc desc, CreateParams params, const unsigned char *ImageData)
00183 {
00184     glBindTexture(params.Type,params.ID);
00185         
00186     if (params.GenerateMipmaps)
00187     {
00188         if (desc.Format==RGB)
00189         {
00190             gluBuild2DMipmaps(params.Type,3,desc.Width,desc.Height,GL_RGB,GL_UNSIGNED_BYTE,ImageData);
00191         }
00192         else
00193         {
00194             gluBuild2DMipmaps(params.Type,4,desc.Width,desc.Height,GL_RGBA,GL_UNSIGNED_BYTE,ImageData);
00195         }
00196     }
00197     else
00198     {       
00199         //\todo check power of two
00200         //\todo and scale?
00201 
00202         if (desc.Format==RGB)
00203         {               
00204             glTexImage2D(params.Type,params.MipLevel,3,desc.Width,desc.Height,params.Border,
00205                 GL_RGB,GL_UNSIGNED_BYTE,ImageData);         
00206         }
00207         else
00208         {
00209             glTexImage2D(params.Type,params.MipLevel,4,desc.Width,desc.Height,params.Border,
00210                 GL_RGBA,GL_UNSIGNED_BYTE,ImageData);
00211         }
00212     }       
00213 }
00214 
00215 bool TexturePainter::LoadPData(const string &Filename, unsigned int &w, unsigned int &h, TypedPData<dColour> &pixels)
00216 {
00217     string Fullpath = SearchPaths::Get()->GetFullPath(Filename);
00218 
00219     unsigned char *ImageData;
00220     TextureDesc desc;
00221     ImageData=PNGLoader::Load(Fullpath,desc.Width,desc.Height,desc.Format);
00222     
00223     if (ImageData!=NULL)
00224     {
00225         pixels.Resize(desc.Width*desc.Height);
00226         w=desc.Width;
00227         h=desc.Height;
00228 
00229         if (desc.Format==RGB)
00230         {
00231             for (int n=0; n<desc.Width*desc.Height; n++)
00232             {
00233                 pixels.m_Data[n]=dColour(ImageData[n*3]/255.0f, 
00234                                          ImageData[n*3+1]/255.0f,
00235                                          ImageData[n*3+2]/255.0f,1.0f);
00236                 
00237             }   
00238         }   
00239         else if (desc.Format==RGBA)
00240         {
00241             for (int n=0; n<desc.Width*desc.Height; n++)
00242             {
00243                 pixels.m_Data[n]=dColour(ImageData[n*4]/255.0f, 
00244                                          ImageData[n*4+1]/255.0f,
00245                                          ImageData[n*4+2]/255.0f,
00246                                          ImageData[n*4+3]/255.0f);
00247                 
00248             }   
00249         }
00250         else
00251         {
00252             return false;
00253         }
00254             
00255         return true;
00256     }
00257     
00258     return false;
00259 }
00260 
00261 unsigned int TexturePainter::MakeTexture(unsigned int w, unsigned int h, PData *data)
00262 {
00263     GLuint ID=0;
00264     TypedPData<dColour> *pixels = dynamic_cast<TypedPData<dColour>*>(data);
00265     if (pixels)
00266     {
00267         // upload to card...
00268         glGenTextures(1,&ID);
00269         glBindTexture(GL_TEXTURE_2D,ID);
00270         gluBuild2DMipmaps(GL_TEXTURE_2D,4,w,h,GL_RGBA,GL_FLOAT,&pixels->m_Data[0]);
00271         return ID;
00272     }
00273     return 0;
00274 }
00275 
00276 bool TexturePainter::SetCurrent(unsigned int *ids, TextureState *states)
00277 {
00278     bool ret=false;
00279     
00280     for (int c=0; c<MAX_TEXTURES; c++)
00281     {
00282         #ifdef ENABLE_MULTITEXTURE
00283         glActiveTexture(GL_TEXTURE0+c);
00284         #endif
00285                 
00286         if (ids[c]!=0)
00287         {
00288             map<unsigned int,CubeMapDesc>::iterator i=m_CubeMapMap.find(ids[c]);
00289 
00290             if (i!=m_CubeMapMap.end()) // cubemap texture path
00291             {
00292                 glBindTexture(GL_TEXTURE_CUBE_MAP_POSITIVE_X,i->second.Positive[0]);
00293                 glBindTexture(GL_TEXTURE_CUBE_MAP_NEGATIVE_X,i->second.Negative[0]);
00294                 glBindTexture(GL_TEXTURE_CUBE_MAP_POSITIVE_Y,i->second.Positive[1]);
00295                 glBindTexture(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,i->second.Negative[1]);
00296                 glBindTexture(GL_TEXTURE_CUBE_MAP_POSITIVE_Z,i->second.Positive[2]);
00297                 glBindTexture(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,i->second.Negative[2]);
00298                 
00299                 glEnable(GL_TEXTURE_CUBE_MAP);
00300                 ApplyState(GL_TEXTURE_CUBE_MAP,states[c],true);                                                     
00301             }
00302             else // normal 2D texture path
00303             {
00304                 glEnable(GL_TEXTURE_2D);
00305                 glBindTexture(GL_TEXTURE_2D,ids[c]);                    
00306                 ApplyState(GL_TEXTURE_2D,states[c],false);              
00307             }
00308             
00309             ret=true;                       
00310         }
00311         else
00312         {
00313             glDisable(GL_TEXTURE_2D);
00314             glDisable(GL_TEXTURE_CUBE_MAP);
00315         }
00316     }
00317     
00318     #ifdef ENABLE_MULTITEXTURE
00319     glActiveTexture(GL_TEXTURE0);
00320     #endif
00321     
00322     return ret;
00323 }
00324 
00325 void TexturePainter::ApplyState(int type, TextureState &state, bool cubemap)
00326 {
00327     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, state.TexEnv);
00328     glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, state.EnvColour.arr());
00329     glTexParameteri(type, GL_TEXTURE_MIN_FILTER, state.Min);
00330     glTexParameteri(type, GL_TEXTURE_MAG_FILTER, state.Mag);    
00331     glTexParameteri(type, GL_TEXTURE_WRAP_S, state.WrapS);
00332     glTexParameteri(type, GL_TEXTURE_WRAP_T, state.WrapT);
00333     if (cubemap) glTexParameteri(type, GL_TEXTURE_WRAP_R, state.WrapT);
00334     glTexParameterfv(type, GL_TEXTURE_BORDER_COLOR, state.BorderColour.arr());
00335     glTexParameterf(type, GL_TEXTURE_PRIORITY, state.Priority);
00336     glTexParameterf(type, GL_TEXTURE_MIN_LOD, state.MinLOD);
00337     glTexParameterf(type, GL_TEXTURE_MAX_LOD, state.MaxLOD);
00338 }
00339 
00340 void TexturePainter::DisableAll()
00341 {
00342     #ifdef ENABLE_MULTITEXTURE
00343     for (int c=0; c<MAX_TEXTURES; c++)
00344     {
00345         glActiveTexture(GL_TEXTURE0+c);
00346         glDisable(GL_TEXTURE_2D);
00347     }
00348     glClientActiveTexture(GL_TEXTURE0);
00349     #else
00350     glDisable(GL_TEXTURE_2D);
00351     #endif
00352 }
00353 
00354 
00355 
00356 
00357 
00358 
00359 

Generated on Mon Feb 11 06:54:25 2008 for The Fluxus Renderer (libfluxus) by  doxygen 1.5.1