void processParticles() { static int pindex = 0 ; ParticleIterator pit = particleSystem->_getIterator() ; while(!pit.end()) { Particle *particle = pit.getNext(); Vector3 ppos = particle->position; if (ppos.y<=0 && particle->timeToLive>0) { // hits the water! // delete particle particle->timeToLive = 0.0f; // push the water float x = ppos.x / PLANE_SIZE * COMPLEXITY ; float y = ppos.z / PLANE_SIZE * COMPLEXITY ; float h = rand() % RAIN_HEIGHT_RANDOM + RAIN_HEIGHT_CONSTANT ; if (x<1) x=1 ; if (x>COMPLEXITY-1) x=COMPLEXITY-1; if (y<1) y=1 ; if (y>COMPLEXITY-1) y=COMPLEXITY-1; waterMesh->push(x,y,-h) ; WaterCircle *circle = new WaterCircle( "Circle#"+StringConverter::toString(pindex++), x, y); circles.push_back(circle); } } }
//----------------------------------------------------------------------- void DeflectorPlaneAffector::_affectParticles(ParticleSystem* pSystem, Real timeElapsed) { // precalculate distance of plane from origin Real planeDistance = - mPlaneNormal.dotProduct(mPlanePoint) / Math::Sqrt(mPlaneNormal.dotProduct(mPlaneNormal)); Vector3 directionPart; ParticleIterator pi = pSystem->_getIterator(); while (!pi.end()) { Particle *p = pi.getNext(); Vector3 direction(p->mDirection * timeElapsed); if (mPlaneNormal.dotProduct(p->mPosition + direction) + planeDistance <= 0.0) { Real a = mPlaneNormal.dotProduct(p->mPosition) + planeDistance; if (a > 0.0) { // for intersection point directionPart = direction * (- a / direction.dotProduct( mPlaneNormal )); // set new position p->mPosition = (p->mPosition + ( directionPart )) + (((directionPart) - direction) * mBounce); // reflect direction vector p->mDirection = (p->mDirection - (2.0f * p->mDirection.dotProduct( mPlaneNormal ) * mPlaneNormal)) * mBounce; } } } }
void LinearForceAffector::_affectParticles(ParticleSystem* pSystem, Real timeElapsed) { ParticleIterator pi = pSystem->_getIterator(); Particle *p; Vector3 scaledVector = Vector3::ZERO; // Precalc scaled force for optimisation if (mForceApplication == FA_ADD) { // Scale force by time scaledVector = mForceVector * timeElapsed; } while (!pi.end()) { p = pi.getNext(); if (mForceApplication == FA_ADD) { p->direction += scaledVector; } else // FA_AVERAGE { p->direction = (p->direction + mForceVector) / 2; } } }
//----------------------------------------------------------------------- void ScaleAffector::_affectParticles(ParticleSystem* pSystem, Real timeElapsed) { ParticleIterator pi = pSystem->_getIterator(); Particle *p; Real ds; // Scale adjustments by time ds = mScaleAdj * timeElapsed; Real NewWide, NewHigh; while (!pi.end()) { p = pi.getNext(); if( p->hasOwnDimensions() == false ) { NewWide = pSystem->getDefaultWidth() + ds; NewHigh = pSystem->getDefaultHeight() + ds; } else { NewWide = p->getOwnWidth() + ds; NewHigh = p->getOwnHeight() + ds; } p->setDimensions( NewWide, NewHigh ); } }
//----------------------------------------------------------------------- void DirectionRandomiserAffector::_affectParticles(ParticleSystem* pSystem, Real timeElapsed) { ParticleIterator pi = pSystem->_getIterator(); Particle *p; Real length = 0; while (!pi.end()) { p = pi.getNext(); if (mScope > Math::UnitRandom()) { if (!p->direction.isZeroLength()) { if (mKeepVelocity) { length = p->direction.length(); } p->direction += Vector3(Math::RangeRandom(-mRandomness, mRandomness) * timeElapsed, Math::RangeRandom(-mRandomness, mRandomness) * timeElapsed, Math::RangeRandom(-mRandomness, mRandomness) * timeElapsed); if (mKeepVelocity) { p->direction *= length / p->direction.length(); } } } } }
//----------------------------------------------------------------------- void MeshRotationAffector::_affectParticles(ParticleSystem* pSystem, Real timeElapsed) { ParticleIterator pi = pSystem->_getIterator(); Particle *p; Real ds; // Rotation adjustments by time ds = timeElapsed; while (!pi.end()) { p = pi.getNext(); MeshParticleVisualData *data = static_cast<MeshParticleVisualData *>(p->getVisualData()); data->mYawRotation = data->mYawRotation + ds * data->mYawRotationSpeed; data->mPitchRotation = data->mPitchRotation + ds * data->mPitchRotationSpeed; data->mRollRotation = data->mRollRotation + ds * data->mRollRotationSpeed; if ( data->mYawRotation != Radian(0) || data->mPitchRotation != Radian(0) || data->mRollRotation != Radian(0) ) pSystem->_notifyParticleRotated(); } }
//----------------------------------------------------------------------- void ColourImageAffector::_affectParticles(ParticleSystem* pSystem, Real timeElapsed) { Particle* p; ParticleIterator pi = pSystem->_getIterator(); if (!mColourImageLoaded) { _loadImage(); } int width = (int)mColourImage.getWidth() - 1; while (!pi.end()) { p = pi.getNext(); const Real life_time = p->totalTimeToLive; Real particle_time = 1.0f - (p->timeToLive / life_time); if (particle_time > 1.0f) particle_time = 1.0f; if (particle_time < 0.0f) particle_time = 0.0f; const Real float_index = particle_time * width; const int index = (int)float_index; if(index < 0) { p->colour = mColourImage.getColourAt(0, 0, 0); } else if(index >= width) { p->colour = mColourImage.getColourAt(width, 0, 0); } else { // Linear interpolation const Real fract = float_index - (Real)index; const Real to_colour = fract; const Real from_colour = 1.0f - to_colour; ColourValue from=mColourImage.getColourAt(index, 0, 0), to=mColourImage.getColourAt(index+1, 0, 0); p->colour.r = from.r*from_colour + to.r*to_colour; p->colour.g = from.g*from_colour + to.g*to_colour; p->colour.b = from.b*from_colour + to.b*to_colour; p->colour.a = from.a*from_colour + to.a*to_colour; } } }
void RotationAffector::_affectParticles(ParticleSystem* pSystem, Real timeElapsed) { ParticleIterator pi = pSystem->_getIterator(); Particle *p; Real ds; // Rotation adjustments by time ds = timeElapsed; Radian NewRotation; while (!pi.end()) { p = pi.getNext(); NewRotation = p->rotation + (ds * p->rotationSpeed); p->setRotation( NewRotation ); } }
int main(int argc, char **argv) { NaiveParticlePool<struct simpleParticle>* pool = new NaiveParticlePool<struct simpleParticle>(NUM_PARTICLES); SimpleParticleInitializer* init = new SimpleParticleInitializer(); SimpleParticleUpdater* update = new SimpleParticleUpdater(100); Curve<long,long>* c = new ConstantCurve(400); ParticleSystem<struct simpleParticle>* system = new ParticleSystem<struct simpleParticle>(pool,init,update,c,false); testParticleSystem(system,&valFunc,c,pool,NUM_PARTICLES,30); printf("Hello world!\n"); printf("Managed to create curve on stack.\n"); printf("Curve gives value %ld for input 45.\n", c->getValue(45)); //struct simpleParticle** readParticles = (struct simpleParticle**) calloc(NUM_PARTICLES,sizeof(struct simpleParticle*)); size_t currentPos = 0; for(int i = 0; i < ITER; i++) { currentPos = 0; printf("Started step %d of %d for particle system.\n", i + 1,ITER); system->step(); for(int i = 0; i < NUM_THREADS; i++) startWorkerThread(system); ParticleIterator<struct simpleParticle>* living = system->getLivingParticles(); struct simpleParticle* part; while(living->hasNext()) { part = living->next(); //printf("Particle value: %d\n", part->value); //if(part->value != i + 1) printf("Read non-updated particle at round %d. %d\n", i + 1, part->value); //readParticles[currentPos] = part; currentPos++; living->done(part); } delete living; printf("%ld Particles this iteration.\n", currentPos); } //free(readParticles); return 0; }
//----------------------------------------------------------------------- void ColourFaderAffector2::_affectParticles(ParticleSystem* pSystem, Real timeElapsed) { ParticleIterator pi = pSystem->_getIterator(); Particle *p; float dr1, dg1, db1, da1; float dr2, dg2, db2, da2; // Scale adjustments by time dr1 = mRedAdj1 * timeElapsed; dg1 = mGreenAdj1 * timeElapsed; db1 = mBlueAdj1 * timeElapsed; da1 = mAlphaAdj1 * timeElapsed; // Scale adjustments by time dr2 = mRedAdj2 * timeElapsed; dg2 = mGreenAdj2 * timeElapsed; db2 = mBlueAdj2 * timeElapsed; da2 = mAlphaAdj2 * timeElapsed; while (!pi.end()) { p = pi.getNext(); if( p->timeToLive > StateChangeVal ) { applyAdjustWithClamp(&p->colour.r, dr1); applyAdjustWithClamp(&p->colour.g, dg1); applyAdjustWithClamp(&p->colour.b, db1); applyAdjustWithClamp(&p->colour.a, da1); } else { applyAdjustWithClamp(&p->colour.r, dr2); applyAdjustWithClamp(&p->colour.g, dg2); applyAdjustWithClamp(&p->colour.b, db2); applyAdjustWithClamp(&p->colour.a, da2); } } }
//----------------------------------------------------------------------- void MeshAnimationAffector::_affectParticles(ParticleSystem* pSystem, Real timeElapsed) { ParticleIterator pi = pSystem->_getIterator(); Particle *p; while (!pi.end()) { p = pi.getNext(); MeshParticleVisualData *data = static_cast<MeshParticleVisualData *>(p->getVisualData()); data->mAnimationName = mAnimationName; data->mDeltaTime = timeElapsed; data->mAnimationLoop = mAnimationLoop; data->mAnimationSpeedFactor = mAnimationSpeedFactor; data->mAnimationUpdated = true; } }
//----------------------------------------------------------------------- void ColourFaderAffector::_affectParticles(ParticleSystem* pSystem, Real timeElapsed) { ParticleIterator pi = pSystem->_getIterator(); Particle *p; float dr, dg, db, da; // Scale adjustments by time dr = mRedAdj * timeElapsed; dg = mGreenAdj * timeElapsed; db = mBlueAdj * timeElapsed; da = mAlphaAdj * timeElapsed; while (!pi.end()) { p = pi.getNext(); applyAdjustWithClamp(&p->colour.r, dr); applyAdjustWithClamp(&p->colour.g, dg); applyAdjustWithClamp(&p->colour.b, db); applyAdjustWithClamp(&p->colour.a, da); } }
//----------------------------------------------------------------------- void ColourInterpolatorAffector::_affectParticles(ParticleSystem* pSystem, Real timeElapsed) { Particle* p; ParticleIterator pi = pSystem->_getIterator(); while (!pi.end()) { p = pi.getNext(); const Real life_time = p->totalTimeToLive; Real particle_time = 1.0f - (p->timeToLive / life_time); if (particle_time <= mTimeAdj[0]) { p->colour = mColourAdj[0]; } else if (particle_time >= mTimeAdj[MAX_STAGES - 1]) { p->colour = mColourAdj[MAX_STAGES-1]; } else { for (int i=0;i<MAX_STAGES-1;i++) { if (particle_time >= mTimeAdj[i] && particle_time < mTimeAdj[i + 1]) { particle_time -= mTimeAdj[i]; particle_time /= (mTimeAdj[i+1]-mTimeAdj[i]); p->colour.r = ((mColourAdj[i+1].r * particle_time) + (mColourAdj[i].r * (1.0f - particle_time))); p->colour.g = ((mColourAdj[i+1].g * particle_time) + (mColourAdj[i].g * (1.0f - particle_time))); p->colour.b = ((mColourAdj[i+1].b * particle_time) + (mColourAdj[i].b * (1.0f - particle_time))); p->colour.a = ((mColourAdj[i+1].a * particle_time) + (mColourAdj[i].a * (1.0f - particle_time))); break; } } } } }
//----------------------------------------------------------------------- void FireExtinguisherAffector::_affectParticles(ParticleSystem* pSystem, Real timeElapsed) { ExtinguishableFireAffectorFactory::affectorIterator affIt = mEfaf->getAffectorIterator(); ExtinguishableFireAffector* fire; while(affIt.hasMoreElements()) { fire = (ExtinguishableFireAffector*)affIt.getNext(); if (fire->isTemplate()) continue; Real squaredRadius = Math::Pow(fire->getRadius(), 2); Vector3 middlePoint = fire->getAbsoluteMiddlePoint(); ParticleIterator pi = pSystem->_getIterator(); Particle *p; int fireHits = 0; while (!pi.end()) { p = pi.getNext(); if ( middlePoint.squaredDistance(p->position) < squaredRadius ) { // This particle is inside the fire, dispose of it in the next update p->timeToLive = 0; ++fireHits; } } if (fireHits>0) { Real intensity = fire->reduceIntensity(fireHits*mEffectiveness); if (intensity<0) delete fire->getParticleSystem(); } } }
//----------------------------------------------------------------------- void RevolutionAffector::_affectParticles(ParticleSystem* pSystem, Real timeElapsed) { // 因为timeElapsed有可能有0,加上判断,避免除0错 if (false == Ogre::Math::RealEqual(timeElapsed, 0.0f)) { ParticleIterator pi = pSystem->_getIterator(); Particle *p; Quaternion q( Radian(Degree(mRotationSpeed*timeElapsed).valueRadians()), mRotateAxis); Matrix3 mat(Matrix3::IDENTITY); q.ToRotationMatrix(mat); Ogre::Vector3 randomPoint; randomPoint.x = Math::RangeRandom(mCenterOffsetMin.x, mCenterOffsetMax.x); randomPoint.y = Math::RangeRandom(mCenterOffsetMin.y, mCenterOffsetMax.y); randomPoint.z = Math::RangeRandom(mCenterOffsetMin.z, mCenterOffsetMax.z); Vector3 particleSystemPos(Vector3::ZERO); bool localSpace = pSystem->getKeepParticlesInLocalSpace(); particleSystemPos = pSystem->getParentSceneNode()->_getDerivedPosition(); Ogre::Vector3 destPoint = particleSystemPos + randomPoint; Vector3 particlePos(Vector3::ZERO); Vector3 RadiusIncrementDir(Vector3::ZERO); bool needFmod = mRepeatTimes != 1.0f; while (!pi.end()) { p = pi.getNext(); particlePos = p->position; /** 如果是localSpace,那么p->position得到的是粒子的相对位置,所以要加上 粒子系统的位置particleSystemPos,得到绝对位置,再减去destPoint才能得到 正确的向量 particlePos + particleSystemPos - destPoint = particlePos + particleSystemPos - particleSystemPos - randomPoint = particlePos - randomPoint */ if (localSpace) { RadiusIncrementDir = particlePos - randomPoint; RadiusIncrementDir.normalise(); particlePos = mat *( particlePos - randomPoint ) + randomPoint - particlePos; } else { RadiusIncrementDir = particlePos - destPoint; RadiusIncrementDir.normalise(); particlePos = mat *( particlePos - destPoint ) + destPoint - particlePos; } p->direction = particlePos / timeElapsed; if (mUseRadiusIncrementScale) { const Real life_time = p->totalTimeToLive; Real particle_time = 1.0f - (p->timeToLive / life_time); // wrap the particle time Real repeatedParticleTime = needFmod ? fmod( particle_time * mRepeatTimes, 1.0f ) : particle_time; if (repeatedParticleTime <= mTimeAdj[0]) { p->direction += RadiusIncrementDir * mRadiusIncrementAdj[0]; } else if (repeatedParticleTime >= mTimeAdj[MAX_STAGES - 1]) { p->direction += RadiusIncrementDir * mRadiusIncrementAdj[MAX_STAGES - 1]; } else { for (int i=0;i<MAX_STAGES-1;i++) { if (repeatedParticleTime >= mTimeAdj[i] && repeatedParticleTime < mTimeAdj[i + 1]) { repeatedParticleTime -= mTimeAdj[i]; repeatedParticleTime /= (mTimeAdj[i+1]-mTimeAdj[i]); p->direction += RadiusIncrementDir * ( (mRadiusIncrementAdj[i+1] * repeatedParticleTime) + (mRadiusIncrementAdj[i] * (1.0f - repeatedParticleTime)) ); break; } } } } else { p->direction += RadiusIncrementDir*mRadiusIncrement; } // case RotationType::OUTER_NORMAL: //// p->direction.x += pos.x; // // p->direction.z += pos.z; // p->direction = pos; // break; // case RotationType::OUTER_FAST: //// p->direction.x += (p->direction.x + pos.x) /2; // // p->direction.z += (p->direction.z + pos.z) /2; // p->direction += (p->direction + pos) /2; // break; } } }