void SparkDrawer::draw(const ParticleSystem& psys) const { buffer->clear(); buffer->set_pos(Vector2f(psys.get_x_pos(), psys.get_y_pos())); if (width == 1.0f) { buffer->set_mode(GL_LINES); buffer->set_blend_func(GL_SRC_ALPHA, GL_ONE); for(ParticleSystem::const_iterator i = psys.begin(); i != psys.end(); ++i) { buffer->color(Color(color.r, color.g, color.b, color.a - (color.a * psys.get_progress(i->t)))); buffer->vertex(i->x + i->v_x/10.0f, i->y + i->v_y/10.0f); buffer->color(Color(0, 0, 0, 0)); buffer->vertex(i->x, i->y); } } else { buffer->set_mode(GL_QUADS); buffer->set_blend_func(GL_SRC_ALPHA, GL_ONE); for(ParticleSystem::const_iterator i = psys.begin(); i != psys.end(); ++i) { const float len = sqrtf(i->v_x * i->v_x + i->v_y * i->v_y); const float o_x = i->v_y/len * width; const float o_y = i->v_x/len * width; const float x1 = i->x; const float y1 = i->y; const float x2 = i->x + i->v_x/10.0f; const float y2 = i->y + i->v_y/10.0f; buffer->color(Color(0, 0, 0, 0)); buffer->vertex(x1 + o_x, y1 - o_y); buffer->color(Color(0, 0, 0, 0)); buffer->vertex(x1 - o_x, y1 + o_y); buffer->color(Color(color.r, color.g, color.b, color.a - (color.a * psys.get_progress(i->t)))); buffer->vertex(x2 - o_x, y2 + o_y); buffer->color(Color(color.r, color.g, color.b, color.a - (color.a * psys.get_progress(i->t)))); buffer->vertex(x2 + o_x, y2 - o_y); } } buffer->render(~0u); }
void MagnetPSA::execute( ParticleSystem &particleSystem, float dTime ) { BW_GUARD_PROFILER( MagnetPSA_execute ); // Do nothing if the dTime passed was zero or if the particle system // is not quite old enough to be active. if ( ( age_ < delay() ) || ( dTime <= 0.0f ) ) { age_ += dTime; return; } // If there is no source matrix provider, use the origin of the // particle system itself. Vector3 origin; if ( source_ ) { Matrix m; source_->matrix(m); origin = m.applyToOrigin(); } else { if ( !particleSystem.pRenderer() || !particleSystem.pRenderer()->local() ) { origin = particleSystem.worldTransform().applyToOrigin(); } else { origin.set(0,0,0); } } Particles::iterator current = particleSystem.begin(); Particles::iterator endOfParticles = particleSystem.end(); while ( current != endOfParticles ) { Particle &particle = *current++; if (particle.isAlive()) { // Here we go: Apply acceleration to velocity based on magnet position. Vector3 dv (origin-particle.position()); float separation = max(dv.length(), minDist_); dv /= separation; float factor = (dTime * strength_) / separation; Vector3 velocity; particle.getVelocity( velocity ); particle.setVelocity( velocity + (dv * factor) ); } } }
/** * This method executes the action for the given frame of time. The dTime * parameter is the time elapsed since the last call. * * @param particleSystem The particle system on which to operate. * @param dTime Elapsed time in seconds. */ void ScalerPSA::execute( ParticleSystem &particleSystem, float dTime ) { BW_GUARD_PROFILER( ScalerPSA_execute ); // Do nothing if the dTime passed was zero or if the particle system // is not quite old enough to be active. if ( ( age_ < delay() ) || ( dTime <= 0.0f ) ) { age_ += dTime; return; } Particles::iterator current = particleSystem.begin(); Particles::iterator endOfParticles = particleSystem.end(); while ( current != endOfParticles ) { Particle &particle = *current; if (particle.isAlive()) { float size = particle.size(); if ( size > size_ ) { size -= rate_ * dTime; if ( size < size_ ) { size = size_; } } else if ( size < size_ ) { size += rate_ * dTime; if ( size > size_ ) { size = size_; } } particle.size( size ); } ++current; } }
/** * This method executes the action for the given frame of time. The dTime * parameter is the time elapsed since the last call. * * @param particleSystem The particle system on which to operate. * @param dTime Elapsed time in seconds. */ void CollidePSA::execute( ParticleSystem &particleSystem, float dTime ) { BW_GUARD; SourcePSA* pSource = static_cast<SourcePSA*>( &*particleSystem.pAction( PSA_SOURCE_TYPE_ID ) ); if ( !pSource ) return; RompColliderPtr pGS = pSource->groundSpecifier(); if ( !pGS ) return; uint64 tend = timestamp() + stampsPerSecond() / 2000; bool soundHit = false; float maxVelocity = 0; Vector3 soundPos; uint materialKind; Particles::iterator it = particleSystem.begin(); Particles::iterator end = particleSystem.end(); WorldTriangle tri; //bust out of the loop if we take more than 0.5 msec //Sprite particles don't calculate spin while ( it != end && timestamp()<tend ) { Particle &particle = *it++; if (!particle.isAlive()) { continue; } //note - particles get moved after actions. Vector3 velocity; particle.getVelocity(velocity); Vector3 pos; Vector3 newPos; if(particleSystem.isLocal()) { Matrix world = particleSystem.worldTransform(); pos = world.applyPoint(particle.position()); Vector3 nPos; particleSystem.predictPosition( particle, dTime, nPos ); newPos = world.applyPoint(nPos); } else { pos = particle.position(); particleSystem.predictPosition( particle, dTime, newPos ); } float tValue = pGS->collide( pos, newPos, tri ); if ( tValue >= 0.f && tValue <= 1.f ) { // calc v as a dotprod of the two normalised vectors (before and after collision) Vector3 oldVel = velocity / velocity.length(); tri.bounce( velocity, elasticity_ ); particle.setVelocity( velocity ); float newSpeed = velocity.length(); Vector3 newVel(velocity / newSpeed); float severity = oldVel.dotProduct(newVel); //DEBUG_MSG("severity: %1.3f, speed=%1.3f\n", severity, newSpeed); float v = (1 - severity) * newSpeed; //now spin the particle ( mesh only ) if ( !spriteBased_ ) { //first, calculate the current rotation, and update the pitch/yaw value. Matrix currentRot; currentRot.setRotate( particle.yaw(), particle.pitch(), 0.f ); Matrix spin; float spinSpeed = particle.meshSpinSpeed(); Vector3 meshSpinAxis = particle.meshSpinAxis(); // If there is no spin direction then creating a rotation // matrix can create weird matrices - e.g. matrices with // negative scale components and a translation. We choose the // velocity as the spin direction (aribitrarily choosing, for // example up looks weird). if (meshSpinAxis == Vector3::zero()) { meshSpinAxis = velocity; meshSpinAxis.normalise(); } D3DXMatrixRotationAxis ( &spin, &meshSpinAxis, spinSpeed * (particle.age()-particle.meshSpinAge()) ); currentRot.preMultiply( spin ); particle.pitch( currentRot.pitch() ); particle.yaw( currentRot.yaw() ); //now, reset the age of the spin particle.meshSpinAge( particle.age() ); //finally, update the spin ( stored in the particle's colour ) float addedSpin = unitRand() * (maxAddedRotation_-minAddedRotation_) + minAddedRotation_; addedSpin *= min( newSpeed, 1.f ); spinSpeed = Math::clamp( 0.f, spinSpeed + addedSpin, 1.f ); particle.meshSpinSpeed(spinSpeed); particle.meshSpinAxis(meshSpinAxis); } if ( soundEnabled_ && v > 0.5f ) { soundHit = true; if (v > maxVelocity) { maxVelocity = v; soundPos = particle.position(); materialKind = tri.materialKind(); } } } } if ( soundHit ) { SmartPointer < RompSound > rs = RompSound::getProvider(); if (rs) { if (!soundTag_.empty()) { rs->playParticleSound( soundTag_.c_str(), soundPos, maxVelocity, soundSrcIdx_, materialKind ); } } } }