void FTLParticleChain::simulateStep()
	{
		std::vector<std::pair<Particle*, CollisionConstraint> > collisionConstraints;

		auto i = mParticles.begin()+1;
		Ogre::Vector3 oldPos(i->position);
		i->velocity += i->force * mTimestep * mParticleMassInv;
		i->position += i->velocity * mTimestep;
		Ogre::Vector3 correctionVec = computeFTLCorrectionVector(i);
		CollisionConstraint cc;
		if (checkPenetration(i->position, cc.closestSurfacePoint, cc.normal))
		{
			collisionConstraints.push_back(std::make_pair(&(*i), cc));
			i->position += computeCollisionCorrection(i->position, cc);
		}
		for (; i != mParticles.end()-1; ++i)
		{
			// recompute FTL correction, considering the previously added collision response
			i->position += computeFTLCorrectionVector(i);	//correctionVec;

			auto succ = i + 1;
			Ogre::Vector3 nextOldPos(succ->position);
			succ->velocity += succ->force * mTimestep * mParticleMassInv;
			succ->position += succ->velocity * mTimestep;

			// this seems give the most stable results:
			// 1. compute FTL correction vector without considering collision, use this for damping
			// 2. add collision response
			// 3. recompute FTL correction and add it (see first line after for loop statement)
			Ogre::Vector3 nextCorrectionVec = computeFTLCorrectionVector(succ);

			if (checkPenetration(succ->position, cc.closestSurfacePoint, cc.normal))
			{
				collisionConstraints.push_back(std::make_pair(&(*succ), cc));
				succ->position += computeCollisionCorrection(succ->position, cc);
			}

			i->velocity = (i->position - oldPos - nextCorrectionVec * mFTLDamping - correctionVec * mPBDPointDamping) / mTimestep;

			correctionVec = nextCorrectionVec;
			oldPos = nextOldPos;
		}

		// perform update for last particle
		i->position += correctionVec;
		i->velocity = (i->position - oldPos - correctionVec * (mPBDPointDamping + mFTLDamping)) / mTimestep;

		// finally project collision constraints once more and simulate friction by damping the velocity
		for (auto ic = collisionConstraints.begin(); ic != collisionConstraints.end(); ++ic)
		{
			Particle &particle = *ic->first;
			particle.position += computeCollisionCorrection(particle.position, ic->second);
			particle.velocity -= mTimestep * mParticleMassInv * computeFrictionDamping(ic->second.normal, particle.velocity);
		}
	}
Beispiel #2
0
/**
 * Updates the sprite to apply gravitational effects to it.
 * The sprite will accellerate downwards unless it lands on another baseable spriteObject.
 */
void massObject::updateSprite()
{
	spriteObject::updateSprite();	//move sprite first
	
	wasGrounded = grounded;
	if (!isOnGround() && !bStasis)
	{
		vy += GRAVITY;
		if (vy > TERMINALVEL)
			vy = TERMINALVEL;
		checkPenetration();
	}
	
	grounded = false;		//is re-checked in collidingWith() later in the tick
}
	// this implementation follows closely the method proposed here: http://www.matthiasmueller.info/publications/posBasedDyn.pdf
	void PBDParticleChain::simulateStep()
	{
		std::vector<Particle> futureParticles = mParticles;
		for (auto i = futureParticles.begin() + 1; i != futureParticles.end(); ++i)
		{
			i->velocity += i->force * mParticleMassInv * mTimestep;
			i->velocity -= i->velocity * mPointDamping * mParticleMassInv * mTimestep;	// point damping
			i->position += i->velocity * mTimestep;
		}

		// generate collision constraints
		std::vector<std::pair<int, CollisionConstraint> > collisionConstraints;
		int particleIndex = 1;
		for (auto i = futureParticles.begin() + 1; i != futureParticles.end(); ++i)
		{
			CollisionConstraint cc;
			if (checkPenetration(i->position, cc.closestSurfacePoint, cc.normal))
				collisionConstraints.push_back(std::make_pair(particleIndex, cc));
			particleIndex++;
		}

		// hack: use force component of Particle class to store correction vector for damping later
		for (auto i = futureParticles.begin(); i != futureParticles.end(); ++i)
			i->force = Ogre::Vector3(0, 0, 0);

		// collision constraints
		// maybe it is necessary to put this inside the iterative solver, but so far it seems to work this way
		for (auto ic = collisionConstraints.begin(); ic != collisionConstraints.end(); ++ic)
		{
			Particle &particle = futureParticles[ic->first];
			Ogre::Vector3 collisionCorrection = computeCollisionCorrection(particle.position, ic->second);
			particle.position += collisionCorrection;
			particle.force += collisionCorrection;
		}

		int numIterations = mIterationCount;	//std::min<int>(mIterationCount + collisionConstraints.size(), 10);
		for (int iteration = 0; iteration < numIterations; iteration++)
		{
			auto i = futureParticles.begin() + 1;
			Ogre::Vector3 correction = computeFTLCorrectionVector(i) * mOverRelaxation;
			i->force += correction;
			i->position += correction;

			for (i = futureParticles.begin() + 2; i != futureParticles.end(); ++i)
			{
				correction = computeFTLCorrectionVector(i) * 0.5f * mOverRelaxation;
				(i-1)->position -= correction;
				i->position += correction;
				(i-1)->force -= correction;
				i->force += correction;
			}

			// chain stiffness
			for (i = futureParticles.begin() + 1; i != futureParticles.end() - 1; ++i)
			{
				Ogre::Vector3 target = projectPointOnLine(i->position, (i-1)->position, (i+1)->position);
				Ogre::Vector3 correction = (target - i->position) * mChainStiffness;
				i->position += correction;
				i->force += correction;
			}
		}

		auto ifu = futureParticles.begin() + 1;
		for (auto i = mParticles.begin() + 1; i != mParticles.end(); ++i)
		{
			i->velocity = (ifu->position - i->position - ifu->force * mPBDPointDamping) / mTimestep;
			i->position = ifu->position;
			++ifu;
		}

		// finally project collision constraints once more and simulate friction by damping the velocity
		for (auto ic = collisionConstraints.begin(); ic != collisionConstraints.end(); ++ic)
		{
			Particle &particle = mParticles[ic->first];
			particle.position += computeCollisionCorrection(particle.position, ic->second);
			particle.velocity -= mTimestep * mParticleMassInv * computeFrictionDamping(ic->second.normal, particle.velocity);
		}
	}