/** Compute forces and update particles **/ void ParticleSystem::computeForcesAndUpdateParticles(float t) { time = t; if (!simulate) return; for (int i = 0; i < 20; i++) { for (int j = 19; j >= 0; j--) { if (i == 0 && (j == 0 || j == 19)) continue; Vec3f force = Vec3f(g); Vec3f position = particles[i][j].getPosition(); force += springForce(i - 1, j, position); force += springForce(i + 1, j, position); force += springForce(i, j - 1, position); force += springForce(i, j + 1, position); if (force.length() > 10) { force.normalize(); force *= 10; } particles[i][j].applyForce(force); } } for (int i = 0; i < 20; i++) for (int j = 19; j >= 0; j--) particles[i][j].move(t); bakeParticles(t); }
/** Compute forces and update initial_state **/ void ParticleSystem::computeForcesAndUpdateParticles(float t) { // TODO if (simulate){ // no need to update if the particles are already baked float roundedTime = round(t*bake_fps) / bake_fps; if (bakedParticles.count(roundedTime)){ return; } // compute new force for (int i = 0; i < n; i++){ // clear force accumulator float newForVectors[3] = { 0.0, 0.0, 0.0 }; particles[i].setPositionVectors(newForVectors); float* derivatives = new float[6 * n]; float totalForce[3] = { 0.0, 0.0, 0.0 }; // gravity force float gravityForce[3] = { 0.0, particles[i].getMass() * (-1) * 9.8, 0.0 }; totalForce[0] += gravityForce[0]; totalForce[1] += gravityForce[1]; totalForce[2] += gravityForce[2]; // air drag float airDragCoeff = 10; float airDrag[3] = { airDragCoeff*particles[i].getVelocityVectors()[0], airDragCoeff*particles[i].getVelocityVectors()[1], airDragCoeff*particles[i].getVelocityVectors()[2] }; totalForce[0] += airDrag[0]; totalForce[1] += airDrag[1]; totalForce[2] += airDrag[2]; //update particles derivatives derivatives[0] = particles[i].getVelocityVectors()[0]; derivatives[1] = particles[i].getVelocityVectors()[1]; derivatives[2] = particles[i].getVelocityVectors()[2]; derivatives[3] = totalForce[0] / particles[i].getMass(); derivatives[4] = totalForce[1] / particles[i].getMass(); derivatives[5] = totalForce[2] / particles[i].getMass(); float newPosVectors[3]; float newVelVectors[3]; newPosVectors[0] = particles[i].getPositionVectors()[0] + 1.0 / bake_fps*derivatives[0]; newPosVectors[1] = particles[i].getPositionVectors()[1] + 1.0 / bake_fps*derivatives[1]; newPosVectors[2] = particles[i].getPositionVectors()[2] + 1.0 / bake_fps*derivatives[2]; newVelVectors[0] = particles[i].getVelocityVectors()[0] + 1.0 / bake_fps*derivatives[3]; newVelVectors[1] = particles[i].getVelocityVectors()[1] + 1.0 / bake_fps*derivatives[4]; newVelVectors[2] = particles[i].getVelocityVectors()[2] + 1.0 / bake_fps*derivatives[5]; // reset the position of the particles if it exceeds the limit double limit = 5.0; if (newPosVectors[0] > limit || newPosVectors[1] > limit || newPosVectors[2] > limit){ newPosVectors[0] = initial_state[i].getPositionVectors()[0]; newPosVectors[1] = initial_state[i].getPositionVectors()[1]; newPosVectors[2] = initial_state[i].getPositionVectors()[2]; newVelVectors[0] = initial_state[i].getVelocityVectors()[0]; newVelVectors[1] = initial_state[i].getVelocityVectors()[1]; newVelVectors[2] = initial_state[i].getVelocityVectors()[2]; } // update particles state particles[i].setPositionVectors(newPosVectors); particles[i].setVelocityVectors(newVelVectors); particles[i].setForceVectors(totalForce); delete[] derivatives; } bakeParticles(roundedTime); } }