//------------------------------------------------------------------------------ void HamiltonMatrix::computeTimDepMatrixElements(int basisSize) { cout << "Setting up the time dependent part of the Hamilton matrix." << endl; int phase; int nStates = slaterDeterminants.size(); bitset<BITS> newState; double interactionElement = 1.0 / sqrt(2 * w); for (int st = 0; st < nStates; st++) { for (int p = 0; p < basisSize-1; p++) { // <Psi'|Psi^p_{p+1}> newState = slaterDeterminants[st]; phase = 1; newState = removeParticle(p + 1, newState); phase *= sign(p + 1, newState); newState = addParticle(p, newState); phase *= sign(p, newState); if (newState[BITS - 1] != 1) { for (int st2 = 0; st2 < (int)slaterDeterminants.size(); st2++) { if (newState == slaterDeterminants[st2]) { Ht(st, st2) += sqrt(p+1)*interactionElement * phase; break; } } } // <Psi'|Psi^{p+1}_p> newState = slaterDeterminants[st]; phase = 1; newState = removeParticle(p, newState); phase *= sign(p, newState); newState = addParticle(p + 1, newState); phase *= sign(p + 1, newState); if (newState[BITS - 1] != 1) { for (int st2 = 0; st2 < (int)slaterDeterminants.size(); st2++) { if (newState == slaterDeterminants[st2]) { Ht(st, st2) += sqrt(p+1)*interactionElement * phase; break; } } } } } #if DEBUG cout << "computeTimDepMatrixElements(int basisSize)" << endl; cout << Ht << endl; #endif }
void HamiltonMatrix::computeMatrixElements() { cout << "Computing the Hamilton matrix " << endl; int s; int nStates = SLBit.size(); // int newState; bitset<BITS> newState; int i, j, k, l; double interactionElement; H = zeros(nStates, nStates); for (int st = 0; st < SLBit.size(); st++) { for (int b = 0; b < interactions.n_rows; b++) { newState = SLBit[st]; i = interactions(b, 0); j = interactions(b, 1); k = interactions(b, 2); l = interactions(b, 3); interactionElement = interactions(b, 4); // Using the two body operator. Mathematics: a+(i)a+(j)a-(l)a-(k)|psi> s = 1; newState = removeParticle(k, newState); s *= sign(k, newState); newState = removeParticle(l, newState); s *= sign(l, newState); newState = addParticle(j, newState); s *= sign(j, newState); newState = addParticle(i, newState); s *= sign(i, newState); if (newState != 0) { // Searching for the new state to compute the matrix elements. for (int st2 = 0; st2 < SLBit.size(); st2++) { if (newState == SLBit[st2]) { H(st, st2) += interactionElement * s; } } } } // One body energies H(st, st) += oneBodyEnergy(st); } // Symmetrizing the Hamilton matrix for (int i = 0; i < H.n_rows; i++) { for (int j = 0; j < i; j++) { H(j, i) = H(i, j); } } cout << "Completed generating the Hamilton matrix" << endl; }
TEST(TransferParticlesToPointCloudBehaviorTests, UpdateTest) { auto runtime = std::make_shared<Framework::Runtime>(); runtime->addManager(std::make_shared<Framework::BehaviorManager>()); runtime->addManager(std::make_shared<Physics::PhysicsManager>()); auto sceneElement = std::make_shared<Framework::BasicSceneElement>("Element"); auto particles = std::make_shared<Particles::SphRepresentation>("Particles"); particles->setMaxParticles(10); particles->setMassPerParticle(1.0); particles->setDensity(1.0); particles->setGasStiffness(1.0); particles->setKernelSupport(1.0); for (size_t particleId = 0; particleId < 10; particleId++) { particles->addParticle(Vector3d(static_cast<double>(particleId), 0.0, 0.0), Vector3d::Zero(), 100000); } sceneElement->addComponent(particles); auto pointCloud = std::make_shared<Graphics::OsgPointCloudRepresentation>("Graphics"); sceneElement->addComponent(pointCloud); auto behavior = std::make_shared<TransferParticlesToPointCloudBehavior>("Behavior"); behavior->setSource(particles); behavior->setTarget(pointCloud); sceneElement->addComponent(behavior); auto scene = runtime->getScene(); scene->addSceneElement(sceneElement); particles->update(0.1); behavior->update(0.1); auto sourceVertices = particles->getParticles().safeGet()->getVertices(); auto targetVertices = pointCloud->getVertices()->getVertices(); ASSERT_EQ(sourceVertices.size(), targetVertices.size()); auto sourceVertex = sourceVertices.begin(); auto targetVertex = targetVertices.begin(); for (; sourceVertex != sourceVertices.end(); ++sourceVertex, ++targetVertex) { EXPECT_TRUE(sourceVertex->position.isApprox(targetVertex->position)); } particles->removeParticle(0); particles->removeParticle(1); particles->update(0.1); behavior->update(0.1); sourceVertices = particles->getParticles().safeGet()->getVertices(); targetVertices = pointCloud->getVertices()->getVertices(); ASSERT_EQ(sourceVertices.size(), targetVertices.size()); sourceVertex = sourceVertices.begin(); targetVertex = targetVertices.begin(); for (; sourceVertex != sourceVertices.end(); ++sourceVertex, ++targetVertex) { EXPECT_TRUE(sourceVertex->position.isApprox(targetVertex->position)); } }
//updates the whole particle system (generates new particles & updates existing particles) void ParticleSystem::update() { ParticleData pData; Particle *particle; int count; Vector3D *posTemp, *velTemp; //UPDATE assert(camera!=NULL); const GLfloat *mat=camera->getViewMatrix(); for(register int i=lastParticle;i>=firstParticle;i--) //reverse order to simply the removal -> no more skipping { //save the adresses now, in order to optimize memory access particle=particles[i]; posTemp=particlesPositions+i; velTemp=particlesVelocities+i; //update the particles velocity according to the ATTRACTORS count=attractors.size(); for(int j=0; j<count;j++) attractors[j]->attractParticle(posTemp,velTemp); //update the particles velocity according to the AFFECTORS count=affectors.size(); for(int j=0;j<count;j++) affectors[j]->affectParticle(posTemp,velTemp); //update the new position and vertexes of the particle *posTemp+=*velTemp; this->updateParticle(posTemp,&vertexData[i*12],mat,particle->size); particle->updatePosition(); //check if it should be removed if(particle->hasDied()) removeParticle(i); } //GENERATION assert(emitter!=NULL); //Generate and add 'particlesPerGeneration' new particles. if(!oneTimeGeneration) //if we generate continously for(int i=0;i<particlesPerGeneration;i++) { pData=emitter->generateParticle(); pData.position+=this->position; this->addParticle(&pData); } else //if one time generation is active, we stop after we reach particleLimit generated items for(int i=0;particlesLeft>0 && i<particlesPerGeneration;i++,particlesLeft--) { pData=emitter->generateParticle(); pData.position+=this->position; this->addParticle(&pData); } }
static void updateParticle(GameObject obj) { EntityManager &em = EntityManager::instance(); ParticleComponent *part = em.getComponentForEntity<ParticleComponent>(obj); if (part->start_time + part->time_to_live <= SDL_GetTicks()) { removeParticle(obj); return; } SpaceComponent *space = em.getComponentForEntity<SpaceComponent>(obj); if (space) { space->pos += part->velocity * CFPS::fps_control.GetSpeedFactor(); } }
void PathParticleSystem::update( float dt ) { assert( paths() > 0 ); SpriteParticleSystem::update( dt ); // update positions int particles = this->particles(); const float* times = particleTimes(); Vector3* positions = particlePositions(); int i; for ( i = 0 ; i < particles ; ++i ) { // get local space position float v[3]; float t = times[i] * m_this->particleSpeeds[i]; bool alive = getParticlePosition( i, t, v ); if ( !alive ) { removeParticle( i ); --particles; --i; continue; } // transform to world space Vector3 v1( v[0], v[1], v[2] ); //Vector3 v1; //for ( int j = 0 ; j < 3 ; ++j ) // v1[j] = v[0]*wt(j,0) + v[1]*wt(j,1) + v[2]*wt(j,2); //v1.x += wt(0,3); //v1.y += wt(1,3); //v1.z += wt(2,3); positions[i] = v1; } // update sizes float* particleSizes = this->particleSizes(); for ( i = 0 ; i < particles ; ++i ) { int hint = m_this->particleHints[i]; int path = m_this->particlePaths[i]; float t = (float)hint / (float)m_this->paths[path].curve.keys(); float deltaScale = m_this->particleEndScale - m_this->particleStartScale; float scale = deltaScale * t + m_this->particleStartScale; particleSizes[i] = m_this->originalParticleSizes[i] * scale; } }
void ParticleSystem::ParticleManager::reset() { Particle* p; Particle* next; // Remove all pending add particles. p = mAddHead; while(p) { next = p->mAddNext; removeParticle(p); p = next; } mAddHead = NULL; mAddTail = NULL; // Remove all current particles. p = mHead; while(p) { next = p->mNext; removeParticle(p); p = next; } }
//=====-----=======---------=========---------==========---------=========----------============= void ParticleSet::updateParticles(const float deltaTime) { for(int i = 0; i <= mHighestLiveIndex; ++i) { if(!mParticles[i].mAlive) { continue; } // Check to see if the particle has expired if (mParticles[i].mLifetime > 0) { mParticles[i].mLifetime -= deltaTime; // Death is knocking? if (mParticles[i].mLifetime <= 0.0f) { removeParticle(i); continue; } } if (mParticles[i].mOmega != 0) { mParticles[i].mOmega *= mOmegaDamping; mParticles[i].mAngleDeg += mParticles[i].mOmega; } mParticles[i].mForceAccum = mParticles[i].mForceAccum * mParticles[i].mInvMass; // update particles mIntegrator.integrateParticle(mParticles[i].mPosition, mParticles[i].mPositionOld, mParticles[i].mVelocity, mParticles[i].mForceAccum, deltaTime); memset( &mParticles[i].mForceAccum, 0, sizeof(Vector2) ); } // call the per particle post callback if it exists if(mPostParticleUpdateCallback) { PostUpdateParameters params(this); mPostParticleUpdateCallback->invoke(¶ms); } //memset( &mPartForces[0], 0, sizeof(Vector2) * mNumParticles ); }
//------------------------------------------------------------------------------ cx_double OrbitalEquation::reducedOneParticleOperator(const int i, const int j) { bitset<BITS> newState; double phase; cx_double value = 0; for(int n=0; n<nSlaterDeterminants; n++){ for(int m=0; m<nSlaterDeterminants; m++){ phase = 1; newState = slaterDeterminants[m]; //------------------------------------------------------------------ // The following is an ugly way of writing //------------------------------------------------------------------ // removeParticle(j, newState); // phase *= sign(j, newState); // addParticle(i, newState); // phase *= sign(i, newState); // if(slaterDeterminants[n] == newState) // value += phase*conj((*A)(n))*(*A)(m); //------------------------------------------------------------------ removeParticle(j, newState); if(newState[BITS-1] != 1){ phase *= sign(j, newState); addParticle(i, newState); if(newState[BITS-1] != 1){ phase *= sign(i, newState); if (!newState[BITS - 1]) { if(slaterDeterminants[n] == newState) value += phase*conj((*A)(n))*(*A)(m); } } } //------------------------------------------------------------------ } } return value; }
//update the particle system with; //The difference in time since the last update void ParticleSystem::update(float dt) { //loop through all the active particles for (int i = 0; i < (int)_activeParticles.size(); i++) { Particle * loopedParticle = _activeParticles[i]; //if the particle is older than what it should be.. if (loopedParticle->Age > loopedParticle->MaxAge) { //remove the particle removeParticle(loopedParticle); //reduce the iterator because we've just deleted a particle and don't want to skip over the next in the loop i--; continue; } //updating them _activeParticles[i]->update(dt); //affect the particle's velocity by the system's gravity _activeParticles[i]->MoveVector = _activeParticles[i]->MoveVector + (Gravity * dt); } //if the system is allowed to regen particles... if (ShouldRegenParticles == true) { //reduce the emission count by the dt so we know when we can next spawn a particle if (_emissionCountdown > 0) _emissionCountdown -= dt; //else if the emission countdown has been passed then we can spawn more else replenishParticles(dt); } }
void ParticleEmitter::addParticle() { if ((_iTailIndex == _iHeadIndex) && (_iParticleCount != 0)) // FIFO is full { removeParticle(); // Now there is a slot free } // Add a single-shape actor to the scene NxActorDesc actorDesc; NxBodyDesc bodyDesc; NxSphereShapeDesc sphereDesc; sphereDesc.radius = 1.0f; sphereDesc.group = cParticleCollisionGroup; // this group does not collide with itself actorDesc.shapes.pushBack(&sphereDesc); actorDesc.body = &bodyDesc; actorDesc.density = 10.0f; actorDesc.globalPose.t = _vStartingPos; NxActor* pNewActor = _pScene->createActor(actorDesc); // Give it an initial linear velocity, scaled by _fStartingVelScale NxVec3 vRandVec(NxReal(rand()*_fStartingVelScale), NxReal(rand()*_fStartingVelScale), NxReal(rand()*_fStartingVelScale)); pNewActor->setLinearVelocity(vRandVec); // Turn off gravity for smoke pNewActor->raiseBodyFlag(NX_BF_DISABLE_GRAVITY); _aParticleArray[_iHeadIndex] = new Particle(pNewActor, _vThermoDynamicAcceleration); _iHeadIndex = (_iHeadIndex+1) % ciMaxParticles; ++_iParticleCount; }
/** * Finalizes and removes the specified particle. Finalization must happen first, because the * particle may be removed to create space, which can result in its deallocation if this emitter * is all that is holding onto it. */ void CC3ParticleEmitter::finalizeAndRemoveParticle( CC3Particle* aParticle, GLuint anIndex ) { aParticle->finalizeParticle(); removeParticle( aParticle, anIndex ); }
bool ParticleSystem::update(float deltaTime) { deltaTime*=settings.timeSpeed; life.update(deltaTime); if(attachedPhysicsObject!=NULL) { pos = attachedPhysicsObject->pos; if(!attachedPhysicsObject->isEnabled()) { //cout << "WHAT THE ACTUAL? " <<endl; } } // if we've just become activated play a sound if(life.active && (life.elapsedTime-deltaTime <= life.delay)){ if(settings.startSound!="") { //float pan = (pos.x - APP_WIDTH/2)/ (APP_WIDTH/2); //cout << "pan " << pan << endl; float volume = 1; if(attachedPhysicsObject!=NULL) { //volume = ofMap(attachedPhysicsObject->vel.length(), 200,3000,0,1,true); volume = power*0.8+0.2; //cout << "volume "<< volume << " " << attachedPhysicsObject->vel.length() << endl; } // soundPlayer.playSound(settings.startSound, volume , pan); soundPlayer.playSoundPanned(settings.startSound, volume, pos); } } if(life.active) { int newparticlecount = 0; if(settings.emitMode == PARTICLE_EMIT_CONTINUOUS) { newparticlecount = (life.elapsedTime-life.delay)*settings.emitCount; } else if (settings.emitMode == PARTICLE_EMIT_BURST) { newparticlecount = settings.emitCount; if(settings.emitShape!=NULL) { newparticlecount = settings.emitShape->getNumVertices(); } life.end(); } while(numParticlesCreated<newparticlecount) { Particle& p = *addParticle(); if(settings.emitPositionShape!=NULL) { p.pos = settings.emitPositionShape->getVertex(ofRandom(0,settings.emitPositionShape->getNumVertices())); } else if(attachedPhysicsObject!=NULL) { if(settings.emitMode == PARTICLE_EMIT_CONTINUOUS) { p.pos = ((attachedPhysicsObject->pos - attachedPhysicsObject->lastPos) * ofMap(numParticlesCreated/settings.emitCount, life.lastUpdateTime, life.elapsedTimeActual,0,1)) + attachedPhysicsObject->lastPos; } else { p.pos = attachedPhysicsObject->pos; } } else { p.pos = pos; } } } activeParticleCount = 0; Particle *p = firstParticle; while(p!=NULL) { //if(!p.enabled) continue; p->update(deltaTime); if(!p->enabled) { p = removeParticle(p); } else { activeParticleCount++; p = p->next; } } finished = ((activeParticleCount ==0) && (life.isFinished())); return finished; }
void graphics_ParticleSystem_update(graphics_ParticleSystem *ps, float dt) { if(ps->pMem == 0 || dt == 0.0f) { return; } graphics_Particle *p = ps->pHead; while(p) { p->life -= dt; if(p->life <= 0.0f) { p = removeParticle(ps, p); continue; } float radialX = p->position[0] - p->origin[0]; float radialY = p->position[1] - p->origin[1]; normalizeInPlace(&radialX, &radialY); float tangentialX = -radialY * p->tangentialAcceleration; float tangentialY = radialX * p->tangentialAcceleration; radialX *= p->radialAcceleration; radialY *= p->radialAcceleration; p->velocity[0] += (radialX + tangentialX + p->linearAcceleration[0]) * dt; p->velocity[1] += (radialY + tangentialY + p->linearAcceleration[1]) * dt; p->velocity[0] *= 1.0f / (1.0f + p->linearDamping * dt); p->velocity[1] *= 1.0f / (1.0f + p->linearDamping * dt); p->position[0] += p->velocity[0] * dt; p->position[1] += p->velocity[1] * dt; float const t = 1.0f - p->life / p->lifetime; p->rotation += lerp(p->spinStart, p->spinEnd, t) * dt; p->angle = p->rotation; if(ps->relativeRotation) { p->angle += atan2(p->velocity[1], p->velocity[0]); } float s = (p->sizeOffset + t * p->sizeIntervalSize) * (float)(ps->sizeCount - 1); size_t i = (size_t)s; size_t k = (i == ps->sizeCount - 1) ? i : i + 1; s -= (float)i; p->size = lerp(ps->sizes[i], ps->sizes[k], s); s = t * (float)(ps->colorCount - 1); i = (size_t)s; k = (i == ps->colorCount - 1) ? i : i + 1; s -= (float)i; p->color.red = lerp(ps->colors[i].red, ps->colors[k].red, s); p->color.green = lerp(ps->colors[i].green, ps->colors[k].green, s); p->color.blue = lerp(ps->colors[i].blue, ps->colors[k].blue, s); p->color.alpha = lerp(ps->colors[i].alpha, ps->colors[k].alpha, s); k = ps->quadCount; if(k > 0) { s = t * (float)k; i = (s > 0.0f) ? (size_t) s : 0; p->quadIndex = (i < k) ? i : k - 1; } p = p->next; } if(ps->active) { float rate = 1.0f / ps->emissionRate; ps->emitCounter += dt; float total = ps->emitCounter - rate; while(ps->emitCounter > rate) { addParticle(ps, 1.0f - (ps->emitCounter - rate) / total); ps->emitCounter -= rate; } ps->life -= dt; if(ps->lifetime != -1 && ps->life < 0) { graphics_ParticleSystem_stop(ps); } } memcpy(ps->prevPosition, ps->position, sizeof(ps->position)); }
void ParticleEmitter::removeAllParticles() { while (_iParticleCount > 0) removeParticle(); }
//------------------------------------------------------------------------------ void HamiltonMatrix::computeMatrixElements() { cout << "Setting up the Hamilton matrix " << endl; int phase; int nStates = slaterDeterminants.size(); bitset<BITS> newState; int i, j, k, l; double interactionElement; H = zeros(nStates, nStates); Ht = zeros(nStates, nStates); for (int st = 0; st < nStates; st++) { for (int b = 0; b < (int)interactions.n_rows; b++) { newState = slaterDeterminants[st]; i = interactions(b, 0); j = interactions(b, 1); k = interactions(b, 2); l = interactions(b, 3); // Using the two body operator. Mathematics: a+(i)a+(j)a-(l)a-(k)|psi> phase = 1; newState = removeParticle(k, newState); phase *= sign(k, newState); newState = removeParticle(l, newState); phase *= sign(l, newState); newState = addParticle(j, newState); phase *= sign(j, newState); newState = addParticle(i, newState); phase *= sign(i, newState); if (newState[BITS - 1] != 1) { interactionElement = interactions(b, 4); // Searching for the new state to compute the matrix elements. for (int st2 = 0; st2 < (int)slaterDeterminants.size(); st2++) { if (newState == slaterDeterminants[st2]) { H(st, st2) += interactionElement * phase; break; } } } } // One body energies H(st, st) += spsEnergy(st); } #if DEBUG cout << H << endl; // // Symmetrizing the Hamilton matrix // for (int i = 0; i < H.n_rows; i++) { // for (int j = 0; j < i; j++) { // H(j, i) = H(i, j); // } // } cout << "Completed generating the Hamilton matrix" << endl; #endif }
int main(){ //// Declarations // define functions for modularity void initialise( int [], int [], double [], double []); void addParticle( int [], double); void removeParticle(int [], double); void moveParticle( int [], int ); void moveParticle2D(int [], int [], int ); int iter=1e8; // lattice and iterations to be done on them. int i, j, ii, rn; int intrvl = 100; // interval after how many iterations at which observation is made. double lbc=0.4, rbc=0.2; // boundary conditions (BCs) on the left and right boundaries. double lbc2=0.001, rbc2=0.8; // boundary conditions (BCs) on the left and right boundaries. int A[Ns], B[Ns]; // occupancy of the site on the two lattices double d[Ns], d2[Ns]; // density on the two lattices init_genrand(time(NULL)); // seed the random number generator with the NULL of the time! initialise(A, B, d, d2); // initialise the array! // now simulate for (j=1; j<iter; j++){ rn = genrand_real2()*(Ns+1); // NOTE that we have generated N+1 RNs for N sized lattice. if (genrand_real2() <0.5){ // choose the lattice randomly! // case corresponding to the addition of particle if (( rn == Ns) && (A[0]==0) ) addParticle(A, lbc); // case corresponding to the particle removal else if ( (rn == Ns-1) && (A[Ns-1]==1) ) removeParticle(A, rbc); // move the particles on the lattice else if ( (A[rn]==1) && (A[rn+1]==0) ) moveParticle2D(A, B, rn); } // lattice 2 else{ // case corresponding to the addition of particle if (( rn == Ns) && (B[0]==0) ) addParticle(B, lbc2); // case corresponding to the particle removal else if ( (rn == Ns-1) && (B[Ns-1]==1) ) removeParticle(B, rbc2); // move the particles on the lattice else if ( (B[rn]==1) && (B[rn+1]==0) ) moveParticle2D(B, A, rn); } // take the observation with this interval! if (j>1e5 && j%intrvl==0){ for (ii=0; ii<Ns; ii++) { d[ii] +=A[ii]; d2[ii]+=B[ii]; } } } //simulation completed! Now plot, save, etc. with the data. FILE *fp; fp = fopen("testData.txt", "w"); for (i=0; i<Ns; i++){ printf( "%d \t %0.4f\t%0.4f\t \n", i, intrvl*d[i]/iter, intrvl*d2[i]/iter); fprintf(fp, "%d \t %0.4f\t%0.4f\t \n", i, intrvl*d[i]/iter, intrvl*d2[i]/iter); } fclose(fp); // that is all! return 0; }
//kbd. Handles toggle switching system settings with regular keys. void kbd(unsigned char key, int x, int y){ if (key == 'q'|| key == 'Q'){ exit(0); } if (key == 'r'|| key == 'R'){ restart(); } if (key == ' '){ paused = !paused; if(paused == true){ std::cout << "The animation is paused" << std::endl; } else{ std::cout <<"The animation is running!" << std::endl;} } if (key == 'z' || key == 'Z'){ addParticle(); } if (key == 'x' || key == 'X'){ particleSpray(); } if (key == 'c' || key == 'C'){ removeParticle(); } //Wind toggles if (key == 'w' || key == 'W'){ westerly = !westerly; if(westerly == true){ std::cout << "There's a western wind!" << std::endl; } else{ std::cout <<"The western wind has died down." << std::endl;} } if (key == 'e' || key == 'E'){ easterly = !easterly; if(easterly == true){ std::cout << "There's an eastern wind!" << std::endl; } else{ std::cout <<"The eastern wind has died down." << std::endl;} } if (key == 's' || key == 'S'){ southernly = !southernly; if(southernly == true){ std::cout << "There's a southernly wind!" << std::endl; } else{ std::cout << "The southernly wind has died down." << std::endl;} } if (key == 'n' || key == 'N'){ northernly = !northernly; if(northernly == true){ std::cout << "There's a northernly wind!" << std::endl; } else{ std::cout <<"The northernly wind has died down." << std::endl;} } //Friction if (key == 'f'){ bounceFriction = !bounceFriction; if(bounceFriction == true){ std::cout << "Bounce friction has been turned on" << std::endl; } else{ std::cout <<"Bounce friction has been turned off." << std::endl;} } //as close as you'll get to a help menu toggler if (key == 'h'){ initComments(); } }
void ParticleSystem::update(float dt) { if (pMem == nullptr || dt == 0.0f) return; // Traverse all particles and update. Particle *p = pHead; while (p) { // Decrease lifespan. p->life -= dt; if (p->life <= 0) p = removeParticle(p); else { // Temp variables. love::Vector radial, tangential; love::Vector ppos = p->position; // Get vector from particle center to particle. radial = ppos - p->origin; radial.normalize(); tangential = radial; // Resize radial acceleration. radial *= p->radialAcceleration; // Calculate tangential acceleration. { float a = tangential.getX(); tangential.setX(-tangential.getY()); tangential.setY(a); } // Resize tangential. tangential *= p->tangentialAcceleration; // Update velocity. p->velocity += (radial + tangential + p->linearAcceleration) * dt; // Apply damping. p->velocity *= 1.0f / (1.0f + p->linearDamping * dt); // Modify position. ppos += p->velocity * dt; p->position = ppos; const float t = 1.0f - p->life / p->lifetime; // Rotate. p->rotation += (p->spinStart * (1.0f - t) + p->spinEnd * t) * dt; p->angle = p->rotation; if (relativeRotation) p->angle += atan2f(p->velocity.y, p->velocity.x); // Change size according to given intervals: // i = 0 1 2 3 n-1 // |-------|-------|------|--- ... ---| // t = 0 1/(n-1) 3/(n-1) 1 // // `s' is the interpolation variable scaled to the current // interval width, e.g. if n = 5 and t = 0.3, then the current // indices are 1,2 and s = 0.3 - 0.25 = 0.05 float s = p->sizeOffset + t * p->sizeIntervalSize; // size variation s *= (float)(sizes.size() - 1); // 0 <= s < sizes.size() size_t i = (size_t)s; size_t k = (i == sizes.size() - 1) ? i : i + 1; // boundary check (prevents failing on t = 1.0f) s -= (float)i; // transpose s to be in interval [0:1]: i <= s < i + 1 ~> 0 <= s < 1 p->size = sizes[i] * (1.0f - s) + sizes[k] * s; // Update color according to given intervals (as above) s = t * (float)(colors.size() - 1); i = (size_t)s; k = (i == colors.size() - 1) ? i : i + 1; s -= (float)i; // 0 <= s <= 1 p->color = colors[i] * (1.0f - s) + colors[k] * s; // Update the quad index. k = quads.size(); if (k > 0) { s = t * (float) k; // [0:numquads-1] (clamped below) i = (s > 0.0f) ? (size_t) s : 0; p->quadIndex = (int) ((i < k) ? i : k - 1); } // Next particle. p = p->next; } } // Make some more particles. if (active) { float rate = 1.0f / emissionRate; // the amount of time between each particle emit emitCounter += dt; float total = emitCounter - rate; while (emitCounter > rate) { addParticle(1.0f - (emitCounter - rate) / total); emitCounter -= rate; } life -= dt; if (lifetime != -1 && life < 0) stop(); } prevPosition = position; }