AaronCameron.net
Not Left, nor right. Just correct.
Not a Member? - Login or Create an Account
Tuesday the 22nd of May 2012 @ 02:44am
Front Page Journal Projects Your Profile About
[]

LibN2L-4 Library Code Reference

Classes
Compounds
Files
Members
Method Index
Full Reference

cRSkyBox.cpp

Go to the documentation of this file.
00001 /************************************************************************
00002 Nova-2 Library (libN2L, or simply n2l) Game development C++ Library
00003 Copyright (C) 2002  Aaron Cameron
00004 
00005 This library is free software; you can redistribute it and/or
00006 modify it under the terms of the GNU Lesser General Public
00007 License as published by the Free Software Foundation; either
00008 version 2.1 of the License, or (at your option) any later version.
00009 
00010 This library is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 Lesser General Public License for more details.
00014 
00015 You should have received a copy of the GNU Lesser General Public
00016 License along with this library; if not, write to the Free Software
00017 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00018 
00019 A copy of the GNU Lesser General Public License has been provided with
00020 this library in the file 'COPYING'.
00021 
00022 Contact information for the author of this library has been provided
00023 with this library in the file 'AUTHOR'.
00024 ************************************************************************/
00025 #include "renderObjects/cRSkyBox.h"
00026 
00027 #include "n2l/materials.h"
00028 #include "n2l/dynVars.h"
00029 #include "n2l/vfs.h"
00030 #include "n2l/resourceManagement.h"
00031 
00032 #include "renderObjects/cRFrustum.h"
00033 
00034 #include <math.h>
00035 
00036 using namespace std;
00037 
00038 namespace n2l
00039 {
00040 
00041     /*******************************************************************/
00042     cRSkyBox::cRSkyBox()
00043     {
00044         init();
00045     }
00046 
00047     /*******************************************************************/
00048     cRSkyBox::cRSkyBox( const cVfsNodeInterface & iNode )
00049     {
00050         init();
00051         load( iNode );
00052     }
00053 
00054     /*******************************************************************/
00055     cRSkyBox::cRSkyBox( const cDynVar & iDef )
00056     {
00057         init();
00058         load( iDef );
00059     }
00060 
00061     /*******************************************************************/
00062     cRSkyBox::~cRSkyBox()
00063     {
00064         free();
00065     }
00066 
00067     /******************************************************************/
00068     void cRSkyBox::load( const cDynVar &iDef )
00069     {
00070         clear();
00071         // Do the load here
00072         try
00073         {
00074             // Are our textures a directory, or a list
00075             vector<cAutoPtr<const cGLTexture> > textures;
00076             if (iDef["textures"].isArray()) {
00077                 // Load this list
00078                 const cDynVar::tConstIterator Last( iDef["textures"].end() );
00079                 for (cDynVar::tConstIterator i=iDef["textures"].begin(); i!=Last; ++i)
00080                     textures.push_back( cResourceManager::get<cGLTexture>(i->second) );
00081             }
00082 
00083             subFaceRep( iDef.keyValueOr("subFaceRep", 1.0f) );
00084             boxSize( iDef.keyValueOr("boxSize", 1.0f ) );
00085 
00086             tUbyte divisions = tUbyte( n2lMax(tSint(iDef.keyValueOr("divisions", 1)),0) );
00087 
00088             // Build the box as requested
00089             tString buildTypeStr( iDef["buildType"] );
00090             if (buildTypeStr.empty()) buildTypeStr += 's';
00091             switch ( buildTypeStr[0] )
00092             {
00093                 case 'r':
00094                     randomBuildFrom( divisions, textures );
00095                     break;
00096 
00097                 case 's':
00098                 default:
00099                     stepBuildFrom( divisions, textures );
00100                     break;
00101             }
00102 
00103         }
00104         catch ( const cException &iException )
00105         {
00106             throw cBadDataUseException( "cRSkyBox::load",
00107                 tString("Not a valid sky box: ")+
00108                 tString(iException) );
00109         }
00110     }
00111 
00112 
00113     /******************************************************************/
00114     void cRSkyBox::load( const cVfsNodeInterface &iNode )
00115     {
00116         tVfsFileBuffer buffer;
00117         tUint DataOffset;
00118         try
00119         {
00120             DataOffset = vfsNodeFileWithHeader( iNode,
00121                                                 "n2l::cRSkyBox",
00122                                                 buffer );
00123         }
00124         catch ( const cBadDataUseException & iException )
00125         {
00126             throw cBadDataUseException( "cRSkyBox::load",
00127                                         tString("Failed to load: \"")+
00128                                         iNode.name() + "\": " +
00129                                         tString(iException) );
00130         }
00131         cDynVar def;
00132         def.unserialize( buffer, DataOffset );
00133         load( def );
00134     }
00135 
00136     /*******************************************************************/
00137     void cRSkyBox::boxSize( const tFloat &iSize )
00138     {
00139         mBoxSize = iSize;
00140         // Set up halfsizes
00141         const tFloat HalfSize( mBoxSize/2.0f );
00142         mFaceOffset[0].set(-HalfSize,-HalfSize,HalfSize);
00143         mFaceOffset[1].set(-HalfSize,-HalfSize,-HalfSize);
00144         mFaceOffset[2].set(-HalfSize,-HalfSize,-HalfSize);
00145         mFaceOffset[3].set(-HalfSize,HalfSize,-HalfSize);
00146         mFaceOffset[4].set(HalfSize,-HalfSize,-HalfSize);
00147         mFaceOffset[5].set(-HalfSize,-HalfSize,-HalfSize);
00148     }
00149 
00150     /*******************************************************************/
00151     void cRSkyBox::subFaceRep( const tFloat &iRep )
00152     {
00153         mSubFaceRep = iRep;
00154 
00155         const tFloat SecSize( mBoxSize/(mDivisions+1) );
00156         mFaceUnits[0][0].set(SecSize,0,0);
00157         mFaceUnits[0][1].set(0,SecSize,0);
00158 
00159         mFaceUnits[1][0].set(0,SecSize,0);
00160         mFaceUnits[1][1].set(SecSize,0,0);
00161         
00162         mFaceUnits[2][0].set(SecSize,0,0);
00163         mFaceUnits[2][1].set(0,0,SecSize);
00164 
00165         mFaceUnits[3][0].set(0,0,SecSize);
00166         mFaceUnits[3][1].set(SecSize,0,0);
00167 
00168         mFaceUnits[4][0].set(0,SecSize,0);
00169         mFaceUnits[4][1].set(0,0,SecSize);
00170 
00171         mFaceUnits[5][0].set(0,0,SecSize);
00172         mFaceUnits[5][1].set(0,SecSize,0);
00173         
00174     }
00175 
00176     /*******************************************************************/
00177     void cRSkyBox::stepBuildFrom( const tUbyte iDivisions,
00178         const vector<cAutoPtr<const cGLTexture> > &iTextures )
00179     {
00180         // Clear ourselves if we were built.
00181         clear();
00182 
00183         const tUint NumTex( iTextures.size() );
00184         if (!NumTex)
00185             throw cBadDataUseException( "cRSkyBox::stepSelectFrom",
00186                 "Tried to build from an empty texture list" );
00187 
00188         mDivisions = iDivisions;
00189         // We have to reset the cached calculations
00190         subFaceRep( mSubFaceRep );
00191 
00192         // Do it.
00193         const tUint NumSubFaces( (mDivisions+1)*(mDivisions+1) );
00194 
00195         mTextures = iTextures;
00196         
00197         tUint imgIndex(0);
00198         for (tUint f=Face_Front; f<Face_NumFaces; ++f)
00199             for (tUint i=0; i<NumSubFaces; ++i) {
00200                 if (imgIndex==NumTex) imgIndex = 0;
00201                 // Add it to the proper bin.
00202                 mFaces[f][imgIndex].push_back( i );
00203                 ++imgIndex;
00204             }
00205     }
00206 
00207 
00208     /*******************************************************************/
00209     void cRSkyBox::randomBuildFrom( const tUbyte iDivisions,
00210         const vector<cAutoPtr<const cGLTexture> > &iTextures )
00211     {
00212         // Clear ourselves if we were built.
00213         clear();
00214 
00215         const tUint NumTex( iTextures.size() );
00216         if (!NumTex)
00217             throw cBadDataUseException( "cRSkyBox::stepSelectFrom",
00218                 "Tried to build from an empty texture list" );
00219 
00220         mDivisions = iDivisions;
00221         // We have to reset the cached calculations
00222         subFaceRep( mSubFaceRep );
00223 
00224         // Do it.
00225         const tUint NumSubFaces( (mDivisions+1)*(mDivisions+1) );
00226 
00227         mTextures = iTextures;
00228         
00229         for (tUint f=Face_Front; f<Face_NumFaces; ++f)
00230             for (tUint i=0; i<NumSubFaces; ++i) {
00231                 mFaces[f][n2lRandom(NumTex)].push_back( i );
00232             }
00233     }
00234 
00235     /*******************************************************************/
00236     void cRSkyBox::draw( const tUint iOptions ) const
00237     {
00238         if (mDivisions==-1) return;
00239 
00240         // Do the draw.
00241         glPushAttrib( GL_ALL_ATTRIB_BITS );
00242 
00243         glEnable( GL_TEXTURE_2D );
00244         glDisable( GL_DEPTH_TEST );
00245         glDisable( GL_BLEND );
00246         glDepthMask( false );
00247         glCullFace( GL_BACK );
00248         glEnable( GL_CULL_FACE );
00249         glColor4f(1,1,1,1);
00250 
00251         // Do it.
00252         for (tUint f=Face_Front; f<Face_NumFaces; ++f)
00253         {
00254             for (tTexDivMap::const_iterator t=mFaces[f].begin();
00255                 t!=mFaces[f].end(); ++t)
00256             {
00257                 mTextures[t->first]->bind();
00258                 glBegin( GL_QUADS );
00259                 // Do all the sub faces associated with this texture
00260                 for (vector<tUint>::const_iterator i=t->second.begin();
00261                     i!=t->second.end(); ++i)
00262                 {
00263                     const tVector3f SectOffset( mFaceUnits[f][0]*((*i)%(mDivisions+1)) + mFaceUnits[f][1]*((*i)/(mDivisions+1)) );
00264                     
00265                     glTexCoord2f( mSubFaceRep,0 );
00266                     (SectOffset+mFaceOffset[f]+mFaceUnits[f][1]).glVertex3f();
00267 
00268                     glTexCoord2f( 0,0 );
00269                     (SectOffset+mFaceOffset[f]+mFaceUnits[f][0]+mFaceUnits[f][1]).glVertex3f();
00270                     
00271                     glTexCoord2f( 0,mSubFaceRep );
00272                     (SectOffset+mFaceOffset[f]+mFaceUnits[f][0]).glVertex3f();
00273 
00274                     glTexCoord2f( mSubFaceRep,mSubFaceRep );
00275                     (SectOffset+mFaceOffset[f]).glVertex3f();
00276                     
00277                     
00278                 } // each subface
00279                 glEnd();
00280             } // each texture
00281         } // each face
00282 
00283         glPopAttrib();
00284     }
00285 
00286     /*******************************************************************/
00287     void cRSkyBox::draw( const cRFrustum &iFrustum,
00288         const tVector3f &iPosAdjust, const tUint iOptions ) const
00289     {
00290         if (mDivisions==-1) return;
00291 
00292         // Do the draw.
00293         glPushAttrib( GL_ALL_ATTRIB_BITS );
00294 
00295         glEnable( GL_TEXTURE_2D );
00296         glDisable( GL_DEPTH_TEST );
00297         glDisable( GL_BLEND );
00298         glDepthMask( false );
00299         glCullFace( GL_BACK );
00300         glEnable( GL_CULL_FACE );
00301         glColor4f(1,1,1,1);
00302 
00303         // Do it.
00304         for (tUint f=Face_Front; f<Face_NumFaces; ++f)
00305         {
00306             for (tTexDivMap::const_iterator t=mFaces[f].begin();
00307                 t!=mFaces[f].end(); ++t)
00308             {
00309                 mTextures[t->first]->bind();
00310                 glBegin( GL_QUADS );
00311                 // Do all the sub faces associated with this texture
00312                 for (vector<tUint>::const_iterator i=t->second.begin();
00313                     i!=t->second.end(); ++i)
00314                 {
00315                     const tVector3f SectOffset( mFaceUnits[f][0]*((*i)%(mDivisions+1)) + mFaceUnits[f][1]*((*i)/(mDivisions+1)) );
00316 
00317                     const tVector3f p0 = (SectOffset+mFaceOffset[f]+mFaceUnits[f][1]);
00318                     const tVector3f p1 = (SectOffset+mFaceOffset[f]+mFaceUnits[f][0]+mFaceUnits[f][1]);
00319                     const tVector3f p2 = (SectOffset+mFaceOffset[f]+mFaceUnits[f][0]);
00320                     const tVector3f p3 = (SectOffset+mFaceOffset[f]);
00321 
00322                     if (!iFrustum.testQuad( p0+iPosAdjust, p1+iPosAdjust,
00323                         p2+iPosAdjust, p3+iPosAdjust ))
00324                         continue;
00325 
00326                     
00327                     glTexCoord2f( mSubFaceRep,0 );
00328                     p0.glVertex3f();
00329 
00330                     glTexCoord2f( 0,0 );
00331                     p1.glVertex3f();
00332                     
00333                     glTexCoord2f( 0,mSubFaceRep );
00334                     p2.glVertex3f();
00335 
00336                     glTexCoord2f( mSubFaceRep,mSubFaceRep );
00337                     p3.glVertex3f();
00338                     
00339                 } // each subface
00340                 glEnd();
00341             } // each texture
00342         } // each face
00343 
00344         glPopAttrib();
00345     }
00346 
00347     /*******************************************************************/
00348     void cRSkyBox::clear()
00349     {
00350         if (mDivisions==-1) return;
00351 
00352         for (tUint i=Face_Back; i<Face_NumFaces; ++i)
00353             mFaces[i].clear();
00354 
00355         mDivisions = -1;
00356 
00357         boxSize(1.0f);
00358         subFaceRep(1.0f);
00359     }
00360 
00361     /*******************************************************************/
00362     void cRSkyBox::init()
00363     {
00364         mDivisions = -1;
00365         
00366         boxSize(1.0f);
00367         subFaceRep(1.0f);
00368     }
00369 
00370     /*******************************************************************/
00371     void cRSkyBox::free()
00372     {
00373         if (mDivisions==-1) return;
00374         for (tUint i=Face_Back; i<Face_NumFaces; ++i)
00375             mFaces[i].clear();
00376     }
00377 
00378     /*******************************************************************/
00379 
00380     /*******************************************************************/
00381 
00382     /*******************************************************************/
00383 
00384     /*******************************************************************/
00385 
00386     /*******************************************************************/
00387 
00388     /*******************************************************************/
00389 
00390 
00391 } // namespace
©2012 Aaron Cameron