//---------------------------------------------------------------------------- // EgalTech 2015-2015 //---------------------------------------------------------------------------- // File : TextureMgr.cpp Data : 27.09.15 Versione : 1.6i8 // Contenuto : Implementazione della classe gestione textures. // // // // Modifiche : 27.09.15 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "Scene.h" #include "TextureMgr.h" #include "\EgtDev\Include\EGnStringUtils.h" #include "\EgtDev\Include\EgtStringConverter.h" #include "\EgtDev\Extern\FreeImage\Include\FreeImage.h" using namespace std ; //---------------------------------------------------------------------------- TextureMgr::TextureMgr( void) { // inserisco le texture standard calcolate : Chessboard e Lines } //---------------------------------------------------------------------------- TextureMgr::~TextureMgr( void) { // scarico le texture da OpenGL for ( auto iIter = m_umTextData.begin() ; iIter != m_umTextData.end() ; ++ iIter) { GLuint nTextId = iIter->second.nTexId ; glDeleteTextures( 1, &nTextId) ; } m_umTextData.clear() ; } //---------------------------------------------------------------------------- bool TextureMgr::LoadTexture( const string& sName, const string& sFile, double dMMxPix, double dDimX, double dDimY, bool bRepeat) { // verifico se immagine già caricata auto iIter = m_umTextData.find( sName) ; if ( iIter != m_umTextData.end()) return ( EqualNoCase( iIter->second.sFile, sFile) && iIter->second.bRepeat == bRepeat) ; // leggo l'immagine dal file FIBITMAP* pDib = nullptr ; if ( ! ReadImage( sFile, pDib)) return false ; // se necessario, converto l'immagine a 32 bit per pixel (BGRA) int bitsPerPixel = FreeImage_GetBPP( pDib) ; if ( bitsPerPixel != 32) { FIBITMAP* pTmpDib = pDib ; pDib = FreeImage_ConvertTo32Bits( pTmpDib) ; FreeImage_Unload( pTmpDib) ; } // se necessario e possibile, la riduco alle dimensioni caricabili da OpenGL corrente if ( ! TestImageWithOpenGL( pDib)) return false ; // recupero le dimensioni in pixel dell'immagine int nWidth = FreeImage_GetWidth( pDib) ; int nHeight = FreeImage_GetHeight( pDib) ; // carico l'immagine in OpenGL come texture GLuint nTexName ; glPixelStorei( GL_UNPACK_ALIGNMENT, 4) ; glGenTextures( 1, &nTexName) ; glBindTexture( GL_TEXTURE_2D, nTexName) ; glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, ( bRepeat ? GL_REPEAT : GL_CLAMP_TO_BORDER)) ; glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, ( bRepeat ? GL_REPEAT : GL_CLAMP_TO_BORDER)) ; float color[] = { 0.9f, 0.9f, 0.9f, 1.0f} ; glTexParameterfv( GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color) ; glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) ; glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) ; glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, nWidth, nHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, FreeImage_GetBits( pDib)) ; // libero l'immagine originaria FreeImage_Unload( pDib) ; // verifico che la texture sia stata veramente caricata if ( ! glIsTexture( nTexName)) return false ; // rendo non corrente questa texture glBindTexture( GL_TEXTURE_2D, 0) ; // se dati mm/pixel determino le dimensioni fisiche della texture if ( dMMxPix > EPS_SMALL && ( dDimX < EPS_SMALL || dDimY < EPS_SMALL)) { dDimX = dMMxPix * nWidth ; dDimY = dMMxPix * nHeight ; } // salvo i dati TextureData textData( sFile, dDimX, dDimY, nWidth, nHeight, nTexName, bRepeat) ; m_umTextData.emplace( sName, textData) ; return true ; } //---------------------------------------------------------------------------- bool TextureMgr::UnloadTexture( const std::string& sName) { // cerco la texture, se non la trovo già ok auto iIter = m_umTextData.find( sName) ; if ( iIter == m_umTextData.end()) return true ; // scarico la texture da OpenGL GLuint nTextId = iIter->second.nTexId ; glDeleteTextures( 1, &nTextId) ; // tolgo la texture dall'elenco m_umTextData.erase( iIter) ; return true ; } //---------------------------------------------------------------------------- bool TextureMgr::GetPixels( const std::string& sName, int& nWidth, int& nHeight) { // ricerca della texture di nome dato auto iIter = m_umTextData.find( sName) ; if ( iIter == m_umTextData.end()) return false ; // restituisco le dimensioni in pixel nWidth = iIter->second.nWidth ; nHeight = iIter->second.nHeight ; return true ; } //---------------------------------------------------------------------------- bool TextureMgr::GetDimensions( const std::string& sName, double& dDimX, double& dDimY) { // ricerca della texture di nome dato auto iIter = m_umTextData.find( sName) ; if ( iIter == m_umTextData.end()) return false ; // restituisco le dimensioni fisiche dDimX = iIter->second.dDimX ; dDimY = iIter->second.dDimY ; return true ; } //---------------------------------------------------------------------------- bool TextureMgr::ChangeDimensions( const std::string& sName, double dDimX, double dDimY) { // ricerca della texture di nome dato auto iIter = m_umTextData.find( sName) ; if ( iIter == m_umTextData.end()) return false ; // assegno le nuove dimensioni iIter->second.dDimX = dDimX ; iIter->second.dDimY = dDimY ; return true ; } //---------------------------------------------------------------------------- bool TextureMgr::GetTextureData( const string& sName, unsigned int& nId, double& dDimX, double& dDimY) { // ricerca della texture di nome dato auto iIter = m_umTextData.find( sName) ; if ( iIter == m_umTextData.end()) return false ; // restituzione dei parametri nId = iIter->second.nTexId ; dDimX = iIter->second.dDimX ; dDimY = iIter->second.dDimY ; return true ; } //---------------------------------------------------------------------------- bool TextureMgr::ReadImage( const string& sFile, FIBITMAP*& pDib) { // deduco il formato dell'immagine dalla sua segnatura o dalla estensione del file FREE_IMAGE_FORMAT nFif = FreeImage_GetFileTypeU( stringtoW( sFile), 0) ; if ( nFif == FIF_UNKNOWN) nFif = FreeImage_GetFIFFromFilenameU( stringtoW( sFile)) ; // se non determinata, esco con errore if ( nFif == FIF_UNKNOWN) return false ; // carico l'immagine pDib = nullptr ; if ( FreeImage_FIFSupportsReading( nFif)) pDib = FreeImage_LoadU( nFif, stringtoW( sFile)) ; if ( pDib == nullptr) return false ; // recupero alcuni dati dell'immagine e li verifico if ( FreeImage_GetBits( pDib) == nullptr || FreeImage_GetWidth( pDib) == 0 || FreeImage_GetHeight( pDib) == 0) { FreeImage_Unload( pDib) ; pDib = nullptr ; return false ; } return true ; } //---------------------------------------------------------------------------- bool TextureMgr::TestImageWithOpenGL( FIBITMAP*& pDib) { // recupero le dimensioni in pixel dell'immagine int nWidth = FreeImage_GetWidth( pDib) ; int nHeight = FreeImage_GetHeight( pDib) ; // verifico sia caricabile da OpenGL corrente glTexImage2D( GL_PROXY_TEXTURE_2D, 0, GL_RGBA, nWidth, nHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, FreeImage_GetBits( pDib)) ; int nW ; glGetTexLevelParameteriv( GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &nW) ; if ( nW == 0) { // recupero la massima dimensione di una texture per OpenGL corrente int nMaxTextDim ; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &nMaxTextDim) ; // cerco le dimensioni POT (power of two) appena minori delle due dimensioni int nNewW = nMaxTextDim ; while ( nNewW > nWidth) nNewW /= 2 ; int nNewH = nMaxTextDim ; while ( nNewH > nHeight) nNewH /= 2 ; // deformo la texture per avere queste dimensioni FIBITMAP* pTmpDib = pDib ; pDib = FreeImage_Rescale( pTmpDib, nNewW, nNewH, FILTER_BILINEAR) ; FreeImage_Unload( pTmpDib) ; nWidth = nNewW ; nHeight = nNewH ; // verifico che la nuova immagine sia valida if ( pDib == nullptr) return false ; if ( FreeImage_GetBits( pDib) == nullptr || FreeImage_GetWidth( pDib) != nWidth || FreeImage_GetHeight( pDib) != nHeight) { FreeImage_Unload( pDib) ; pDib = nullptr ; return false ; } } return true ; } //---------------------------------------------------------------------------- //// !!! PROVVISORIO Textures //#define checkImageWidth 64 //#define checkImageHeight 64 //static GLubyte checkImage[checkImageHeight][checkImageWidth][4]; //static GLuint texName; // //void makeCheckImage(void) //{ // int i, j, c; // // for (i = 0; i < checkImageHeight; i++) { // for (j = 0; j < checkImageWidth; j++) { // c = (((i&0x8)==0)^((j&0x8)==0))*255; // checkImage[i][j][0] = (GLubyte) c; // checkImage[i][j][1] = (GLubyte) c; // checkImage[i][j][2] = (GLubyte) c; // checkImage[i][j][3] = (GLubyte) 255; // } // } //} // //#include "\EgtDev\Extern\FreeImage\Include\FreeImage.h" //#include "\EgtDev\Include\EgtStringConverter.h" //#include