![[]](/images/special/trans.gif)
LibN2L-4 Library Code ReferenceClassesCompounds Files Members Method Index Full Reference cRSkyBox.cppGo 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 |