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
![]() | ||||
![]() |
Confidential Copyright © 2002-2003 Fathammer | with doxygen by Dimitri van Heesch |