Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

XFuParticleSystem.cpp

Go to the documentation of this file.
00001 /*! \file 
00002  * X-Forge Util <br>
00003  * Copyright 2000-2003 Fathammer Ltd
00004  * 
00005  * \brief Particle system utility
00006  * 
00007  * $Id: XFuParticleSystem.cpp,v 1.15.2.1 2003/12/02 14:34:18 mikko Exp $
00008  * $Date: 2003/12/02 14:34:18 $
00009  * $Revision: 1.15.2.1 $
00010  */
00011 #include <xfcore/XFcCore.h>
00012 #include <xfcore/XFcGLTextureFromFile.h>
00013 #include <xfutil/XFuParticleSystem.h>
00014 
00015 // 
00016 // somewhat long-term TODO:
00017 // - Get rid of fixed point dependency (compile time or otherwise)
00018 // - multiple particle system support
00019 // - lots of other fixes and additions
00020 
00021 #ifndef PI
00022 #define PI 3.1415926535897932384626433832795f
00023 #endif
00024 #define PS_VERSIONTAG 0x03005350
00025 
00026 void XFuParticleSystem::PSSeed(INT32 v)
00027 {
00028     INT32 s = v & 31;
00029     INT32 t = v ^ 0x14951C57;
00030     mRandSeed2 = (t >> s) + (t << (32 - s));
00031     s = (v >> 5) & 31;
00032     t = v ^ 0x6C691B25;
00033     mRandSeed1 = (t >> s) + (t << (32 - s));
00034 }
00035 
00036 
00037 // Sol's rol'n'xor noise function 
00038 INT32 XFuParticleSystem::PSRand()
00039 {
00040     INT32 v = mRandSeed1;
00041     mRandSeed1 = ((v >> 13) + (v << (32 - 13)));  
00042     v = mRandSeed2 ^ 0x51549515;
00043     mRandSeed2 = mRandSeed1 ^ mRandSeed2;
00044     mRandSeed1 = v;
00045     return mRandSeed1;
00046 }
00047 
00048 
00049 INT32 XFuParticleSystem::PSRandInPlace(INT32 aSeed)
00050 {
00051     INT32 randseed1, randseed2;
00052     INT32 s = aSeed & 31;
00053     INT32 t = aSeed ^ 0x14951C57;
00054     randseed2 = (t >> s) + (t << (32 - s));
00055     s = (aSeed >> 5) & 31;
00056     t = aSeed ^ 0x6C691B25;
00057     aSeed = (t >> s) + (t << (32 - s));  
00058     randseed1 = ((aSeed >> 13) + (aSeed << (32 - 13)));  
00059     aSeed = randseed2 ^ 0x51549515;
00060     randseed2 = randseed1 ^ randseed2;
00061     randseed1 = aSeed;
00062     return randseed1 & 0x7fff;
00063 }
00064 
00065 
00066 XFuParticleSystem::XFuParticleSystem()
00067 {
00068     mFrames = 0;
00069     mFrame = NULL;
00070     mParticle = NULL;
00071     mTexture = NULL;
00072     mCurrentTick = 0;
00073     mViewScale = 1;
00074     mSharedTextures = 0;
00075     PSSeed(0xf00ba517);
00076 }
00077 
00078 
00079 void XFuParticleSystem::restart() 
00080 {
00081     mStartTick = XFcCore::getTick(); // TODO: this should be replaced with a parameter
00082     mLastTick = 0;
00083     mActive = 0;
00084     mPeakActive = 0;
00085     mEmitQueue = 0;
00086     mEmitted = 0;
00087     INT32 i;
00088     for (i = 0; i < mMaxVisible; i++)
00089         mParticle[i].mAge = -1;
00090     for (i = 0; i < mPreTick; i++)
00091         tickOnce(REALi(1000) / mDesiredFPS);
00092 }
00093 
00094 
00095 void XFuParticleSystem::setMaxVisible(INT32 aValue) 
00096 {
00097     if (mParticle != NULL) 
00098         delete[] mParticle;
00099     mParticle = new struct Particle[aValue];
00100     mMaxVisible = aValue;
00101     restart();
00102 }
00103 
00104 
00105 XFuParticleSystem::~XFuParticleSystem()
00106 {
00107     if (mFrames > 0)
00108     {
00109         INT32 i;
00110         for (i = 0; i < mFrames; i++)
00111         {
00112             if (!mSharedTextures)
00113                 delete mFrame[i];
00114             delete[] mTexture[i]; 
00115         }
00116         delete[] mFrame;
00117         delete[] mTexture;
00118     }
00119     if (mParticle != NULL) 
00120         delete[] mParticle;
00121 }
00122 
00123 
00124 // TODO: get rid of fixed point dependency (at compile time, or always)
00125 XFcFixed XFuNoiseController::noise(INT32 aTick, XFuParticleSystem *ps)
00126 {    
00127     if (mType == 0) return 0; // no noise
00128     XFcFixed t;// = REAL(tick);  
00129     t.setValue(aTick << (XFCFIXED_SHIFT - 10)); 
00130   
00131     // If noise period is zero, consider it completely random:
00132     if (mPeriod == 0) 
00133     {
00134         XFcFixed r; 
00135         r.setValue(((ps->PSRand() & 8191) - 4096) << (XFCFIXED_SHIFT - 12));
00136         return r * mValue;
00137     }
00138 
00139     t = t / mPeriod;
00140     INT32 v;
00141 
00142     switch (mType) 
00143     {
00144     case 1: // sin
00145         return XFcMath::sinFast((t * PI) * 2) * mValue;
00146     case 2: // cos
00147         return XFcMath::cosFast((t * PI) * 2) * mValue;
00148     case 3: // triangle1
00149         v = ((((t.getValue() >> (XFCFIXED_SHIFT - 12)) & 4095) - 2048) << 2);
00150         if (v < 0) v = -v;
00151         v -= 4096;
00152         t.setValue(v);
00153         return t * mValue;
00154     case 4: // triangle2
00155         v = (((((t.getValue() >> (XFCFIXED_SHIFT - 12)) + 1024) & 4095) - 2048) << 2);
00156         if (v < 0) v = -v;
00157         v -= 4096;
00158         t.setValue(v);
00159         return t * mValue;
00160     case 5: // random
00161         {
00162             // please note that the PSRand() noise function has been 
00163             // tailored so that this would work: 
00164             int d = t.getValue() >> (XFCFIXED_SHIFT - 12);
00165             int s = d >> 12;
00166             d &= 4095;
00167             int id = 4096 - d;        
00168             int r1 = ((ps->PSRandInPlace(s)) * id) >> 14; // 16384    
00169             int r2 = ((ps->PSRandInPlace(s+1)) * d) >> 14;
00170             t.setValue((r1 + r2 - 4096) << (XFCFIXED_SHIFT - 12));    
00171             return t * mValue;
00172         }
00173     }
00174     return 0;
00175 }
00176 
00177 
00178 void XFuParticleSystem::render(XFcGL * aGL)
00179 {
00180     INT32 cullmode, alphablend, srcblend, tgtblend, shademode, perspcorr;
00181     // save current GL modes: (note: texture NOT saved)
00182     aGL->getStateI(XFCGLRS_CULLING, cullmode);
00183     aGL->getStateI(XFCGLRS_ALPHABLEND, alphablend);
00184     aGL->getStateI(XFCGLRS_SRCBLEND, srcblend);
00185     aGL->getStateI(XFCGLRS_TGTBLEND, tgtblend);
00186     aGL->getStateI(XFCGLRS_SHADING, shademode);
00187     aGL->getStateI(XFCGLRS_PERSPECTIVECORRECTION, perspcorr);
00188     // and then set some:
00189     XFcMatrix4 rot;    
00190     aGL->setStateI(XFCGLRS_CULLING, XFCGLCULL_NONE);    
00191     aGL->setStateI(XFCGLRS_ALPHABLEND, 1);
00192     aGL->setStateI(XFCGLRS_SHADING, XFCGLSHADE_MATTE);
00193     aGL->setStateI(XFCGLRS_PERSPECTIVECORRECTION, 0);
00194 
00195     switch (mAlphaMode)
00196     {
00197     case 0: //none:
00198         aGL->setStateI(XFCGLRS_SRCBLEND, XFCBLEND_ONE);
00199         aGL->setStateI(XFCGLRS_TGTBLEND, XFCBLEND_ZERO);
00200         aGL->setStateI(XFCGLRS_ALPHABLEND, 0);
00201         break;
00202     case 1: //add
00203         aGL->setStateI(XFCGLRS_SRCBLEND, XFCBLEND_ONE);
00204         aGL->setStateI(XFCGLRS_TGTBLEND, XFCBLEND_ONE);
00205         break;
00206     case 2: //alpha:
00207         aGL->setStateI(XFCGLRS_SRCBLEND, XFCBLEND_SRCALPHA);
00208         aGL->setStateI(XFCGLRS_TGTBLEND, XFCBLEND_INVSRCALPHA);
00209         break;
00210     case 3: //mul: Does not work (fillers not implemented)
00211         aGL->setStateI(XFCGLRS_SRCBLEND, XFCBLEND_ZERO);
00212         aGL->setStateI(XFCGLRS_TGTBLEND, XFCBLEND_SRCCOLOR);
00213         break;
00214     case 4: //invmul
00215         aGL->setStateI(XFCGLRS_SRCBLEND, XFCBLEND_ZERO);
00216         aGL->setStateI(XFCGLRS_TGTBLEND, XFCBLEND_INVSRCCOLOR);
00217         break;
00218     }
00219     
00220     if (mFrames == 0)
00221         aGL->setTexture(NULL);
00222 
00223     INT32 i;
00224     for (i = 0; i < mMaxVisible; i++) 
00225     {
00226         if (mParticle[i].mAge !=  - 1) 
00227         {
00228             XFcFixed deltaAge = mParticle[i].mAge / mParticle[i].mMaxAge;
00229             
00230             if (mFrames != 0)
00231             {
00232                 // find current animation frame and select the texture:
00233                 INT32 texture = deltaAge * mFrames + mFrames * mFrameVariation.noise(mCurrentTick, this);
00234                 if (texture < 0) texture = 0;
00235                 if (texture >= mFrames) texture = mFrames - 1;
00236                 aGL->setTexture(mFrame[texture]);
00237             }            
00238             
00239             XFcFixed size = mParticleSizeStart + deltaAge * (mParticleSizeEnd - mParticleSizeStart);
00240             size += mParticleSizeVariation.noise(mCurrentTick, this);
00241             size = size * mSizeScale * mViewScale;
00242 
00243             XFcFixed alpha = mAlphaStart + deltaAge * (mAlphaEnd - mAlphaStart);
00244             alpha += mAlphaVariation.noise(mCurrentTick, this) * 255;
00245             INT32 finalAlpha = alpha;
00246             if (finalAlpha > 255) finalAlpha = 255;
00247             if (finalAlpha < 0) finalAlpha = 0;
00248             finalAlpha <<= 24;
00249 
00250             XFcMath::matrixIdentity(rot);
00251             if (mParticle[i].mAngle != REALi(0))
00252             {
00253                 REAL cosVal = XFcMath::cosFast(mParticle[i].mAngle);
00254                 REAL sinVal = XFcMath::sinFast(mParticle[i].mAngle);
00255                 rot.m[0][0] = cosVal;
00256                 rot.m[0][1] = sinVal;
00257                 rot.m[1][0] = -sinVal;
00258                 rot.m[1][1] = cosVal;
00259             }
00260 
00261             // draw sprite: 
00262             aGL->drawSprite3dBillboard(mParticle[i].mX * mSizeScale, mParticle[i].mY * mSizeScale, mParticle[i].mZ * mSizeScale, size, size, 0, 0, 1, 1, &rot, 0xffffff | finalAlpha);
00263         }
00264     }
00265     // restore changed GL states:
00266     aGL->setStateI(XFCGLRS_CULLING,cullmode);
00267     aGL->setStateI(XFCGLRS_ALPHABLEND,alphablend);
00268     aGL->setStateI(XFCGLRS_SRCBLEND,srcblend);
00269     aGL->setStateI(XFCGLRS_TGTBLEND,tgtblend);
00270     aGL->setStateI(XFCGLRS_SHADING,shademode);
00271     aGL->setStateI(XFCGLRS_PERSPECTIVECORRECTION, perspcorr);
00272 }
00273 
00274 
00275 void XFuParticleSystem::newParticle(struct Particle &aParticle)
00276 {
00277     aParticle.mAge = 0;
00278     aParticle.mMaxAge = mMaxAge - ((int)((mAgeVariation.noise(mCurrentTick, this) + mAgeVariation.mValue) * REALi(mMaxAge)));
00279     if (aParticle.mMaxAge == 0)
00280         aParticle.mMaxAge = 1;
00281     aParticle.mX = aParticle.mY = aParticle.mZ = 0;
00282     if (mEmitterSize[0] != 0)
00283     {
00284         aParticle.mX = ((PSRand() - 16384) * mEmitterSize[0]) / REALi(16384);
00285     }
00286     if (mEmitterSize[1] != 0)
00287     {
00288         aParticle.mY = ((PSRand() - 16384) * mEmitterSize[1]) / REALi(16384);
00289     }
00290     if (mEmitterSize[2] != 0)
00291     {
00292         aParticle.mZ=((PSRand() - 16384) * mEmitterSize[2]) / REALi(16384);
00293     }
00294     aParticle.mUniqueSeed = (PSRand() & 0x7fff);
00295     aParticle.mXi = (mLaunchVelocity[0] + mLaunchVelocityVar[0].noise(mCurrentTick, this));
00296     aParticle.mYi = (mLaunchVelocity[1] + mLaunchVelocityVar[1].noise(mCurrentTick, this));
00297     aParticle.mZi = (mLaunchVelocity[2] + mLaunchVelocityVar[2].noise(mCurrentTick, this));
00298 
00299     aParticle.mAngle = mRotationNoise.noise(mCurrentTick, this) * PI;
00300     aParticle.mBaseRotation = mRotation;
00301 }
00302 
00303 void XFuParticleSystem::tickOnce(XFcFixed aTimeSlice)
00304 {    
00305     XFcFixed time = aTimeSlice / 100;
00306     mCurrentTick += aTimeSlice;
00307     mEmitQueue += XFcFixed(aTimeSlice * mLaunchRate) / 1000;
00308     INT32 newones = (INT32)(mEmitQueue - mEmitted);
00309     if (newones > mMaxVisible * 2) mEmitQueue -= (newones - mMaxVisible * 2);
00310 
00311     INT32 i;
00312     for (i = 0; i < mMaxVisible; i++) 
00313     {
00314         if (mParticle[i].mAge != -1) 
00315         {
00316             mParticle[i].mAge += aTimeSlice;
00317             if (mParticle[i].mAge >= mParticle[i].mMaxAge) 
00318             {
00319                 mParticle[i].mAge = -1;
00320                 mActive--;
00321             }
00322         }
00323         if (mParticle[i].mAge == -1 && newones > 0 && (mMaxTotal == 0 || mMaxTotal > mEmitted)) 
00324         {
00325             newParticle(mParticle[i]);
00326             mEmitted++;
00327             newones--;
00328             mActive++;
00329             if (mPeakActive < mActive) mPeakActive = mActive;
00330         }
00331         if (mParticle[i].mAge !=  - 1) 
00332         {
00333             XFcFixed difx = mWeight[0] + mNoise[0].noise(mCurrentTick + mParticle[i].mUniqueSeed, this) + -mParticle[i].mXi * (1 - mDamping[0]);
00334             XFcFixed dify = mWeight[1] + mNoise[1].noise(mCurrentTick + mParticle[i].mUniqueSeed, this) + -mParticle[i].mYi * (1 - mDamping[1]);
00335             XFcFixed difz = mWeight[2] + mNoise[2].noise(mCurrentTick + mParticle[i].mUniqueSeed, this) + -mParticle[i].mZi * (1 - mDamping[2]);
00336 
00337             mParticle[i].mX += mParticle[i].mXi * time + (difx / 2) * time * time;
00338             mParticle[i].mY += mParticle[i].mYi * time + (dify / 2) * time * time;
00339             mParticle[i].mZ += mParticle[i].mZi * time + (difz / 2) * time * time;
00340         
00341             mParticle[i].mXi += difx * time;
00342             mParticle[i].mYi += dify * time;
00343             mParticle[i].mZi += difz * time;                            
00344 
00345             if (mAABB[0]!=0 && XFcMath::abs(mParticle[i].mX) > mAABB[0]) 
00346             {
00347                 if ((mParticle[i].mX < 0 && mFlags & XFUPSF_COLLIDER_XMIN) || (mParticle[i].mX > 0 && mFlags & XFUPSF_COLLIDER_XMAX))
00348                 {
00349                     mParticle[i].mXi = -mParticle[i].mXi;
00350                     if (mParticle[i].mX < 0)
00351                         mParticle[i].mX = -mAABB[0];
00352                     else
00353                         mParticle[i].mX = mAABB[0];
00354                 
00355                 } 
00356                 else
00357                 {
00358                     mParticle[i].mAge = -1;
00359                     mActive--;
00360                 }
00361             }
00362             if (mAABB[1] != 0 && XFcMath::abs(mParticle[i].mY) > mAABB[1]) 
00363             {
00364                 if ((mParticle[i].mY < 0 && mFlags & XFUPSF_COLLIDER_YMIN) || (mParticle[i].mY > 0 && mFlags & XFUPSF_COLLIDER_YMAX))
00365                 {
00366                     mParticle[i].mYi = -mParticle[i].mYi;
00367                     if (mParticle[i].mY < 0)
00368                         mParticle[i].mY = -mAABB[1];
00369                     else
00370                         mParticle[i].mY = mAABB[1];
00371                 
00372                 } 
00373                 else
00374                 {
00375                     mParticle[i].mAge = -1;
00376                     mActive--;
00377                 }
00378             }
00379             if (mAABB[2] != 0 && XFcMath::abs(mParticle[i].mZ) > mAABB[2]) 
00380             {
00381                 if ((mParticle[i].mZ < 0 && mFlags & XFUPSF_COLLIDER_ZMIN) || (mParticle[i].mZ > 0 && mFlags & XFUPSF_COLLIDER_ZMAX))
00382                 {
00383                     mParticle[i].mZi = -mParticle[i].mZi;
00384                     if (mParticle[i].mZ < 0)
00385                         mParticle[i].mZ = -mAABB[2];
00386                     else
00387                         mParticle[i].mZ = mAABB[2];
00388                 
00389                 } 
00390                 else
00391                 {
00392                     mParticle[i].mAge = -1;
00393                     mActive--;
00394                 }
00395             }
00396             mParticle[i].mAngle += time * (mParticle[i].mBaseRotation + mRotationVariation.noise(mCurrentTick+mParticle[i].mUniqueSeed, this));
00397         }
00398     }
00399 }
00400 
00401 
00402 
00403 void XFuParticleSystem::tick(XFcFixed aTime)
00404 {    
00405     XFcFixed currenttick = aTime;    
00406 
00407     XFcFixed deltatick = currenttick - mLastTick;
00408 
00409     if (deltatick > 500 || deltatick < 0) 
00410     {
00411         // if over 500ms, (2 fps), assume we have slept for a while and don't even try to keep up
00412         // (these particle systems tend to blow up under 4fps in any case)
00413         deltatick = 0;
00414         mLastTick = currenttick;
00415     } 
00416 
00417     deltatick = mTimeScale * deltatick;
00418 
00419     XFcFixed frametime = deltatick;
00420 
00421     if (mDesiredFPS != 0) 
00422         frametime = (REALi(1000) / mDesiredFPS);
00423   
00424     if (mDesiredFPS != 0 && deltatick < frametime) return;  
00425 
00426     // accuracy problem here - round-offs of last tick are ignored
00427     mLastTick = currenttick;
00428 
00429     INT32 loops = 1;
00430 
00431     if (mFlags & XFUPSF_FORCEITERATIONS) 
00432     {
00433         loops = (INT32)(deltatick / frametime);
00434         deltatick = frametime;
00435         if (loops < 0) loops = 1;
00436     }
00437  
00438 
00439     for (; loops; --loops) 
00440     {
00441         tickOnce(deltatick);
00442     }
00443 }
00444 
00445 
00446 void XFuNoiseController::write(XFcFile * aFile)
00447 {
00448     aFile->writeINT32(mType);
00449     aFile->writeFLOAT32(mPeriod);
00450     aFile->writeFLOAT32(mValue);
00451 }
00452 
00453 void XFuNoiseController::read(XFcFile * aFile)
00454 {
00455     mType = aFile->readINT32();
00456     mPeriod = aFile->readFLOAT32();
00457     mValue = aFile->readFLOAT32();
00458 }
00459 
00460 
00461 void XFuParticleSystem::save(const CHAR *fname)
00462 {
00463     XFcFile * f;
00464     f = XFcFile::open(fname,"wb");
00465     INT32 tag = PS_VERSIONTAG; // 'PR__' where __ is 00 03
00466     f->writeINT32(tag);
00467     f->writeINT32(mFlags);
00468     f->writeFLOAT32(mLaunchVelocity[0]);
00469     f->writeFLOAT32(mLaunchVelocity[1]);
00470     f->writeFLOAT32(mLaunchVelocity[2]);
00471     mLaunchVelocityVar[0].write(f);
00472     mLaunchVelocityVar[1].write(f);
00473     mLaunchVelocityVar[2].write(f);
00474     f->writeFLOAT32(mDamping[0]);
00475     f->writeFLOAT32(mDamping[1]);
00476     f->writeFLOAT32(mDamping[2]);
00477     f->writeFLOAT32(mWeight[0]);
00478     f->writeFLOAT32(mWeight[1]);
00479     f->writeFLOAT32(mWeight[2]);
00480     mNoise[0].write(f);
00481     mNoise[1].write(f);
00482     mNoise[2].write(f);
00483     f->writeFLOAT32(mLaunchRate);
00484     f->writeINT32(mMaxAge);
00485     mAgeVariation.write(f);
00486     f->writeINT32(mMaxTotal);
00487     f->writeINT32(mMaxVisible);
00488     f->writeFLOAT32(mSizeScale);
00489     f->writeFLOAT32(mTimeScale);
00490     f->writeFLOAT32(mDesiredFPS);
00491     f->writeINT32(mAlphaMode);
00492     f->writeFLOAT32(mAlphaStart);
00493     f->writeFLOAT32(mAlphaEnd);
00494     mAlphaVariation.write(f);
00495     f->writeFLOAT32(mParticleSizeStart);
00496     f->writeFLOAT32(mParticleSizeEnd);
00497     mParticleSizeVariation.write(f);
00498     f->writeFLOAT32(mRotation);
00499     mRotationVariation.write(f);
00500     mRotationNoise.write(f);
00501     mFrameVariation.write(f);
00502     f->writeFLOAT32(mEmitterSize[0]);
00503     f->writeFLOAT32(mEmitterSize[1]);
00504     f->writeFLOAT32(mEmitterSize[2]);
00505     f->writeFLOAT32(mAABB[0]);
00506     f->writeFLOAT32(mAABB[1]);
00507     f->writeFLOAT32(mAABB[2]);
00508     f->writeINT32(mPreTick);
00509 
00510     // filenames are encoded as thus: "filename1|filename2|filename3||" <- two |:s end the string
00511 
00512     INT32 i;
00513     for (i = 0; i < mFrames; i++)
00514     {
00515         CHAR * t = mTexture[i];
00516         while (*t != 0)
00517         {
00518             f->putChar(*t);
00519             t++;
00520         }
00521         f->putChar('|');
00522     }
00523     f->putChar('|');
00524     f->putChar('|');
00525 
00526     f->close();
00527 }
00528 
00529 
00530 
00531 void XFuParticleSystem::load(const char *fname)
00532 {
00533     XFcFile *f = XFcFile::open(fname, "rb");
00534     load(f);
00535     f->close();
00536 }
00537 
00538 void XFuParticleSystem::load(XFcFile *f)
00539 {
00540     if (f == NULL) return;
00541     // load ps3
00542     int tag = f->readINT32();
00543     if (tag != PS_VERSIONTAG)
00544     {
00545         // different version
00546     }
00547     mFlags = f->readINT32();
00548     mLaunchVelocity[0] = f->readFLOAT32();
00549     mLaunchVelocity[1] = f->readFLOAT32();
00550     mLaunchVelocity[2] = f->readFLOAT32();
00551     mLaunchVelocityVar[0].read(f);
00552     mLaunchVelocityVar[1].read(f);
00553     mLaunchVelocityVar[2].read(f);
00554     mDamping[0] = f->readFLOAT32();
00555     mDamping[1] = f->readFLOAT32();
00556     mDamping[2] = f->readFLOAT32();
00557     mWeight[0] = f->readFLOAT32();
00558     mWeight[1] = f->readFLOAT32();
00559     mWeight[2] = f->readFLOAT32();
00560     mNoise[0].read(f);
00561     mNoise[1].read(f);
00562     mNoise[2].read(f);
00563     mLaunchRate = f->readFLOAT32();
00564     mMaxAge = f->readINT32();
00565     mAgeVariation.read(f);
00566     mMaxTotal = f->readINT32();
00567     mMaxVisible = f->readINT32();
00568     mSizeScale = f->readFLOAT32();
00569     mTimeScale = f->readFLOAT32();
00570     mDesiredFPS = f->readFLOAT32();
00571     mAlphaMode = f->readINT32();
00572     mAlphaStart = f->readFLOAT32();
00573     mAlphaEnd = f->readFLOAT32();
00574     mAlphaVariation.read(f);
00575     mParticleSizeStart = f->readFLOAT32();
00576     mParticleSizeEnd = f->readFLOAT32();
00577     mParticleSizeVariation.read(f);
00578     mRotation = f->readFLOAT32();
00579     mRotationVariation.read(f);
00580     mRotationNoise.read(f);
00581     mFrameVariation.read(f);
00582     mEmitterSize[0] = f->readFLOAT32();
00583     mEmitterSize[1] = f->readFLOAT32();
00584     mEmitterSize[2] = f->readFLOAT32();
00585     mAABB[0] = f->readFLOAT32();
00586     mAABB[1] = f->readFLOAT32();
00587     mAABB[2] = f->readFLOAT32();
00588     mPreTick = f->readINT32();
00589 
00590     if (mFrame != NULL)
00591     {
00592         INT32 i;
00593         for (i = 0; i < mFrames; i++)
00594             delete mFrame[i];
00595         delete[] mFrame;
00596     }
00597     mFrames = 0;  
00598     mFrame = NULL;
00599     CHAR ** temp;
00600     CHAR * tempstr;
00601     temp = new CHAR*[256];
00602     tempstr = new CHAR[256];
00603     INT32 inchar = f->getChar();
00604     INT32 idx=0;
00605     while (inchar != EOF)
00606     {
00607         if (inchar == '|' && idx == 0)
00608         {
00609             inchar = EOF;
00610         }
00611         else
00612         {
00613             if (inchar == '|')
00614             {
00615                 tempstr[idx] = 0;
00616                 temp[mFrames] = XFcStringToolkit::copy(tempstr);
00617                 idx = 0;
00618                 mFrames++;
00619             }
00620             else
00621             {
00622                 tempstr[idx] = (CHAR)inchar;
00623                 idx++;
00624             }
00625             inchar = f->getChar();
00626         }
00627     }
00628     delete[] tempstr;   
00629 
00630     if (mFrames > 0)
00631     {
00632         mTexture = new CHAR*[mFrames];
00633         INT i;
00634         for (i = 0; i < mFrames; i++)
00635             mTexture[i] = temp[i];
00636     }
00637     else
00638     {
00639         mTexture = NULL;
00640     }
00641     delete[] temp;
00642 
00643     if (mSizeScale == 0) mSizeScale = 1;
00644     setMaxVisible(mMaxVisible); // calls restart()
00645 }
00646 
00647 
00648 void XFuParticleSystem::loadTextures(const CHAR *aFilenamePrefix)
00649 {
00650     mFrame = new XFcGLTexture *[mFrames];
00651     INT32 i;
00652     for (i = 0; i < mFrames; i++)
00653     {
00654         mFrame[i] = NULL;
00655     }
00656 
00657     for (i = 0; i < mFrames; i++)
00658     {
00659         if (aFilenamePrefix == NULL)
00660             mFrame[i] = XFcGLTextureFromFile::create(mTexture[i]);
00661         else
00662         {
00663             CHAR *filename = XFcStringToolkit::concat(aFilenamePrefix, mTexture[i]);
00664             mFrame[i] = XFcGLTextureFromFile::create(filename);
00665             delete[] filename;
00666         }
00667     }
00668 }
00669 

   
X-Forge Documentation
Confidential
Copyright © 2002-2003 Fathammer
   
Documentation generated
with doxygen
by Dimitri van Heesch