![[]](/images/special/trans.gif)
LibN2L-4 Library Code ReferenceClassesCompounds Files Members Method Index Full Reference cRSkyMobile.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/cRSkyMobile.h" 00026 00027 #include "n2l/vfs.h" 00028 #include "n2l/dynVars.h" 00029 #include "n2l/materials.h" 00030 #include "n2l/resourceManagement.h" 00031 00032 #include "renderObjects/cRFrustum.h" 00033 00034 using namespace std; 00035 00036 namespace n2l 00037 { 00038 00039 /**************************************************************************/ 00040 cRSkyMobile::cRSkyMobile() 00041 { 00042 init(); 00043 } 00044 00045 /**************************************************************************/ 00046 cRSkyMobile::cRSkyMobile( const cVfsNodeInterface &iNode ) 00047 { 00048 init(); 00049 load( iNode ); 00050 } 00051 00052 /**************************************************************************/ 00053 cRSkyMobile::cRSkyMobile( const cDynVar &iDef ) 00054 { 00055 init(); 00056 load( iDef ); 00057 } 00058 00059 /**************************************************************************/ 00060 cRSkyMobile::~cRSkyMobile() 00061 { 00062 free(); 00063 } 00064 00065 /**************************************************************************/ 00066 void cRSkyMobile::load( const cDynVar &iDef ) 00067 { 00068 clear(); 00069 00070 // Load mobiles, last (and only, for now) 00071 if (!iDef["mobiles"].isArray()) return; 00072 00073 try 00074 { 00075 mSkipSort = true; 00076 const cDynVar::tConstIterator Last( iDef["mobiles"].end() ); 00077 for (cDynVar::tConstIterator i=iDef["mobiles"].begin(); i!=Last; ++i) { 00078 const cDynVar &Rotation( i->second["rotation"] ); 00079 const cDynVar &Size( i->second["size"] ); 00080 addSprite( 00081 i->first, 00082 tVector3f( Rotation[0], Rotation[1], Rotation[2] ), 00083 tFloat(i->second.keyValueOr("distance",1.0f)), 00084 tVector2f( Size.keyValueOr(0,1.0f), Size.keyValueOr(1,1.0f) ), 00085 cResourceManager::get<cGLTexture>( i->second["texture"] ) 00086 ); 00087 00088 } 00089 mSkipSort = false; 00090 } 00091 catch ( const cException &iException ) 00092 { 00093 clear(); 00094 mSkipSort = false; 00095 iException.rethrow(); 00096 } 00097 sort(); 00098 } 00099 00100 /**************************************************************************/ 00101 void cRSkyMobile::load( const cVfsNodeInterface &iNode ) 00102 { 00103 tVfsFileBuffer buffer; 00104 tUint DataOffset; 00105 try 00106 { 00107 DataOffset = vfsNodeFileWithHeader( iNode, 00108 "n2l::cRSkyMobile", 00109 buffer ); 00110 } 00111 catch ( const cBadDataUseException & iException ) 00112 { 00113 throw cBadDataUseException( "cRSkyMobile::load", 00114 tString("Failed to load: \"")+ 00115 iNode.name() + "\": " + 00116 tString(iException) ); 00117 } 00118 cDynVar def; 00119 def.unserialize( buffer, DataOffset ); 00120 load( def ); 00121 } 00122 00123 /**************************************************************************/ 00124 void cRSkyMobile::draw( const tUint iOptions ) const 00125 { 00126 glPushAttrib( GL_ALL_ATTRIB_BITS ); 00127 00128 glEnable( GL_TEXTURE_2D ); 00129 glDisable( GL_DEPTH_TEST ); 00130 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); 00131 glEnable( GL_BLEND ); 00132 glDepthMask( false ); 00133 glCullFace( GL_BACK ); 00134 glEnable( GL_CULL_FACE ); 00135 glColor4f(1,1,1,1); 00136 00137 const tUint NumSprites( mSprites.size() ); 00138 00139 for (tUint i=0; i<NumSprites; ++i) { 00140 mSprites[i].mTexture->bind(); 00141 00142 glBegin( GL_QUADS ); 00143 glTexCoord2f( 0,1 ); 00144 mSprites[i].mA.glVertex3f(); 00145 00146 glTexCoord2f( 1,1 ); 00147 mSprites[i].mB.glVertex3f(); 00148 00149 glTexCoord2f( 1,0 ); 00150 mSprites[i].mC.glVertex3f(); 00151 00152 glTexCoord2f( 0,0 ); 00153 mSprites[i].mD.glVertex3f(); 00154 00155 glEnd(); 00156 } 00157 00158 glPopAttrib(); 00159 } 00160 00161 /**************************************************************************/ 00162 void cRSkyMobile::draw( const cRFrustum &iFrustum, 00163 const tVector3f &iPosAdjust, const tUint iOptions ) const 00164 { 00165 glPushAttrib( GL_ALL_ATTRIB_BITS ); 00166 00167 glEnable( GL_TEXTURE_2D ); 00168 glDisable( GL_DEPTH_TEST ); 00169 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); 00170 glEnable( GL_BLEND ); 00171 glDepthMask( false ); 00172 glCullFace( GL_BACK ); 00173 glEnable( GL_CULL_FACE ); 00174 glColor4f(1,1,1,1); 00175 00176 const tUint NumSprites( mSprites.size() ); 00177 00178 for (tUint i=0; i<NumSprites; ++i) { 00179 if (!iFrustum.testQuad( mSprites[i].mA+iPosAdjust, 00180 mSprites[i].mB+iPosAdjust, 00181 mSprites[i].mC+iPosAdjust, 00182 mSprites[i].mD+iPosAdjust )) continue; 00183 00184 mSprites[i].mTexture->bind(); 00185 00186 glBegin( GL_QUADS ); 00187 glTexCoord2f( 0,1 ); 00188 mSprites[i].mA.glVertex3f(); 00189 00190 glTexCoord2f( 1,1 ); 00191 mSprites[i].mB.glVertex3f(); 00192 00193 glTexCoord2f( 1,0 ); 00194 mSprites[i].mC.glVertex3f(); 00195 00196 glTexCoord2f( 0,0 ); 00197 mSprites[i].mD.glVertex3f(); 00198 00199 glEnd(); 00200 } 00201 00202 glPopAttrib(); 00203 } 00204 00205 /**************************************************************************/ 00206 const cRSkyMobile::tSprite &cRSkyMobile::mustFindSprite( 00207 const tString &iName ) const 00208 { 00209 const vector<tSprite>::const_iterator LastSprite( mSprites.end() ); 00210 for (vector<tSprite>::const_iterator i=mSprites.begin(); 00211 i!=LastSprite; ++i) 00212 { 00213 if (i->mName==iName) return *i; 00214 } 00215 throw cOutOfBoundsException( "cRSkyMobile::mustFindSprite", 00216 tString("No such sprite named: ")+iName ); 00217 } 00218 00219 /**************************************************************************/ 00220 void cRSkyMobile::addSprite( const tString &iName, 00221 const tVector3f &iRotation, 00222 const tFloat &iDistance, const tVector2f &iSize, 00223 const cAutoPtr<const cGLTexture> &iTexture ) 00224 { 00225 if (!iTexture.isSet()) 00226 throw cBadDataUseException( "cRSkyMobile::addSprite", 00227 "Tried to add a null texture sprite" ); 00228 00229 // Calculate the unit vectors for this position. 00230 tVector3f uUp(0,1,0); 00231 tVector3f uLeft(1,0,0); 00232 uUp.rotateD( -iRotation.y(), tVector3f(1,0,0) ); 00233 uUp.rotateD( iRotation.x(), tVector3f(0,1,0) ); 00234 uLeft.rotateD( -iRotation.y(), tVector3f(1,0,0) ); 00235 uLeft.rotateD( iRotation.x(), tVector3f(0,1,0) ); 00236 tVector3f uPos( uLeft.cross(uUp)*iDistance ); 00237 00238 // Finally, roll the vector around the direction vector 00239 tVector3f posDirV( uPos ); 00240 posDirV.normalize(); 00241 00242 uUp.rotateD( -iRotation.z(), posDirV ); 00243 uLeft.rotateD( -iRotation.z(), posDirV ); 00244 00245 tSprite newSprite; 00246 newSprite.mName = iName; 00247 newSprite.mA = uPos + (uUp*-0.5f*iSize.y())+(uLeft*0.5f*iSize.x()); 00248 newSprite.mB = uPos + (uUp*-0.5f*iSize.y())+(uLeft*-0.5f*iSize.x()); 00249 newSprite.mC = uPos + (uUp*0.5f*iSize.y())+(uLeft*-0.5f*iSize.x()); 00250 newSprite.mD = uPos + (uUp*0.5f*iSize.y())+(uLeft*0.5f*iSize.x()); 00251 newSprite.mDistance = iDistance; // Keep this to sort faster. 00252 newSprite.mSize = iSize; // Later queries might want this. 00253 newSprite.mTexture = iTexture; 00254 00255 mSprites.push_back( newSprite ); 00256 00257 // Stupid to sort the whole list every time. But hey, I suck. 00258 if (!mSkipSort) sort(); 00259 } 00260 00261 /**************************************************************************/ 00262 void cRSkyMobile::clear() 00263 { 00264 mSprites.clear(); 00265 mSkipSort = false; 00266 } 00267 00268 /**************************************************************************/ 00269 void cRSkyMobile::init() 00270 { 00271 mSkipSort = false; 00272 } 00273 00274 /**************************************************************************/ 00275 void cRSkyMobile::free() 00276 { 00277 } 00278 00279 /**************************************************************************/ 00280 void cRSkyMobile::sort() 00281 { 00282 const tUint NumSprites( mSprites.size() ); 00283 if (NumSprites<2) return; 00284 00285 for (tUint i1=0; i1<NumSprites-1; ++i1) 00286 for (tUint i2=0; i2<NumSprites-1-i1; ++i2) 00287 if ( mSprites[i2+1].mDistance > mSprites[i2].mDistance) { 00288 tSprite tempS( mSprites[i2+1] ); 00289 mSprites[i2+1] = mSprites[i2]; 00290 mSprites[i2] = tempS; 00291 } 00292 } 00293 00294 } // namespace |