# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

texture_grouped.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "std3d.h"
00027 
00028 #include "3d/texture_grouped.h"
00029 #include "3d/texture_file.h"
00030 #include "nel/misc/common.h"
00031 #include "nel/misc/path.h"
00032 
00033 #include <algorithm>
00034 
00035 namespace NL3D {
00036 
00039 static inline void GetTextureSize(ITexture *tex, uint &width, uint &height)
00040 {       
00041         if (tex->getClassName() == "CTextureFile")
00042         {
00043                 CTextureFile *tf = static_cast<CTextureFile *>(tex);                                                            
00044                 uint32 srcWidth, srcHeight;
00045                 if (!tf->getFileName().empty())
00046                 {
00047                         try
00048                         {
00049                                 CBitmap::loadSize(NLMISC::CPath::lookup(tf->getFileName()), srcWidth, srcHeight);
00050                                 if (srcWidth == 0 || srcHeight == 0)
00051                                 {
00052                                         nlinfo("Unable to get size of texture : %s", tf->getFileName().c_str());
00053                                         width = height = 0;
00054                                         return;
00055                                 }
00056                                 width = srcWidth;
00057                                 height = srcHeight;
00058                         }
00059                         catch (NLMISC::EPathNotFound &e)
00060                         {
00061                                 nlinfo("%s", e.what());
00062                                 width = height = 0;
00063                         }
00064                         catch (NLMISC::EStream &e)
00065                         {
00066                                 nlinfo("unable to load size from a bitmap ! name = %s", tf->getFileName().c_str());
00067                                 nlinfo("reason = %s", e.what());
00068                                 width = height = 0;
00069                         }
00070                 }
00071                 else
00072                 {
00073                         width = height = 0;
00074                 }               
00075         }
00076         else // we must generate the texture to get its size
00077         {
00078                 tex->generate();
00079                 width = tex->getWidth();
00080                 height = tex->getHeight();
00081                 if (tex->getReleasable())
00082                 {
00083                         tex->release();
00084                 }
00085         }
00086 }
00087 
00089 CTextureGrouped::CTextureGrouped() : _NbTex(0)
00090 {
00091         setFilterMode(Linear, LinearMipMapOff);
00092 }
00093 
00095 CTextureGrouped::CTextureGrouped(const CTextureGrouped &src) : ITexture(src)
00096 {
00097         // copy the part associated with us;
00098         duplicate(src);
00099 }
00100 
00102 void CTextureGrouped::duplicate(const CTextureGrouped &src)
00103 {       
00104         _NbTex = src._NbTex;
00105         TTexList texCopy(src._Textures.begin(), src._Textures.end());
00106         _Textures.swap(texCopy);
00107         TFourUVList     uvCopy(_TexUVs.begin(), _TexUVs.end());
00108         _TexUVs.swap(uvCopy);
00109 }
00110 
00112 CTextureGrouped &CTextureGrouped::operator=(const CTextureGrouped &src)
00113 {
00114         ITexture::operator=(src); // copy parent part
00115         duplicate(src);
00116         return *this;
00117 }
00118 
00120 bool CTextureGrouped::areValid(CSmartPtr<ITexture> *textureTab, uint nbTex)
00121 {               
00122         bool result = true;     
00123         uint k;
00124         for(k = 0; k < nbTex; ++k)
00125         {
00126                 textureTab[k]->generate();              
00127                 if (textureTab[k]->getWidth() != textureTab[0]->getWidth()
00128                         || textureTab[k]->getHeight() != textureTab[0]->getHeight()
00129                         || textureTab[k]->getPixelFormat() != textureTab[0]->getPixelFormat()
00130                    )
00131                 { 
00132                         result = false; 
00133                         break; 
00134                 }               
00135         }
00136 
00137 
00138         for (k = 0; k < nbTex; ++k)
00139         {
00140                 if (textureTab[k]->getReleasable()) textureTab[k]->release();
00141         }
00142         return result;
00143 }
00144 
00146 void CTextureGrouped::setTextures(CSmartPtr<ITexture> *textureTab, uint nbTex)
00147 {
00148         nlassert(nbTex > 0);    
00149         
00150         
00151         if (!areValid(textureTab, nbTex))
00152         {
00153                 displayIncompatibleTextureWarning(textureTab, nbTex);           
00154                 makeDummies(textureTab, nbTex);
00155         }
00156         
00157         
00158         // Generate the first texture to get the size   
00159         uint width, height;
00160         GetTextureSize(textureTab[0], width, height);
00161 
00162         const uint totalHeight = height * nbTex;
00163         const uint realHeight  = totalHeight ? NLMISC::raiseToNextPowerOf2(totalHeight) : 0;    
00164         
00165         _TexUVs.clear();
00166         _Textures.clear();      
00167         
00168         const float deltaV = realHeight ? (float(totalHeight) / float(realHeight)) * (1.0f / nbTex)
00169                                                                         : 0.f;
00170         _DeltaUV = CUV(1,  deltaV);
00171         CUV currentUV(0, 0);
00172         
00173         _Textures.reserve(nbTex);
00174         _TexUVs.reserve(nbTex);
00175 
00176         for(uint k = 0; k < nbTex; ++k)
00177         {       
00178                 TFourUV uvs;
00179                 _Textures.push_back(textureTab[k]);
00180 
00181                 uvs.uv0 = currentUV;
00182                 uvs.uv1 = currentUV + CUV(1, 0);
00183                 uvs.uv2 = currentUV + _DeltaUV;
00184                 uvs.uv3 = currentUV + CUV(0, deltaV);
00185                 currentUV.V += deltaV;
00186                 _TexUVs.push_back(uvs);
00187         }       
00188         _NbTex = nbTex;
00189         touch(); // the texture need regeneration
00190 
00191         nlassert(_NbTex == _Textures.size());
00192 }
00193 
00195 void CTextureGrouped::doGenerate()
00196 {
00197         nlassert(_NbTex == _Textures.size());
00198         if (_NbTex == 0)
00199         {
00200                 makeDummy();
00201         }
00202         else
00203         {                               
00204                 // Generate the first texture to get the size   
00205                 _Textures[0]->generate();
00206                 const uint width = _Textures[0]->getWidth(), height = _Textures[0]->getHeight();                
00207                 const uint totalHeight = height * _NbTex;
00208                 const uint realHeight  = NLMISC::raiseToNextPowerOf2(totalHeight);      
00209 
00210                 resize(width, realHeight, _Textures[0]->getPixelFormat());
00211                 
00212                 uint k;
00213                 sint32 currY =  0;
00214                 for(k = 0; k < _NbTex; ++k)
00215                 {                       
00216                         _Textures[k]->generate();
00217                         if (_Textures[k]->getWidth() != width
00218                                 || _Textures[k]->getHeight() != height
00219                                 || _Textures[k]->getPixelFormat() != _Textures[0]->getPixelFormat())
00220                         {
00221                                 makeDummy();
00222                                 break;
00223                         }                                               
00224                         this->blit(_Textures[k], 0, currY);
00225                         currY += height;                        
00226                 }
00227 
00228                 for(k = 0; k < _NbTex; ++k)
00229                 {
00230                         if ( _Textures[k]->getReleasable())
00231                         {
00232                                 _Textures[k]->release();
00233                         }
00234                 }
00235         }       
00236 }
00237 
00239 void CTextureGrouped::getTextures(CSmartPtr<ITexture> *textureTab) const
00240 {
00241         CSmartPtr<ITexture> *dest = textureTab;
00242 
00243         for(TTexList::const_iterator it = _Textures.begin(); it != _Textures.end(); ++it, ++dest)
00244         {
00245                 *dest = *it;
00246         }
00247 }
00248 
00250 bool    CTextureGrouped::supportSharing() const
00251 {
00252         // all textures in this group must support sharing for this one to support it
00253         for(TTexList::const_iterator it = _Textures.begin(); it != _Textures.end(); ++it)
00254         {
00255                 if (!(*it)->supportSharing()) return false;
00256         }
00257 
00258         return true;
00259 }
00260 
00262 std::string             CTextureGrouped::getShareName() const
00263 {
00264         nlassert(supportSharing());
00265 
00266         std::string shareName("groupedTex:");
00267         for(TTexList::const_iterator it = _Textures.begin(); it != _Textures.end(); ++it)
00268         {
00269                 shareName += (*it)->getShareName() + std::string("|");
00270         }
00271         return shareName;
00272 }
00273 
00275 void CTextureGrouped::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00276 {
00277         f.serialVersion(1);
00278         
00279         if (f.isReading())
00280         {
00281                 TTexList texList;
00282 
00284                 uint32 nbTex;
00285                 f.serial(nbTex);
00286 
00288                 ITexture *ptTex = NULL;         
00289                 texList.reserve(nbTex);
00290                 for (uint k = 0; k < nbTex; ++k)
00291                 {
00292                         f.serialPolyPtr(ptTex);
00293                         texList.push_back(ptTex);
00294                 }               
00295                 
00296                 // setup the textures
00297                 setTextures(&texList[0], nbTex);
00298                 touch();
00299         }
00300         else
00301         {               
00302                 f.serial(_NbTex);
00303                 ITexture *ptTex;
00304                 for (TTexList::iterator it = _Textures.begin(); it != _Textures.end(); ++it)
00305                 {
00306                         ptTex = *it;
00307                         f.serialPolyPtr(ptTex);
00308                 }               
00309         }       
00310 }
00311 
00313 void CTextureGrouped::release()
00314 {
00315         ITexture::release();
00316         for(uint k = 0; k < _NbTex; ++k)
00317         {
00318                 if ( _Textures[k]->getReleasable())
00319                 {
00320                         _Textures[k]->release();
00321                 }
00322         }
00323 }
00324 
00326 void CTextureGrouped::makeDummies(CSmartPtr<ITexture> *textureTab,uint nbTex)
00327 {
00328         for(uint k = 0; k < nbTex; ++k)
00329         {
00330                 textureTab[k] = new CTextureFile("DummyTex"); // well this shouldn't exist..
00331         }       
00332 }
00333 
00335 void CTextureGrouped::displayIncompatibleTextureWarning(CSmartPtr<ITexture> *textureTab,uint nbTex)
00336 {
00337         nlwarning("=======================================================");
00338         nlwarning("CTextureGrouped : found incompatible textures, that differs by size or format :"     );
00339         for(uint k = 0; k < nbTex; ++k)
00340         {
00341                 if (textureTab[k])
00342                 {               
00343                         nlwarning((textureTab[k]->getShareName()).c_str());
00344                 }
00345                 else
00346                 {
00347                         nlwarning("NULL Texture found");
00348                 }
00349         }
00350         nlwarning("=======================================================");
00351 }
00352 
00353 
00354 } // NL3D