/*! \brief Free streams two particles up to the current time. * * This is here incase an optimisation or overload is performed later. * * This synchronises the delayed states of the two particle. * \param p1 A Particle to syncronise. * \param p2 A Particle to syncronise. */ inline void updateParticlePair(const Particle& p1, const Particle& p2) const { //This is slow but sure, other stuff like reverse streaming, and //partial streaming are faster but work only for some collision //detections, not compression updateParticle(p1); updateParticle(p2); }
ParticleEventData DynNewtonian::runAndersenWallCollision(Particle& part, const Vector & vNorm, const double& sqrtT, const double) const { updateParticle(part); if (hasOrientationData()) M_throw() << "Need to implement thermostating of the rotational degrees" " of freedom"; //This gives a completely new random unit vector with a properly //distributed Normal component. See Granular Simulation Book ParticleEventData tmpDat(part, *Sim->species[part], WALL); double mass = Sim->species[tmpDat.getSpeciesID()]->getMass(part.getID()); for (size_t iDim = 0; iDim < NDIM; iDim++) part.getVelocity()[iDim] = Sim->normal_sampler() * sqrtT / std::sqrt(mass); part.getVelocity() //This first line adds a component in the direction of the normal += vNorm * (sqrtT * sqrt(-2.0*log(1.0-Sim->uniform_sampler()) / mass) //This removes the original normal component -(part.getVelocity() | vNorm)); tmpDat.setDeltaKE(0.5 * mass * (part.getVelocity().nrm2() - tmpDat.getOldVel().nrm2())); return tmpDat; }
ParticleEventData DynNewtonian::randomGaussianEvent(Particle& part, const double& sqrtT, const size_t dimensions) const { #ifdef DYNAMO_DEBUG if (dimensions > NDIM) M_throw() << "Number of dimensions passed larger than NDIM!"; #endif //See http://mathworld.wolfram.com/SpherePointPicking.html if (hasOrientationData()) M_throw() << "Need to implement thermostating of the rotational degrees" " of freedom"; //Ensure the particle is free streamed first updateParticle(part); //Collect the precoll data ParticleEventData tmpDat(part, *Sim->species[part], GAUSSIAN); double mass = Sim->species[tmpDat.getSpeciesID()]->getMass(part.getID()); double factor = sqrtT / std::sqrt(mass); //Assign the new velocities for (size_t iDim = 0; iDim < dimensions; iDim++) part.getVelocity()[iDim] = Sim->normal_sampler() * factor; tmpDat.setDeltaKE(0.5 * mass * (part.getVelocity().nrm2() - tmpDat.getOldVel().nrm2())); return tmpDat; }
ParticleEventData DynCompression::runAndersenWallCollision(Particle& part, const Vector & vNorm, const double& sqrtT, const double d) const { updateParticle(part); if (hasOrientationData()) M_throw() << "Need to implement thermostating of the rotational degrees" " of freedom"; //This gives a completely new random unit vector with a properly //distributed Normal component. See Granular Simulation Book ParticleEventData tmpDat(part, *Sim->species[part], WALL); double mass = Sim->species[tmpDat.getSpeciesID()]->getMass(part.getID()); std::normal_distribution<> normal_dist; std::uniform_real_distribution<> uniform_dist; for (size_t iDim = 0; iDim < NDIM; iDim++) part.getVelocity()[iDim] = normal_dist(Sim->ranGenerator) * sqrtT / std::sqrt(mass); part.getVelocity() //This first line adds a component in the direction of the normal += vNorm * (sqrtT * sqrt(-2.0*log(1.0 - uniform_dist(Sim->ranGenerator)) / mass) //This removes the original normal component -(part.getVelocity() | vNorm) //This adds on the velocity of the wall + d * growthRate) ; return tmpDat; }
NEventData DynGravity::enforceParabola(Particle& part) const { updateParticle(part); const Species& species = *Sim->species(part); NEventData retval(ParticleEventData(part, species, VIRTUAL)); Vector pos(part.getPosition()), vel(part.getVelocity()); Sim->BCs->applyBC(pos, vel); //Find the dimension that is closest to size_t dim = NDIM; double time = std::numeric_limits<float>::infinity(); for (size_t iDim(0); iDim < NDIM; ++iDim) if (g[iDim] != 0) { double tmpTime = std::abs(- vel[iDim] / g[iDim]); if ((std::abs(tmpTime) < time)) { time = tmpTime; dim = iDim; } } #ifdef DYNAMO_DEBUG if (dim >= NDIM) M_throw() << "Could not find a dimension to enforce the parabola in!"; #endif part.getVelocity()[dim] = 0; return retval; }
/// \fn ParticleSystem::doUpdate (float delta) /// \brief Fires the particle update script for every particle. After that the system /// checks if there are still enough particles alive. If not, new particles are initialized /// and put in the active list. void ParticleSystem::update(float delta) { static const float step = 1.0f / 60.0f; updatetime += delta; if ( updatetime >= step ) { for ( int index = 0; index < active; ) { Particle& particle = mParticles[index]; updateParticle(particle, delta, index); } updatetime = 0.0f; } emittime += delta; while ( emittime > mEmitRate && active < maxActive ) { // fetch a particle from the free list Particle& particle = mParticles[active++]; initParticle(particle); emittime -= mEmitRate; } }
void DynGravity::enforceParabola(Particle& part) const { updateParticle(part); Vector pos(part.getPosition()), vel(part.getVelocity()); Sim->BCs->applyBC(pos, vel); //Find the dimension that is closest to size_t dim = NDIM; double time = HUGE_VAL; for (size_t iDim(0); iDim < NDIM; ++iDim) if (g[iDim] != 0) { double tmpTime = std::abs(- vel[iDim] / g[iDim]); if ((std::abs(tmpTime) < time)) { time = tmpTime; dim = iDim; } } #ifdef DYNAMO_DEBUG if (dim >= NDIM) M_throw() << "Could not find a dimension to enforce the parabola in!"; #endif part.getVelocity()[dim] = 0; }
void ParticleComponent::update(sf::Time dt) { if (mEmitting) { emitParticles(computeParticleCount(dt)); } mNeedsVertexUpdate = true; for (std::size_t i = 0; i < mParticles.size();) { updateParticle(mParticles[i], dt); // lifetime, move, rotate if (mParticles[i].passedLifetime < mParticles[i].totalLifetime) { for (std::size_t j = 0; j < mAffectors.size(); ++j) { if (mAffectors[j]) { mAffectors[j](mParticles[i], dt); } } ++i; } else { mParticles.erase(mParticles.begin() + i); } } }
void Emitter::update(){ particle *curr = e->particleList; while(curr){ particle *toUpdate = curr; curr = curr->next; updateParticle(toUpdate); } }
ParticleEventData DynCompression::runPlaneEvent(Particle& part, const Vector& vNorm, const double e, const double diameter) const { updateParticle(part); ParticleEventData retVal(part, *Sim->species[part], WALL); Vector vij = part.getVelocity() - vNorm * diameter * growthRate; part.getVelocity() -= (1+e) * (vNorm | vij) * vNorm; return retVal; }
void ParticleManager::update(float dt) { BBGE_PROF(ParticleManager_update); numActive = 0; for (int i = 0; i < particles.size(); i++) { if (particles[i].active) { updateParticle(&particles[i], dt); } } }
ParticleEventData DynNewtonian::runPlaneEvent(Particle& part, const Vector& vNorm, const double e, const double diameter) const { updateParticle(part); ParticleEventData retVal(part, *Sim->species[part], WALL); part.getVelocity() -= (1+e) * (vNorm | part.getVelocity()) * vNorm; retVal.setDeltaKE(0.5 * Sim->species[retVal.getSpeciesID()]->getMass(part.getID()) * (part.getVelocity().nrm2() - retVal.getOldVel().nrm2())); return retVal; }
void Emitter::update(){ pthread_mutex_lock(&mutex); if(!displaying) return; if(playFromFile){ updateFromFile(); pthread_mutex_unlock(&mutex); return; } particle *curr = e->particleList; while(curr){ particle *toUpdate = curr; curr = curr->next; updateParticle(toUpdate); } pthread_mutex_unlock(&mutex); }
void updateParticles(PARTICLE * ps, PARTICLE * tmp) { int i, j; VECTOR accel; VECTOR summAccel; memcpy(tmp, ps, sizeof(PARTICLE) * PARTICLE_NUMBER); for(i = 0; i != PARTICLE_NUMBER; i++) { vectorInit(&summAccel, 0, 0); for(j = 0; j != PARTICLE_NUMBER; j++) { if (i == j) continue; calcInteraction(ps + i, ps + j, &accel); vectorAdd(&summAccel, &accel); } updateParticle(ps + i, tmp + i, &summAccel); } memcpy(ps, tmp, sizeof(PARTICLE) * PARTICLE_NUMBER); }
BOOST_FOREACH(const size_t& ID, range2) { updateParticle(Sim->particles[ID]); double mass = Sim->species[Sim->particles[ID]]->getMass(ID); structmass2 += mass; Vector pos(Sim->particles[ID].getPosition()), vel(Sim->particles[ID].getVelocity()); Sim->BCs->applyBC(pos, vel); COMVel2 += vel * mass; COMPos2 += pos * mass; }
////////////////////////////////////////////////////////////////////////// // updateParticles void ScnParticleSystemComponent::updateParticles( BcReal Tick ) { // TODO: Iterate over every "affector" at a time, rather than by particle. // - See "updateParticle". // Not optimal, but clear code is clear. (For now...) for( BcU32 Idx = 0; Idx < NoofParticles_; ++Idx ) { ScnParticle& Particle = pParticleBuffer_[ Idx ]; if( Particle.Alive_ ) { updateParticle( Particle, Tick ); } } }
ParticleEventData DynGravity::runPlaneEvent(Particle &part, const Vector& vNorm, const double e, const double diameter) const { updateParticle(part); double e_val = e; if (std::fabs(part.getVelocity() | vNorm) < elasticV) e_val = 1; //Now the tc model; if (_tc > 0) { if ((Sim->systemTime - _tcList[part.getID()] < _tc)) e_val = 1; _tcList[part.getID()] = Sim->systemTime; } return DynNewtonian::runPlaneEvent(part, vNorm, e_val, diameter); }
////////////////////////////////////////////////////////////////////////// // updateParticles void ScnParticleSystemComponent::updateParticles( BcF32 Tick ) { // Wait for upload to have completed. UploadFence_.wait(); // TODO: Iterate over every "affector" at a time, rather than by particle. // - See "updateParticle". MaAABB FullAABB( MaVec3d( 0.0f, 0.0f, 0.0f ), MaVec3d( 0.0f, 0.0f, 0.0f ) ); // Not optimal, but clear code is clear. (For now...) for( BcU32 Idx = 0; Idx < NoofParticles_; ++Idx ) { ScnParticle& Particle = pParticleBuffer_[ Idx ]; if( Particle.Alive_ ) { // Update particle. updateParticle( Particle, Tick ); // Expand AABB by particle's max bounds. const BcF32 MaxHalfSize = BcMax( Particle.Scale_.x(), Particle.Scale_.y() ) * 0.5f; FullAABB.expandBy( Particle.Position_ - MaVec3d( MaxHalfSize, MaxHalfSize, MaxHalfSize ) ); FullAABB.expandBy( Particle.Position_ + MaVec3d( MaxHalfSize, MaxHalfSize, MaxHalfSize ) ); } } // Transform AABB. if( IsLocalSpace_ ) { const MaMat4d& WorldTransform = getParentEntity()->getWorldMatrix(); AABB_ = FullAABB.transform( WorldTransform ); } else { AABB_ = FullAABB; } UpdateFence_.decrement(); }
NEventData DynNewtonian::multibdyCollision(const IDRange& range1, const IDRange& range2, const double&, const EEventType& eType) const { Vector COMVel1(0,0,0), COMVel2(0,0,0), COMPos1(0,0,0), COMPos2(0,0,0); double structmass1(0), structmass2(0); BOOST_FOREACH(const size_t& ID, range1) { updateParticle(Sim->particles[ID]); double mass = Sim->species[Sim->particles[ID]]->getMass(ID); structmass1 += mass; Vector pos(Sim->particles[ID].getPosition()), vel(Sim->particles[ID].getVelocity()); Sim->BCs->applyBC(pos, vel); COMVel1 += vel * mass; COMPos1 += pos * mass; }
bool updateEmitter(tEmitter *emitter, tVector forces, float dt) { int loop,emits; tParticle *particle, *next; if (emitter != NULL) { emitter->forces=forces; if (emitter->particle != NULL) { particle = emitter->particle; while (particle) { next = particle->next; updateParticle(particle,emitter,dt); particle = next; } } emits=emitter->emitsPerFrame+(int)((float)emitter->emitVar*CORE_FRand(0,1)); for (loop = 0; loop < emits; loop++) addParticle(emitter); return TRUE; } return FALSE; }
void ParticleSystem::simulate(float deltaTime) { _timer += deltaTime; // update emitters for (int emitterIndex = 0; emitterIndex < _numEmitters; emitterIndex++) { assert(emitterIndex <= MAX_EMITTERS); if (_emitter[emitterIndex].active) { updateEmitter(emitterIndex, deltaTime); } } // update particles for (int p = 0; p < MAX_PARTICLES; p++) { if (_particle[p].alive) { if (_particle[p].age > _emitter[_particle[p].emitterIndex].particleLifespan) { killParticle(p); } else { updateParticle(p, deltaTime); } } } }
//adds a new particle to the particles array void ParticleSystem::addParticle(ParticleData* _particle) { if(lastParticle < this->particleLimit-1) { particles[++lastParticle]=_particle->particle; particlesPositions[lastParticle]=_particle->position; particlesVelocities[lastParticle]=_particle->velocity; //Add vertex data updateParticle(&particlesPositions[lastParticle],&vertexData[lastParticle*12],camera->getViewMatrix(),_particle->particle->size); //Add color data for(int i=0;i<4;i++) { colorData[lastParticle*12+i*3]=_particle->color.x; colorData[lastParticle*12+i*3+1]=_particle->color.y; colorData[lastParticle*12+i*3+2]=_particle->color.z; } } else { //delete the particle so not to lose memory delete _particle->particle; //fprintf(stderr,"[ERROR] No more new particles can be added. The system can only handle %d particles.\n",particleLimit); } }