![[]](/images/special/trans.gif)
LibN2L-4 Library Code ReferenceClassesCompounds Files Members Method Index Full Reference cPEmitter.cppGo to the documentation of this file.00001 /************************************************************************ 00002 Nova-2 Library (libN2L, or simply n2l) Game development C++ Library 00003 Copyright (C) 2003 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 "particles/cPEmitter.h" 00026 00027 #include "n2l/vfs.h" 00028 #include "n2l/dynVars.h" 00029 #include "n2l/resourceManagement.h" 00030 00031 #include "particles/cParticle.h" 00032 #include "particles/cParticleSystem.h" 00033 #include "particles/cPParticleSpec.h" 00034 00035 00036 #include <iostream> 00037 using namespace std; 00038 00039 /******************************************************************************/ 00040 namespace n2l 00041 { 00042 /**************************************************************************/ 00043 cPEmitter::cPEmitter() 00044 { 00045 init(); 00046 } 00047 00048 /**************************************************************************/ 00049 cPEmitter::cPEmitter( const cVfsNodeInterface &iNode ) 00050 { 00051 init(); 00052 load( iNode ); 00053 } 00054 00055 /**************************************************************************/ 00056 cPEmitter::cPEmitter( const cDynVar &iDef ) 00057 { 00058 init(); 00059 load( iDef ); 00060 } 00061 00062 /**************************************************************************/ 00063 cPEmitter::~cPEmitter() 00064 { 00065 } 00066 00067 /**************************************************************************/ 00068 void cPEmitter::load( const cVfsNodeInterface &iNode ) 00069 { 00070 const tUint DataOffset = 00071 vfsNodeFileWithHeader( iNode, "n2l::cPEmitter"); 00072 cDynVar def; 00073 def.unserialize( iNode.buffer().c_str()+DataOffset ); 00074 load( def ); 00075 } 00076 00077 /**************************************************************************/ 00078 void cPEmitter::load( const cDynVar &iDef ) 00079 { 00080 frequency( iDef["frequency"].keyValueOr("max",1.0f), 00081 iDef["frequency"].keyValueOr("min",0.0f) ); 00082 00083 if (iDef.keyExists("particleSpec")) 00084 particleSpec( cResourceManager::get<cPParticleSpec>( 00085 iDef["particleSpec"]) ); 00086 00087 if (iDef.keyExistsAsArray("velocity")) 00088 mVel.set( iDef["velocity"][0], iDef["velocity"][1], 00089 iDef["velocity"][2] ); 00090 00091 if (iDef.keyExistsAsArray("positionJitter")) 00092 positionJitter( tVector3f( iDef["positionJitter"][0], 00093 iDef["positionJitter"][1], iDef["positionJitter"][2] ) ); 00094 00095 if (iDef.keyExistsAsArray("positions")) { 00096 const cDynVar::tConstIterator Last = iDef["positions"].end(); 00097 for (cDynVar::tConstIterator i = iDef["positions"].begin(); 00098 i!=Last; ++i) 00099 { 00100 mPositions.push_back( tVector3f( i->second[0], 00101 i->second[1], i->second[2] ) ); 00102 } 00103 } 00104 00105 } 00106 00107 /**************************************************************************/ 00108 void cPEmitter::updateInto( const tUint &iTimePassed, 00109 cParticleSystem &ioSystem, const tFloat &iThrottle ) 00110 { 00111 static const tMatrix44f Identity( tMatrix44f().identity() ); 00112 updateInto( iTimePassed, ioSystem, Identity, iThrottle ); 00113 } 00114 00115 /**************************************************************************/ 00116 void cPEmitter::updateInto( const tUint &iTimePassed, 00117 cParticleSystem &ioSystem, const tMatrix44f &iTransMatrix, 00118 const tFloat &iThrottle ) 00119 { 00120 const tVector3f Zero( 0.0f,0.0f,0.0f ); 00121 00122 if (!mPSpec.isSet()) 00123 throw cBadDataUseException( "cPEmitter::updateInto", 00124 "Called on an emitter with no particle spec" ); 00125 00126 // For testing, lets start simple. 00127 mRemainder += tSint(iTimePassed); 00128 tFloat seconds = mRemainder/1000.0f; 00129 tFloat freq = mMinFreq + iThrottle*(mMaxFreq-mMinFreq); 00130 tSint emissions = tSint(seconds*freq); 00131 if (!emissions) return; 00132 00133 mRemainder -= tSint((emissions/freq)*1000.0f); 00134 00135 00136 //cout << "Seconds: " << seconds << endl; 00137 //cout << "Calc Freq: " << freq << endl; 00138 //cout << "# Emissions: " << emissions << endl; 00139 //cout << "Remainder (end): " << mRemainder << endl; 00140 //cout << "------------------------------------------------" << endl; 00141 //return; 00142 00143 tVector3f vel; 00144 iTransMatrix.multiply( vel, mVel ); 00145 00146 for (tSint i=0; i<emissions; ++i) { 00147 tVector3f pos; 00148 switch (mPositions.size()) { 00149 case 0: 00150 iTransMatrix.multiply( pos, Zero ); 00151 break; 00152 00153 case 1: 00154 iTransMatrix.multiply( pos, mPositions[0] ); 00155 break; 00156 00157 default: 00158 if (mLastEmissionFrom>=mPositions.size()) 00159 mLastEmissionFrom = 0; 00160 iTransMatrix.multiply( pos, mPositions[mLastEmissionFrom] ); 00161 ++mLastEmissionFrom; 00162 break; 00163 } 00164 if (mPositionJitter) { 00165 tVector3f tmp; 00166 iTransMatrix.multiply( tmp, mHalfMaxJitter ); 00167 pos -= tmp; 00168 pos.x() += tmp.x()*(n2lRandom(20000)/10000.0f); 00169 pos.y() += tmp.y()*(n2lRandom(20000)/10000.0f); 00170 pos.z() += tmp.z()*(n2lRandom(20000)/10000.0f); 00171 } 00172 pos.x() += iTransMatrix[tMatrix44f::_03]; 00173 pos.y() += iTransMatrix[tMatrix44f::_13]; 00174 pos.z() += iTransMatrix[tMatrix44f::_23]; 00175 ioSystem.ownParticle( mPSpec->newParticle( pos, vel ) ); 00176 } 00177 } 00178 00179 /**************************************************************************/ 00180 void cPEmitter::frequency( const tFloat &iMax, const tFloat &iMin ) 00181 { 00182 mMinFreq = n2lMax(0.0f,n2lMin(iMin,iMax)); 00183 mMaxFreq = n2lMax(0.0f,n2lMax(iMin,iMax)); 00184 } 00185 00186 /**************************************************************************/ 00187 void cPEmitter::positionJitter( const tVector3f &iJitter ) 00188 { 00189 mPositionJitter = true; 00190 mHalfMaxJitter = iJitter; 00191 mHalfMaxJitter *= 0.5f; 00192 } 00193 00194 /**************************************************************************/ 00195 void cPEmitter::disableJitter() 00196 { 00197 mPositionJitter = false; 00198 } 00199 00200 /**************************************************************************/ 00201 void cPEmitter::position( const tVector3f &iPos ) 00202 { 00203 switch (mPositions.size()) { 00204 case 1: 00205 mPositions[0] = iPos; 00206 break; 00207 00208 default: 00209 mPositions.clear(); 00210 mPositions.push_back( iPos ); 00211 break; 00212 } 00213 } 00214 00215 /**************************************************************************/ 00216 void cPEmitter::addFacePositions( const tTriangle3f &iTri, 00217 const tFloat &iMaxSurfaceArea, const tFloat &iMinSurfaceArea ) 00218 { 00219 const tFloat Area = iTri.area(); 00220 if (Area>iMaxSurfaceArea) { 00221 tTriangle3f a,b; 00222 iTri.subdivideLongest( a,b ); 00223 addFacePositions( a, iMaxSurfaceArea, 0.0f ); 00224 addFacePositions( b, iMaxSurfaceArea, 0.0f ); 00225 } else if (Area>iMinSurfaceArea) addPosition( iTri.center() ); 00226 } 00227 00228 /**************************************************************************/ 00229 void cPEmitter::particleSpec( const cAutoPtr<const cPParticleSpec> &iSpec ) 00230 { 00231 mPSpec = iSpec; 00232 } 00233 00234 /**************************************************************************/ 00235 00236 /**************************************************************************/ 00237 00238 /**************************************************************************/ 00239 void cPEmitter::init() 00240 { 00241 mRemainder = 0; 00242 mVel.set( 0.0f,0.0f,0.0f ); 00243 mMinFreq = 0.0f; 00244 mMaxFreq = 1.0f; 00245 mPositionJitter = false; 00246 mHalfMaxJitter.set(0.0f,0.0f,0.0f); 00247 mLastEmissionFrom = 0; 00248 } 00249 00250 } |