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

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