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     if (params.Type==GL_TEXTURE_CUBE_MAP_POSITIVE_X || params.Type==GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
00065         params.Type==GL_TEXTURE_CUBE_MAP_POSITIVE_Y || params.Type==GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
00066         params.Type==GL_TEXTURE_CUBE_MAP_POSITIVE_Z || params.Type==GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
00067     {
00068         return LoadCubeMap(Fullpath, params);
00069     }
00070     
00071     // see if we've loaded this one already
00072     map<string,int>::iterator i=m_LoadedMap.find(Fullpath);
00073     if (i!=m_LoadedMap.end())
00074     {
00075         return i->second;
00076     }
00077     
00078     unsigned char *ImageData;
00079     TextureDesc desc;
00080     ImageData=PNGLoader::Load(Fullpath,desc.Width,desc.Height,desc.Format);
00081     
00082     if (ImageData!=NULL)
00083     {
00084         //\todo support more depths than 8bit
00085         
00086         // upload to card...
00087         glEnable(params.Type);
00088         
00089         if (params.ID==-1) // is this a new texture?
00090         {
00091             GLuint id;
00092             glGenTextures(1,&id);
00093             params.ID=id; // ahem
00094             //\todo this means mipmap levels won't be cached
00095             m_TextureMap[params.ID]=desc;
00096             m_LoadedMap[Fullpath]=params.ID;                    
00097         }
00098                 
00099         UploadTexture(desc,params,ImageData);                                       
00100         delete[] ImageData;
00101         return params.ID;       
00102     }   
00103     m_LoadedMap[Fullpath]=0;
00104     return 0;
00105 }
00106 
00107 unsigned int TexturePainter::LoadCubeMap(const string &Fullpath, CreateParams &params)
00108 {   
00109     // see if we've loaded this one already
00110     map<string,int>::iterator i=m_LoadedCubeMap.find(Fullpath);
00111     if (i!=m_LoadedCubeMap.end())
00112     {
00113         return i->second;
00114     }
00115 
00116     unsigned char *ImageData;
00117     TextureDesc desc;
00118     ImageData=PNGLoader::Load(Fullpath,desc.Width,desc.Height,desc.Format);
00119     
00120     if (ImageData!=NULL)
00121     {
00122         //\todo support more depths than 8bit
00123         
00124         // upload to card...
00125         glEnable(params.Type);
00126         
00127         if (params.ID==-1) // is this a new texture?
00128         {
00129             GLuint id;
00130             glGenTextures(1,&id);
00131             params.ID=id; // ahem
00132             //\todo this means cubemaps won't be cached
00133             m_TextureMap[params.ID]=desc;
00134             m_LoadedCubeMap[Fullpath]=params.ID;
00135                         
00136             CubeMapDesc newcubemap;
00137             m_CubeMapMap[params.ID] = newcubemap;
00138                 
00139             switch (params.Type) // record the cubemap face
00140             {
00141                 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: m_CubeMapMap[params.ID].Positive[0]=params.ID; break;
00142                 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: m_CubeMapMap[params.ID].Negative[0]=params.ID; break;
00143                 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: m_CubeMapMap[params.ID].Positive[1]=params.ID; break;
00144                 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: m_CubeMapMap[params.ID].Negative[1]=params.ID; break;
00145                 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: m_CubeMapMap[params.ID].Positive[2]=params.ID; break;
00146                 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: m_CubeMapMap[params.ID].Negative[2]=params.ID; break;
00147                 default: assert(0); break;
00148             }
00149         }
00150         else // we have an existing texture id specified
00151         {
00152             // make a new texture id for this face
00153             // record the primary cubemap id
00154             unsigned int primary = params.ID;
00155             GLuint id;
00156             glGenTextures(1,&id);
00157             params.ID=id; // ahem
00158             m_TextureMap[params.ID]=desc;
00159             m_LoadedCubeMap[Fullpath]=params.ID;
00160 
00161             switch (params.Type) // record the cubemap face
00162             {
00163                 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: m_CubeMapMap[primary].Positive[0]=params.ID; break;
00164                 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: m_CubeMapMap[primary].Negative[0]=params.ID; break;
00165                 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: m_CubeMapMap[primary].Positive[1]=params.ID; break;
00166                 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: m_CubeMapMap[primary].Negative[1]=params.ID; break;
00167                 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: m_CubeMapMap[primary].Positive[2]=params.ID; break;
00168                 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: m_CubeMapMap[primary].Negative[2]=params.ID; break;
00169                 default: assert(0); break;
00170             }
00171         }
00172             
00173         UploadTexture(desc,params,ImageData);                   
00174         delete[] ImageData;
00175         return params.ID;       
00176     }   
00177     m_LoadedMap[Fullpath]=0;
00178     return 0;
00179 }
00180 
00181 void TexturePainter::UploadTexture(TextureDesc desc, CreateParams params, const unsigned char *ImageData)
00182 {
00183     glBindTexture(params.Type,params.ID);
00184         
00185     if (params.GenerateMipmaps)
00186     {
00187         if (desc.Format==RGB)
00188         {
00189             gluBuild2DMipmaps(params.Type,3,desc.Width,desc.Height,GL_RGB,GL_UNSIGNED_BYTE,ImageData);
00190         }
00191         else
00192         {
00193             gluBuild2DMipmaps(params.Type,4,desc.Width,desc.Height,GL_RGBA,GL_UNSIGNED_BYTE,ImageData);
00194         }
00195     }
00196     else
00197     {       
00198         //\todo check power of two
00199         //\todo and scale?
00200 
00201         if (desc.Format==RGB)
00202         {               
00203             glTexImage2D(params.Type,params.MipLevel,3,desc.Width,desc.Height,params.Border,
00204                 GL_RGB,GL_UNSIGNED_BYTE,ImageData);         
00205         }
00206         else
00207         {
00208             glTexImage2D(params.Type,params.MipLevel,4,desc.Width,desc.Height,params.Border,
00209                 GL_RGBA,GL_UNSIGNED_BYTE,ImageData);
00210         }
00211     }       
00212 }
00213 
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 (unsigned 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 (unsigned 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             delete[] ImageData;
00253             return false;
00254         }
00255             
00256         delete[] ImageData;
00257         return true;
00258     }
00259     
00260     return false;
00261 }
00262 
00263 bool TexturePainter::SavePData(const string &Filename, unsigned int w, unsigned int h, const TypedPData<dColour> &pixels)
00264 {
00265     // save as 8bit rgba 
00266     unsigned char *ImageData=new unsigned char[w*h*4];
00267     for (unsigned int n=0; n<w*h; n++)
00268     {
00269         ImageData[n*4]=(unsigned char)(pixels.m_Data[n].r*255.0f);
00270         ImageData[n*4+1]=(unsigned char)(pixels.m_Data[n].g*255.0f);
00271         ImageData[n*4+2]=(unsigned char)(pixels.m_Data[n].b*255.0f);
00272         ImageData[n*4+3]=(unsigned char)(pixels.m_Data[n].a*255.0f);
00273     }
00274     
00275     PNGLoader::Save(Filename, w, h, RGBA, ImageData);
00276     
00277     delete[] ImageData;
00278     return true;
00279 }
00280 
00281 unsigned int TexturePainter::MakeTexture(unsigned int w, unsigned int h, PData *data)
00282 {
00283     GLuint ID=0;
00284     TypedPData<dColour> *pixels = dynamic_cast<TypedPData<dColour>*>(data);
00285     if (pixels)
00286     {
00287         // upload to card...
00288         glGenTextures(1,&ID);
00289         glBindTexture(GL_TEXTURE_2D,ID);
00290         gluBuild2DMipmaps(GL_TEXTURE_2D,4,w,h,GL_RGBA,GL_FLOAT,&pixels->m_Data[0]);
00291         return ID;
00292     }
00293     return 0;
00294 }
00295 
00296 bool TexturePainter::SetCurrent(unsigned int *ids, TextureState *states)
00297 {
00298     bool ret=false;
00299     
00300     for (int c=0; c<MAX_TEXTURES; c++)
00301     {
00302         #ifdef ENABLE_MULTITEXTURE
00303         glActiveTexture(GL_TEXTURE0+c);
00304         #endif
00305                 
00306         if (ids[c]!=0)
00307         {
00308             map<unsigned int,CubeMapDesc>::iterator i=m_CubeMapMap.find(ids[c]);
00309 
00310             if (i!=m_CubeMapMap.end()) // cubemap texture path
00311             {
00312                 glBindTexture(GL_TEXTURE_CUBE_MAP_POSITIVE_X,i->second.Positive[0]);
00313                 glBindTexture(GL_TEXTURE_CUBE_MAP_NEGATIVE_X,i->second.Negative[0]);
00314                 glBindTexture(GL_TEXTURE_CUBE_MAP_POSITIVE_Y,i->second.Positive[1]);
00315                 glBindTexture(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,i->second.Negative[1]);
00316                 glBindTexture(GL_TEXTURE_CUBE_MAP_POSITIVE_Z,i->second.Positive[2]);
00317                 glBindTexture(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,i->second.Negative[2]);
00318                 
00319                 glEnable(GL_TEXTURE_CUBE_MAP);
00320                 ApplyState(GL_TEXTURE_CUBE_MAP,states[c],true);                                                     
00321             }
00322             else // normal 2D texture path
00323             {
00324                 glEnable(GL_TEXTURE_2D);
00325                 glBindTexture(GL_TEXTURE_2D,ids[c]);                    
00326                 ApplyState(GL_TEXTURE_2D,states[c],false);              
00327             }
00328             
00329             ret=true;                       
00330         }
00331         else
00332         {
00333             glDisable(GL_TEXTURE_2D);
00334             glDisable(GL_TEXTURE_CUBE_MAP);
00335         }
00336     }
00337     
00338     #ifdef ENABLE_MULTITEXTURE
00339     glActiveTexture(GL_TEXTURE0);
00340     #endif
00341     
00342     return ret;
00343 }
00344 
00345 void TexturePainter::ApplyState(int type, TextureState &state, bool cubemap)
00346 {
00347     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, state.TexEnv);
00348     glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, state.EnvColour.arr());
00349     glTexParameteri(type, GL_TEXTURE_MIN_FILTER, state.Min);
00350     glTexParameteri(type, GL_TEXTURE_MAG_FILTER, state.Mag);    
00351     glTexParameteri(type, GL_TEXTURE_WRAP_S, state.WrapS);
00352     glTexParameteri(type, GL_TEXTURE_WRAP_T, state.WrapT);
00353     if (cubemap) glTexParameteri(type, GL_TEXTURE_WRAP_R, state.WrapT);
00354     glTexParameterfv(type, GL_TEXTURE_BORDER_COLOR, state.BorderColour.arr());
00355     glTexParameterf(type, GL_TEXTURE_PRIORITY, state.Priority);
00356     glTexParameterf(type, GL_TEXTURE_MIN_LOD, state.MinLOD);
00357     glTexParameterf(type, GL_TEXTURE_MAX_LOD, state.MaxLOD);
00358 }
00359 
00360 void TexturePainter::DisableAll()
00361 {
00362     #ifdef ENABLE_MULTITEXTURE
00363     for (int c=0; c<MAX_TEXTURES; c++)
00364     {
00365         glActiveTexture(GL_TEXTURE0+c);
00366         glDisable(GL_TEXTURE_2D);
00367     }
00368     glClientActiveTexture(GL_TEXTURE0);
00369     #else
00370     glDisable(GL_TEXTURE_2D);
00371     #endif
00372 }
00373 
00374 void TexturePainter::Dump()
00375 {
00376     for (map<string,int>::iterator i=m_LoadedMap.begin(); i!=m_LoadedMap.end(); ++i)
00377     {
00378         TextureDesc info = m_TextureMap[i->second];
00379         Trace::Stream<<i->first<<" "<<info.Width<<"X"<<info.Height<<" ";
00380         if (info.Format==RGB) Trace::Stream<<"RGB"<<endl;
00381         else if (info.Format==RGBA) Trace::Stream<<"RGBA"<<endl;
00382     }
00383 }
00384 
00385 
00386 
00387 
00388 

Generated on Wed Sep 17 21:16:30 2008 for The Fluxus Renderer (libfluxus) by  doxygen 1.5.1