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