Esempio n. 1
0
void GravityAffector::updateParticle(const ParticlePtr& particle, float elapsedTime)
{
    if(!m_active)
        return;

    PointF velocity = particle->getVelocity();
    velocity += PointF(m_gravity * elapsedTime * cos(m_angle), m_gravity * elapsedTime * sin(m_angle));
    particle->setVelocity(velocity);
}
void RandomColorAffector::Update(ParticlePtr & particle, float dt) {

	sf::Color color = particle->GetColor();

	color.r = sf::Randomizer::Random(0, 255);
	color.g = sf::Randomizer::Random(0, 255);
	color.b = sf::Randomizer::Random(0, 255);

	particle->SetColor(color);

}
Esempio n. 3
0
FixedDist::FixedDist(ParticlePtr pP0, ParticlePtr pP1, 
					 int matrixCol0, int matrixCol1, int NumParticles) :
	m_pP0(pP0),
	m_pP1(pP1),
	m_MatrixCol0(matrixCol0),
	m_MatrixCol1(matrixCol1),
	m_Dist(bnu::norm_2(pP1->GetPosition() - pP0->GetPosition()))
{
	ResizeDJacobian(NumParticles);
	ResizeJacobian(NumParticles);
	ResizeConPos();
	ResizeConVel();
}
Esempio n. 4
0
void AttractionAffector::updateParticle(const ParticlePtr& particle, float elapsedTime)
{
    if(!m_active)
        return;

    PointF pPosition = particle->getPosition();
    PointF d = PointF(m_position.x - pPosition.x, pPosition.y - m_position.y);
    if(d.length() == 0)
        return;

    PointF direction = PointF(1, 1);
    if(m_repelish)
        direction = PointF(-1, -1);

    PointF pVelocity = particle->getVelocity() + (d / d.length() * m_acceleration * elapsedTime) * direction;
    particle->setVelocity(pVelocity - pVelocity * m_reduction/100.0 * elapsedTime);
}
	void apply(ParticlePtr p) {
		p->position.x = Rand::randFloat(space->min.x, space->max.x);
		p->position.y = Rand::randFloat(space->min.y, space->max.y);
		p->position.z = Rand::randFloat(space->min.z, space->max.z);
		
		p->lifeTime = Rand::randFloat(10, 100);
		//printf("random emit: %f %f %f\n", p->x, p->y, p->z);
		p->clearVelocity();
	}		
Esempio n. 6
0
	void CPointEmitter::InitParticle(ParticlePtr &particle)
	{
		math::vec2f ws_pos = mPos + mPositionOffset;
		math::vec2f dir = this->mDirection.Rotate(util::Rand::Get()->Randomf(-this->mEmisionAngle, this->mEmisionAngle));
		dir.Normalize();
		math::float32 speed = util::Rand::Get()->Randomf(mParticleSpeed-mParticleSpeedVariation, mParticleSpeed+mParticleSpeedVariation);

		math::CColorRGBA clr = RandomiseColor();

		particle->Init(ws_pos, dir, speed, util::Rand::Get()->Randomf(this->mLiveTime-mLiveTimeVariation, this->mLiveTime+mLiveTimeVariation), clr, 0, mScale);
	}
Esempio n. 7
0
void Emitter::Play() {

	if(particles.empty() && maxParticles > 0) return;

	for(int i = 0; i < emissionRate && (!particles.empty() || maxParticles == 0); i++) {

		ParticlePtr particle;

		if(maxParticles > 0) {

			particle = particles.front();
			particles.pop_front();

		} else {
			particle = ParticlePtr(new Particle());
		}

		InitParticle(particle);
		emittedParticles.push_front(particle);
		particle->SetIsVisible(true);
	}

}
Esempio n. 8
0
	void CLineEmitter::InitParticle(ParticlePtr &particle)
	{
		math::vec2f ws_pos = mPos + mPositionOffset;
		math::vec2f dir = this->mDirection.Rotate(util::Rand::Get()->Randomf(-this->mEmisionAngle, this->mEmisionAngle));
		dir.Normalize();
		math::vec2f ws_end_pos = ws_pos + this->mPosEnd;
		math::vec2f normalVec(ws_pos - ws_end_pos);
		math::float32 len = normalVec.Length();
		normalVec.Normalize();
		//len = static_cast<math::float32>(rand()%static_cast<math::int32>(len));
		len = util::Rand::Get()->Randomf(len);
		math::float32 speed = util::Rand::Get()->Randomf(mParticleSpeed-mParticleSpeedVariation, mParticleSpeed+mParticleSpeedVariation);

		math::CColorRGBA clr = RandomiseColor();

		particle->Init(ws_pos + (normalVec * len), dir, speed, util::Rand::Get()->Randomf(this->mLiveTime-mLiveTimeVariation, this->mLiveTime+mLiveTimeVariation), clr, 0, mScale);
	}
Esempio n. 9
0
	void CCircleEmitter::InitParticle(ParticlePtr &particle)
	{
		math::vec2f ws_pos = mPos + mPositionOffset;
		math::vec2f dir = this->mDirection.Rotate(util::Rand::Get()->Randomf(-this->mEmisionAngle, this->mEmisionAngle));
		dir.Normalize();

		math::vec2f spawnPos;
		
		math::float32 randomNr = util::Rand::Get()->Randomf(0.f, math::TWO_PI);
		spawnPos.x = mRadius * math::mathf::Sin(randomNr);
		spawnPos.y = mRadius * math::mathf::Cos(randomNr);

		spawnPos += ws_pos;
		math::float32 speed = util::Rand::Get()->Randomf(mParticleSpeed-mParticleSpeedVariation, mParticleSpeed+mParticleSpeedVariation);

		math::CColorRGBA clr = RandomiseColor();


		particle->Init(spawnPos, dir, speed, util::Rand::Get()->Randomf(this->mLiveTime-mLiveTimeVariation, this->mLiveTime+mLiveTimeVariation), clr, 0, mScale);
	}
void ParticleSystem::collide(ParticlePtr part, PlanePtr plane) {
	//SimonState::exemplar()->messages << "Cloth: Kollision Kugel vs. Ebene gestartet" << SimonState::endm;

	float distance = dot(part->getPosition() - 
						 plane->getRigidBody()->getPosition(), 
						 plane->getNormal());
	Vector3<float> n = plane->getNormal();
    Vector3<float> v = part->getVelocity(); 
	
	float vDotN = dot (v, n);
    //Vector3<float> f = getRigidBody()->getForce(); 	
    
    // no resting contact. check collision
    if ( distance <= 3.0)
    {   
        if (vDotN<=0.5f)
        {
						 
			// normal colliding contact:
			
			Vector3 <float> velPart = part->getVelocity();
			
			Vector3 <float> normPlane = plane->getNormal();
			normPlane.normalize();
			float vDoN = dot(velPart,  normPlane);
			normPlane *= vDoN;
			part->setVelocity(part->getVelocity() - normPlane);
			//cout << "Vel aus col " << part->getVelocity()<< endl;
			normPlane = plane->getNormal();
			normPlane.normalize();
			Vector3 <float> forcePart = part->getForce();
			float fDotN = dot(forcePart, normPlane);
			normPlane *= fDotN;
			part->addForce((-1) * normPlane);
			//cout << "Acc aus Col " << part->getAcceleration() << endl;
			// factor in elasticity
			// geschummelt (eigentlich getBounciness)
			//vDotN *= 1 + 2.5f;
			// reflect veloctiy along normal
			//part->setVelocity( Vector3<float>(v[X] - vDotN*n[X], v[Y] - vDotN*n[Y], v[Z] - vDotN*n[Z]));
			SimonState::exemplar()->messages << "Cloth: Kollision Particle vs. Ebene beendet" << SimonState::endm;
        }
    }
}
/**
* \brief Collision Partikel mit einer Box.
* \param box zu testende Box
*/
void ParticleSystem::collide(ParticlePtr part, BoxPtr box)
{ 
    //sphere in das lokale koordinatensystem der box bringen
	Vector3<float> particlePos = part->getPosition() - box->getRigidBody()->getPosition();
	Quaternion boxOri = box->getRigidBody()->getOrientation();
	const Quaternion& boxInvOri = boxOri.inverse();    
    particlePos = qRotate(particlePos, boxInvOri);
    
    //test auf collision mit den 6 seiten der box
    unsigned int cnt = 0;
	float rad = 3.0f;

	float right = dot(particlePos, Vector3<float>(1,0,0)) + rad;
	float left = dot(particlePos, Vector3<float>(-1,0,0)) - rad;
	float front = dot(particlePos, Vector3<float>(0,0,1)) + rad;
	float back = dot(particlePos, Vector3<float>(0,0,-1)) - rad;
	float top = dot(particlePos, Vector3<float>(0,1,0)) + rad;
	float bottom = dot(particlePos, Vector3<float>(0,-1,0)) - rad;
	
	
    float dR  = box->getWidth()/2 - right + rad;
    float dL  = box->getWidth()/2 - left + rad;
    float dF  = box->getDepth()/2 - front + rad;
    float dBa = box->getDepth()/2 - back + rad;
    float dT  = box->getHeight()/2 - top + rad; 
    float dBo = box->getHeight()/2 - bottom + rad; 
    
    if (right  >= 0 && dR >= 0)  
	{	
		cnt ++;
	    if (right >  box->getWidth()/2)
		  particlePos[X] = box->getWidth()/2;	
		else  		
		  particlePos[X] = right ;	
	}
	if (left   >  0 && dL >= 0)  
	{
		cnt ++;	
		if(left > box->getWidth()/2)
		  particlePos[X] = -box->getWidth()/2;
		else
		  particlePos[X] = -left ;
	}
	if (front  >= 0 && dF >= 0)  
	{
		cnt ++;
		if (front > box->getDepth()/2)  
		  particlePos[Z] = box->getDepth()/2;
		else
		  particlePos[Z] = front;	  
 	}
	if (back   >  0 && dBa >= 0)  
	{
		cnt ++;
		if (back > box->getDepth()/2)  
		  particlePos[Z] = -box->getDepth()/2;
		else
		  particlePos[Z] = -back;  	
 	}
	if (top    >= 0 && dT >= 0) 
	{
		cnt ++;
		if (top > box->getHeight()/2)  
		  particlePos[Y] = box->getHeight()/2;
		else
		  particlePos[Y] = top;	  
 	}
	if (bottom >  0 && dBo >= 0) 
	{
		cnt ++;
		if (bottom > box->getHeight()/2)  
		  particlePos[Y] = -box->getHeight()/2;
		else
		  particlePos[Y] = -bottom  ;
	}
    
	//test auf collision
    if (cnt >= 3)
	{
		
		//berechnung normalB und contactPoint
		const Vector3<float>& contactPoint 
			= qRotate(particlePos, boxOri) + box->getRigidBody()->getPosition();
		//cout << "C: " << contactPoint << endl;
		//cout << "P: " << part->getPosition() << endl;
		Vector3<float> normalB = part->getPosition() - contactPoint;
		//cout << normalB.length() <<"\n";

		//if (normalB.length() != 0)
		normalB.normalize();
		
		// folgender Abschnitt aus: 
		// CollisionSystem::collisionResponse(part, sphere, contactPoint, normalB);

		//berechnung der relativen geschwindigkeit in richtung normalB
		const Vector3<float>& velocityA = part->getVelocity();
		const Vector3<float>& velocityB = box->getRigidBody()->getVelocity();
		Vector3<float> velA = part->getVelocity();
		Vector3<float> forceA = part->getForce();


//		const Vector3<float>& rA = contactPoint - part->getPosition(); // vorher: particlePos!
//		const Vector3<float>& rB = contactPoint - box->getPosition();
		
		const Vector3<float>& vA = velocityA;
		const Vector3<float>& vB = velocityB;
		const Vector3<float>& vR = vA - vB;
		
		float vN = dot(vR, normalB);
		
//------------------Behandlung für colliding contact---------------------------------------
		if (vN <= 0.5)
		{	

//--------------------neue Behandlung aus Sphere kopiert-------------------------
			float vDoN = dot(velA, normalB);
			Vector3<float> vS = normalB * vDoN; 
		
			float fDoN = dot(forceA, normalB);
			Vector3<float> fS = normalB * fDoN;
			Vector3<float> force = part->getForce();
			force.normalize();
			if (dot (force, normalB) > 0 ){
				part->setVelocity(part->getVelocity() - vS);
				part->setVelocity(part->getVelocity() * 0.75);	// Wert: 0.75
				part->addForce((-1.0) * fS);
				part->setForce(part->getForce() * 0.75);	// Wert: 0.75
				part->setIsColliding(true);
			}
//------------------------------------------------------------------------------
			////berechnung der impuls-kraft in richtung normalB
			////float damping = (0.01f + box->getBounciness()) / 2.0f;
			//float damping = 0.12f;
			//float invMassA, invMassB = 0.0f;
			////Matrix<float> invTensorA(3,3);

			////Matrix<float> invTensorB = box->getInvWorldInertiaTensor();
		
			////test ob dynamisch
			//if(part->getIsDynamicFlag())
			//{	
			//	invMassA = part->getInvMass();
			//}
			//else 
			//	invMassA = 0.0;
			//
			//if(box->getRigidBody()->getIsDynamicFlag())
			//{	
			//	invMassB = box->getInvMass();
			//	//invTensorB = box->getRigidBody()->getInvWorldInertiaTensor();
			//}
			//else 
			//	invMassB = 0.0;
		
			//float fNum = -(/*1+*/damping)*(dot(normalB,(velocityA - velocityB)));
			//float fDenom = invMassA + invMassB;// + dot(crossA,uA)+dot(crossB,uB);

			//float impulseMagnitude = fNum / fDenom;

			//if (impulseMagnitude < 0){
			//Vector3<float> impulseForce = impulseMagnitude * normalB;

			///*impulseForce.normalize();
			//float vDoI = dot(velA, impulseForce);
			//float fDoI = dot(forceA, impulseForce);
			//Vec3 vS = impulseForce * vDoI;
			//Vec3 fS = impulseForce * fDoI;*/

			////part->setVelocity(part->getVelocity()[X], 0.0f, part->getVelocity()[Z]);
			////part->setVelocity(part->getVelocity() - vS);
			////part->addForce(fS);
			////setzen der linaren momente
			//if (part->getInvMass()!=0)
			//{
			//part->setVelocity(part->getVelocity() - impulseForce/invMassA);
			//part->setIsColliding(true);
			//}
			////part->setVelocity(part->getVelocity() + (impulseForce / invMassB));        
			//
			//}
		}
	}
	
}
void ParticleSystem::collide(ParticlePtr part, CapsulePtr caps)
{
    //part->setIsColliding(false);
	Vector3<float> unitV(0,1,0);
	Vector3<float> rV(qRotate(unitV, caps->getRigidBody()->getOrientation())); 

	Vector3<float> A1 = caps->getRigidBody()->getPosition()+(rV*(caps->getHeight()/2));
	Vector3<float> A2 = caps->getRigidBody()->getPosition()-(rV*(caps->getHeight()/2));
	Vec3 nullVector = Vec3(0.0,0.0,0.0);
	
	// teile des codes Copyright 2001, softSurfer (www.softsurfer.com)

	// alles geschummelt. Kugelzentrum als infinitisimal kleines Segment interpretiert.

	Vector3<float> smallNumberVector(0.1f,0.1f,0.1f);

	Vector3<float> B1 = part->getPosition() + smallNumberVector;
	Vector3<float> B2 = part->getPosition() - smallNumberVector;

	Vector3<float>   u = A2 - A1;
	Vector3<float>   v = B2 - B1;
	Vector3<float>   w = A1 - B1;
	float    a = dot(u,u);        // always >= 0
	float    b = dot(u,v);
	float    c = dot(v,v);        // always >= 0
	float    d = dot(u,w);
	float    e = dot(v,w);
	float    D = a*c - b*b;       // always >= 0
	float    sc, sN, sD = D;      // sc = sN / sD, default sD = D >= 0
	float    tc, tN, tD = D;      // tc = tN / tD, default tD = D >= 0

	// compute the line parameters of the two closest points
	if (D < 0.0000000001) { // the lines are almost parallel
		sN = 0.0;        // force using point P0 on segment S1
		sD = 1.0;        // to prevent possible division by 0.0 later
		tN = e;
		tD = c;
	}
	else {                // get the closest points on the infinite lines
		sN = (b*e - c*d);
		tN = (a*e - b*d);
		if (sN < 0.0) {       // sc < 0 => the s=0 edge is visible
			sN = 0.0;
			tN = e;
			tD = c;
		}
		else if (sN > sD) {  // sc > 1 => the s=1 edge is visible
			sN = sD;
			tN = e + b;
			tD = c;
		}
	}
	if (tN < 0.0) {           // tc < 0 => the t=0 edge is visible
		tN = 0.0;
		// recompute sc for this edge
		if (-d < 0.0)
			sN = 0.0;
		else if (-d > a)
			sN = sD;
		else {
			sN = -d;
			sD = a;
		}
	}
	else if (tN > tD) {      // tc > 1 => the t=1 edge is visible
		tN = tD;
		// recompute sc for this edge
		if ((-d + b) < 0.0)
			sN = 0;
		else if ((-d + b) > a)
			sN = sD;
		else {
			sN = (-d + b);
			sD = a;
		}
	}
	// finally do the division to get sc and tc
	if(fabs(sN) < 0.000000001)
		sc = 0.0;
	else
		sc = sN/sD;

	if(fabs(tN) < 0.0000000001)
		tc = 0.0;
	else
		tc = tN/tD;

	// get the difference of the two closest points
	Vector3<float>  dP = w + (sc * u) - (tc * v);  // = S1(sc) - S2(tc)

	float dist = dP.length();   // return the closest distance 
	float radParticle = 3.0f;	// 3.0f für Partikelradius
	//collision-behandlung
	if (dist < (caps->getRadius()) + radParticle) 
	{
		assert(dP.length() != 0.0);
		if (dP.length() != 0.0)
			dP.normalize();

		Vector3<float> normalB = dP ;
		Vector3<float> contactPoint = part->getPosition() + (radParticle * dP);

        Vector3<float> posOldToContact = contactPoint - (part->getPosition());

        //überprüfung der normalen, falls die capsule weiter als radius eingedrungen ist, umdrehen
        if (dot(posOldToContact, normalB)<0)
        {
            //cout << "Normale " << normalB << " von B=" << caps->getId() << " zeigt in die falsche Richtung !\n";
			normalB = -normalB;
        }
        else
        {
			// cout << "Normale " << normalB << " von B=" << caps->getId() << " zeigt in die richtige Richtung !\n";          
        }


		const Vector3<float>& rA = contactPoint - caps->getRigidBody()->getPosition();
		const Vector3<float>& aVelocityA = caps->getRigidBody()->getAngularVelocity();


		Vector3<float> velA = part->getVelocity();
		Vector3<float> forceA = part->getForce();
		

		const Vector3<float>& velocityB = part->getVelocity();
		const Vector3<float>& velocityA = caps->getRigidBody()->getVelocity() + cross(aVelocityA, rA);

		const Vector3<float>& vR = velocityA - velocityB;
		
		float vN = dot(vR, normalB);    

		//test auf colliding contact
		if (vN <= 0.03)	// Wert: 0.5
		{

			//Vector3<float> normale = -1 * part->getPosition() + caps->getPosition();
			//normalB.normalize();




//-----------Marke Eigenbau--------------------------------------------------------------------------------		
			//float vDoN = dot(velA, normalB);
			//Vector3<float> vS = normalB * vDoN; 
		
			//float fDoN = dot(forceA, normalB);
			//Vector3<float> fS = normalB * fDoN;
			//Vector3<float> force = part->getForce();
			////force.normalize();
			//if (dot (force, normalB) >= 0.0 ){
			//	part->setVelocity(part->getVelocity() - vS);
			//	part->setVelocity(part->getVelocity() * 0.75);	// Wert: 0.75
			//	part->addForce((-1) * fS);
			//	part->setForce(part->getForce() * 0.75);	// Wert: 0.75
			//	part->setIsColliding(true);
			//	}
			//
			//part->setVelocity(part->getVelocity() * vDoN);
			//part->setForce(part->getForce() * fDoN);


//------------Kopie aus Sphere--------------------------------------------------

		float vDoN = dot(velA, normalB);
		Vector3<float> vS = normalB * vDoN; 
		
		float fDoN = dot(forceA, normalB);
		Vector3<float> fS = normalB * fDoN;
		Vector3<float> force = part->getForce();
		if (force.length() != 0.0)
			force.normalize();
		if (dot (force, normalB) > 0 ){
			
			part->setVelocity(part->getVelocity() - vS);
			part->setVelocity(part->getVelocity() * 0.9f);	// Wert: 0.75
			part->setVelocity(part->getVelocity() + caps->getRigidBody()->getVelocity());
			part->addForce((-1.f) * fS);
			part->setForce(part->getForce() * 0.9f);	// Wert: 0.75
			//part->addForce(caps->getRigidBody()->getForce());
			part->setIsColliding(true);
			part->setIsCollidingWhere(1);
			
			
		}
		else if (dot (force, normalB) < 0){
			part->setVelocity(part->getVelocity() + vS);
			part->setVelocity(part->getVelocity() * 0.9f);	// Wert: 0.75
			part->setVelocity(part->getVelocity() + caps->getRigidBody()->getVelocity());
			part->addForce((1.f) * fS);
			part->setForce(part->getForce() * 0.9f);	// Wert: 0.75
			//part->addForce(caps->getRigidBody()->getForce());
			part->setIsColliding(true);
			part->setIsCollidingWhere(-1);
			}
//--------------------------neue Kollisionsbehandlung-------------------------------------------------------------
			/*	float damping = 1.0f; 
			//float damping = (0.1f + caps->getBounciness()) / 2.0f;
			
			float invMassA = caps->getInvMass();			
			float invMassB = part->getInvMass();//1.0f / part->getMass();
			Matrix<float> invTensorA = caps->getInvWorldInertiaTensor();
			
			
			const Vector3<float>& crossA = cross(rA,normalB);
			
			
			const Vector3<float>& uA = invTensorA * crossA;
			

 
//		fNum = damping *( -(1+(-0.5f)) * ....
			
			float fNum = damping*(-(1+0.0f)*(dot(normalB,(velocityA - velocityB)) + dot(aVelocityA,crossA)));
			float fDenom = invMassA + invMassB + dot(crossA,uA);
			float impulseMagnitude = fNum/fDenom;

//			if (impulseMagnitude > 0)
			{
			Vector3<float> impulseForce = impulseMagnitude * normalB; //impulseMagnitude * 2.0 * normalB
			
			if (part->getInvMass()!=0)
			// Velocity setzen
			part->setVelocity(part->getVelocity() - (impulseForce * invMassB));
			}*/
		}
//--------------------keine Ahnung was ist----------------------------------------------------
		/*
		if (vN > -1.5 && vN < 1.5){
				//Vector3<float> normale = -1 * part->getPosition() + caps->getPosition();
			normalB.normalize();
		
			float vDoN = dot(velA, normalB);
			Vector3<float> vS = normalB * vDoN; 
		
			float fDoN = dot(forceA, normalB);
			Vector3<float> fS = normalB * fDoN;
			Vector3<float> force = part->getForce();
			//force.normalize();
			if (dot (force, normalB) >= -0.5 ){
				part->setVelocity(part->getVelocity() - (vS * 1.2));
				//part->setVelocity(Vector3<float>(0.0,0.0,0.0));
				//part->setForce(Vector3<float>(0.0,0.01,0.0));
				
				part->addForce((-1.2) * fS);
				}*/
//---------------------------------------------------------------------------------------------------------
			/*vDoN *= 50;
			  fDoN *= 50;*/
			//part->setVelocity(part->getVelocity() * vDoN);
			//part->setForce(part->getForce() * fDoN);
		}
	}
/**
 * \brief fragt ab WO ein Particle kollidiert.(unterhalb oder oberhalb des RB)
 */
int ParticleSystem::isCollidingWhere(ParticlePtr particle){
	return particle->getIsCollidingWhere();
}
/**
 * \brief fragt ab ob Partikel kollidiert 
 */
bool ParticleSystem::isColliding(ParticlePtr particle){
	return particle->getIsColliding();
}
//-----------------------------------------------------------------------------
//---------Test Verlet----------------
void ParticleSystem::integrateVerletBaltman (double interval)
{

	// Iteratoren
	std::map<Id,  ParticlePtr >::iterator particleIterator;
	std::map<Id,  ParticlePtr >::iterator particleEnd;

	// aktuelle Werte
	ParticlePtr particle; // Partikel
	Vec3 position;                 // lineare Position (Verschiebung)
	Quaternion orientation;        // angulaere Position (Rotation als Quat)
	Vec3 velocity;                 // lineare Geschwindigkeit
	Vec3 velocityAngular;          // Winkelgeschwindigkeit
	Vec3 acceleration;             // lineare Beschleunigung
	Vec3 accelerationAngular;      // Winkelbeschleunigung
	Quaternion orientationDot;     // Ableitung der Orientierung nach der Zeit
	Quaternion orientationDotDot;  // 2. Ableitung der Orientierung nach der Zeit
	double dt = interval;          // Delta time
	double dt2 = interval * interval;  // Delta time squared
	particleEnd =  mParticleList.end ();

	// for all Particles
	for (	particleIterator = mParticleList.begin(); particleIterator != particleEnd; ++particleIterator) {

		particle = particleIterator->second;

		// Ueberspringe den RigidBody, wenn die isDynamic Flag false ist
		if (!(particle->getIsDynamicFlag())) {

			// Setze Kraft und Drehmoment Null
			//particle->setForce(Vector3<float>(0, 0, 0));
			//particle->setTorque(Vector3<float>(0, 0, 0));
			continue;
		}

		// Werte lesen
		position = particle->getPosition ();
		//orientation = particle->getOrientation ();
		velocity = particle->getVelocity ();
		//velocityAngular = particle->getAngularVelocity (); //Winkelgeschwindigkeit nicht benötigt bei Particle
		acceleration = particle->getAcceleration ();
		//accelerationAngular = particle->getAngularAcceleration ();//nicht benötigt bei Particle

		// Ableitungen der Orientierung
/*    orientationDot = 0.5 * Quaternion (velocityAngular) * orientation;
	  orientationDotDot = (0.5 * Quaternion(0.0, accelerationAngular [0],
	  accelerationAngular [1],
	  accelerationAngular [2]) *
	  orientation +
	  0.5 * Quaternion (0.0, velocityAngular [0],
	  velocityAngular [1],
	  velocityAngular [2]) *
	  orientationDot);

*/

/*
// Alternative
orientationDotDot = (0.5) *
Quaternion (-2.0 * dot (orientationDot, orientationDot),
accelerationAngular [0],
accelerationAngular [1],
accelerationAngular [2]) *
orientation;
*/
				
		// Linear Update
		position += ((float)dt * velocity + 0.5f * (float)dt2 * acceleration);
		velocity += ((float)dt * acceleration);

		// Angular Update
		//orientation += (dt * orientationDot + 0.5 * dt2 * orientationDotDot);
		//velocityAngular += (dt * accelerationAngular);
		//orientation.normalize();

		if (SimonState::exemplar()->getViscosityFlag()) {
			velocity *= SimonState::exemplar()->getViscositySlowdownLinear();
			//velocityAngular *= mViscositySlowdownAngular;
		}
		
		// Zurueckschreiben der Werte
		particle->setPosition (position);
		//particle->setOrientation (orientation);
		particle->setVelocity (velocity);
		//particle->setAngularVelocity (velocityAngular);

		// Setzen von Kraft und Drehmoment auf Null
		particle->setForce(Vector3<float>(0, 0, 0));
		//particle->setTorque(Vector3<float>(0, 0, 0));//nicht nötig bei Particle

	}
}
Esempio n. 16
0
    //
    // RenderRallyPoint
    //
    // Display a rally point
    //
    static void RenderRallyPoint()
    {
      Point<S32> srcPoint(0, 0);
      Point<U32> dstPoint(0, 0);
      Matrix src, dst;

      // Get the single selected unit
      UnitObj *unit = data.cInfo.oneUnit.GetPointer();

      // Is there a rally point
      if (unit && unit->GetFootInstance() && unit->GetRallyPoint(dstPoint))
      {
        // Setup destination
        dst.ClearData();
        dst.posit.x = WorldCtrl::CellToMetresX(dstPoint.x);
        dst.posit.z = WorldCtrl::CellToMetresZ(dstPoint.z);
        dst.posit.y = TerrainData::FindFloorWithWater(dst.posit.x, dst.posit.z);

        // Find the source
        srcPoint.Set(S32(dstPoint.x), S32(dstPoint.z));
        unit->GetFootInstance()->ClampToFringe(srcPoint);
        src.ClearData();
        src.posit.x = WorldCtrl::CellToMetresX(srcPoint.x);
        src.posit.z = WorldCtrl::CellToMetresZ(srcPoint.z);
        src.posit.y = TerrainData::FindFloorWithWater(src.posit.x, src.posit.z);
      }
      else
      {
        // Act as if not selected
        unit = NULL;
      }

      if 
      (
        // Rally unit has been deselected
        (!unit && rallyUnitId) 
        
        || 
        
        (
          // Have a rally point unit
          unit 
          
          && 
          
          (
            // Different to last one
            (unit->Id() != rallyUnitId) 
            
            || 
            
            // Rally point location has changed
            (rallyUnitId && (dstPoint != rallyPoint))
          )
        )
      )
      {
        // Dispose of any current particle
        if (rallyParticle.Alive())
        {
          delete rallyParticle;
        }

        // Is there a unit selected
        if (unit)
        {
          // Never display a trail when same point
          if ((srcPoint.x != S32(dstPoint.x)) || (srcPoint.z != S32(dstPoint.z)))
          {
            // Create the runner particle
            if (ParticleClass *p = ParticleSystem::FindType(0x94E362BD)) // "Client::Rally"
            {
              Matrix m(src);
              m.posit.y += 3.0F;
			        Vector v(0.0f, 0.0f, 0.0f);
              rallyParticle = ParticleSystem::New(p, m, v, v, dst.posit - src.posit, 0.0F);
            }
          }

          // Remember this unit's info
          rallyUnitId = unit->Id();
          rallyPoint = dstPoint;
        }
        else
        {
          rallyUnitId = 0;
        }
      }

      // Render the start and end points
      if (unit)
      {     
        Common::Display::Mesh(0x693D5359, src, Color(0.0F, 0.8F, 0.0F, 0.7F)); // "Location"
        Common::Display::Mesh(0x693D5359, dst, Color(0.0F, 1.0F, 0.0F, 0.7F)); // "Location"
      }
    }
Esempio n. 17
0
  namespace Display
  {

    // Multiplayer markers
    NBinTree<PlayerMarker> markers(&PlayerMarker::node);

    // Selection box skin
    TextureSkin *selectionSkin;

    // FootPrint placement display
    static Common::Display::PlacementDeform placeDeform;

    // Id of unit currently displaying a rally point
    static U32 rallyUnitId;

    // Rally point runner particle
    static ParticlePtr rallyParticle;

    // Rally point location
    static Point<U32> rallyPoint;


    //
    // RenderSpecialized
    //
    // Display specialized unit information
    //
    static void RenderSpecialized()
    {
      // Is there a unit under the cursor
      UnitObj *over = data.cInfo.gameWnd.Alive() ? data.cInfo.o.unit.GetPointer() : NULL;

      // Can we see this units special info
      if (over && Team::TestDisplayRelation(over, Relation::ALLY))
      {
        over->RenderSpecialized();
      }

      // Now display for all selected units
      for (UnitObjList::Iterator i(&data.sList); *i; ++i)
      {
        if (UnitObj *u = (*i)->GetPointer())
        {
          if (u != over)
          {
            u->RenderSpecialized();
          }
        }
      }
    }


    //
    // RenderRallyPoint
    //
    // Display a rally point
    //
    static void RenderRallyPoint()
    {
      Point<S32> srcPoint(0, 0);
      Point<U32> dstPoint(0, 0);
      Matrix src, dst;

      // Get the single selected unit
      UnitObj *unit = data.cInfo.oneUnit.GetPointer();

      // Is there a rally point
      if (unit && unit->GetFootInstance() && unit->GetRallyPoint(dstPoint))
      {
        // Setup destination
        dst.ClearData();
        dst.posit.x = WorldCtrl::CellToMetresX(dstPoint.x);
        dst.posit.z = WorldCtrl::CellToMetresZ(dstPoint.z);
        dst.posit.y = TerrainData::FindFloorWithWater(dst.posit.x, dst.posit.z);

        // Find the source
        srcPoint.Set(S32(dstPoint.x), S32(dstPoint.z));
        unit->GetFootInstance()->ClampToFringe(srcPoint);
        src.ClearData();
        src.posit.x = WorldCtrl::CellToMetresX(srcPoint.x);
        src.posit.z = WorldCtrl::CellToMetresZ(srcPoint.z);
        src.posit.y = TerrainData::FindFloorWithWater(src.posit.x, src.posit.z);
      }
      else
      {
        // Act as if not selected
        unit = NULL;
      }

      if 
      (
        // Rally unit has been deselected
        (!unit && rallyUnitId) 
        
        || 
        
        (
          // Have a rally point unit
          unit 
          
          && 
          
          (
            // Different to last one
            (unit->Id() != rallyUnitId) 
            
            || 
            
            // Rally point location has changed
            (rallyUnitId && (dstPoint != rallyPoint))
          )
        )
      )
      {
        // Dispose of any current particle
        if (rallyParticle.Alive())
        {
          delete rallyParticle;
        }

        // Is there a unit selected
        if (unit)
        {
          // Never display a trail when same point
          if ((srcPoint.x != S32(dstPoint.x)) || (srcPoint.z != S32(dstPoint.z)))
          {
            // Create the runner particle
            if (ParticleClass *p = ParticleSystem::FindType(0x94E362BD)) // "Client::Rally"
            {
              Matrix m(src);
              m.posit.y += 3.0F;
			        Vector v(0.0f, 0.0f, 0.0f);
              rallyParticle = ParticleSystem::New(p, m, v, v, dst.posit - src.posit, 0.0F);
            }
          }

          // Remember this unit's info
          rallyUnitId = unit->Id();
          rallyPoint = dstPoint;
        }
        else
        {
          rallyUnitId = 0;
        }
      }

      // Render the start and end points
      if (unit)
      {     
        Common::Display::Mesh(0x693D5359, src, Color(0.0F, 0.8F, 0.0F, 0.7F)); // "Location"
        Common::Display::Mesh(0x693D5359, dst, Color(0.0F, 1.0F, 0.0F, 0.7F)); // "Location"
      }
    }


    //
    // RenderCurrentRegion
    //
    // Display currently selected region
    //
    static void RenderCurrentRegion()
    {
      if (data.paintRegion.Alive())
      {
        Common::Display::MarkAreaMetre(data.paintRegion->GetArea());
      } 
    }


    //
    // RenderFootPrint
    //
    // Render an object placement footprint
    //
    static void RenderFootPrint(Bool deform)
    {
      // Grab a shortcut
      CycleInfo &i = data.cInfo;

      // Are we placing a footprint
      if (i.gameWnd.Alive() && (i.pEvent == PE_CONSTRUCT || i.pEvent == PE_NOCONSTRUCT))
      {
        ASSERT(data.constructType.Alive())
        ASSERT(i.t.cell)

        // Does object have a footprint
        FootPrint::Type *foot = data.constructType->GetFootPrintType();

        // Equality check because type was changed on console during dev
        if (foot && (foot == &data.placeFoot.GetType()))
        {
          if (deform)
          {
            Common::Display::FootPrintPlacementDeform(data.placeFoot, placeDeform, TRUE, &data.placeLocation, data.clientAlpha.GetValue());
          }
          else
          {
            Common::Display::FootPrintPlacement(data.placeFoot, TRUE, &data.placeLocation, data.clientAlpha.GetValue());
          }
        }

        if (i.pEvent == PE_CONSTRUCT)
        {
          // Is this type a wall
          if (WallObjType *wallType = Promote::Type<WallObjType>(data.constructType))
          {
            wallType->DisplayAvailableLinks(i.t.pos);
          }
        }
      }
    }


    //
    // RenderFormation
    //
    // Render the formation mesh
    //
    static void RenderFormation()
    {
      // Grab a shortcut
      CycleInfo &i = data.cInfo;

      // Are we placing a formation
      if (i.gameWnd.Alive() && (i.pEvent == PE_FORMATION))
      {
        Vector pos;
        pos.x = data.cInfo.t.pos.x;
        pos.z = data.cInfo.t.pos.z;
        pos.y = TerrainData::FindFloor(pos.x, pos.z) + 2.0f;
        Matrix m;
        WorldCtrl::SetupWorldMatrix(m, pos, data.dir);

        Common::Display::Mesh(0x7223612A, m); // , Color(1.0f, 1.0f, 1.0f)); // "Formation"
      }
    }


    //
    // RenderSelectionBox
    //
    static void RenderSelectionBox(const Area<S32> &rect)
    {
      if (selectionSkin)
      {
        // Setup paintinfo
        PaintInfo pi(selectionSkin->states[ColorGroup::NORMAL].colors);
        pi.client = pi.window = rect;

        selectionSkin->Render(pi, ColorGroup::NORMAL);
      }
      else
      {
        IFace::RenderRectangle(rect, Common::Display::GroupSelectColor());
      }
    }


    //
    // RenderPlayerMarkers
    //
    static void RenderPlayerMarkers()
    {
      Matrix m = Matrix::I;

      for (NBinTree<PlayerMarker>::Iterator i(&markers); *i; i++)
      {
        PlayerMarker *p = *i;

        // allowed to see it
        if (p->canSee)
        {
          m.posit.x = WorldCtrl::CellToMetresX(p->cx);
          m.posit.z = WorldCtrl::CellToMetresZ(p->cz);
          m.posit.y = TerrainData::FindFloorWithWater(m.posit.x, m.posit.z);

          p->pos = m.posit;

          // "Location"
          Common::Display::Mesh(0x693D5359, m, p->player->GetTeam()->GetColor());
        }
      }
    }


    //
    // PreRender
    //
    // Pre-render processing
    //
    void PreRender()
    {
      // Update the current camera
      Viewer::Simulate();
      Viewer::Render(0xF530E366); // "Render::PreRender"

      /*
      // Get the camera matrix
      const Matrix &m = Vid::CurCamera().WorldMatrix();

      // Update the 3D listener position
      Sound::Digital::UpdateListener
      (
        m.front.x, m.front.y, m.front.z, m.up.x, m.up.y, m.up.z
      );
      */

      // Update pulsating alpha
      data.clientAlpha.Simulate(Main::ElapTimeFrame());
    }


    //
    // PreTerrain
    //
    // Rendering before terrain is drawn
    //
    void PreTerrain()
    {
      // Render an object placement footprint
      if (Common::Debug::data.footDeform)
      {
        RenderFootPrint(TRUE);
      }
    }


    //
    // Render
    //
    // Client specific rendering
    //
    void Render()
    {
      // Display a region
      RenderCurrentRegion();

      // Render an object placement footprint
      if (!Common::Debug::data.footDeform)
      {
        RenderFootPrint(FALSE);
      }

      // Render specialized unit information
      RenderSpecialized();

      // Display a rally point
      RenderRallyPoint();

      // Render formation placement
      RenderFormation();

      // Render trails
      Trail::Render();

      // Render player markers
      RenderPlayerMarkers();

      // Viewer rendering
      Viewer::Render(0xEF30A860); // "Render::PostObject"

      // Display debug information
      #ifdef DEVELOPMENT

        Debug::Render();

      #endif

      // Render interface
      if (!IFace::GetFlag(IFace::DISABLE_DRAW))
      {
        IFace::InitRender();

        // Display the current group selection box on top of main game window
        if (data.selectMode == SM_PREDRAW)
        {
          RenderSelectionBox(data.mouseRect);
        }

        // Render HUD
        HUD::Render();
        
        // Render main portion of interface
        IFace::CallRenderProc();

        // Render any other systems that require iface
        Viewer::Render(0xCEEF613F); // "Render::PostIFace1"
        Viewer::Render(0xC3AC47E6); // "Render::PostIFace2"

        // Display the current group selection box on top of map window
        if (data.selectMode == SM_POSTDRAW)
        {
          RenderSelectionBox(data.mouseRect);
        }

        // Display status icons last
        if (!Viewer::Action::IsPlaying())
        {
          ClipRect screenRect = IFace::RootWindow()->GetPaintInfo().window;

          if (GameTime::IsFallingBehind())
          {
            Client::HUD::RenderStatusIcon(0x267B119C, screenRect); // "FallingBehind"
          }

          if (GameTime::IsDroppingFrames())
          {
            Client::HUD::RenderStatusIcon(0xF144EDC2, screenRect); // "DroppingFrames"
          }

          if (GameTime::IsStalled())
          {
            Client::HUD::RenderStatusIcon(0x540B86C8, screenRect); // "NetworkLag"
          }
        }

        IFace::DoneRender();
      }
    }


    //
    // PostRender
    //
    // Called after rendering is finished
    //
    void PostRender()
    {
      Common::Display::PostFootPrintPlacementDeform(placeDeform);
    }

  
    //
    // Init
    //
    // Initialize this sub-system
    //
    void Init()
    {
      // Clear the region reaper
      data.paintRegion = NULL;

      // Clear local data
      placeDeform.Init();
      rallyUnitId = 0;
      rallyParticle = NULL;
      selectionSkin = NULL;
    }


    //
    // Done
    //
    // Shutdown this sub-system
    //
    void Done()
    {
      selectionSkin = NULL;
      markers.DisposeAll();
    }


    //
    // SetPlayerMarker
    //
    void SetPlayerMarker(const Player *player, S32 cx, S32 cz)
    {
      ASSERT(player)
      ASSERT(WorldCtrl::CellOnMap(cx, cz))

      PlayerMarker *marker;

      if ((marker = markers.Find(player->GetId())) == NULL)
      {
        marker = new PlayerMarker;
        marker->player = player;
        marker->canSee = Team::TestRelation(Team::GetDisplayTeam(), player->GetTeam(), Relation::ALLY) ? TRUE : FALSE;

        markers.Add(player->GetId(), marker);
      }

      marker->cx = cx;
      marker->cz = cz;
    }


    //
    // ClearPlayerMarker
    //
    void ClearPlayerMarker(const Player *player)
    {
      PlayerMarker *marker;

      if ((marker = markers.Find(player->GetId())) != NULL)
      {
        markers.Dispose(marker);
      }
    }
  }
void ParticleSystem::collide(ParticlePtr part, SpherePtr sphere)
{
	
	Vector3<float> distance = part->getPosition() - sphere->getRigidBody()->getPosition();
    float radiusSum = sphere->getRadius();
    
    //test auf collision
	if (distance.length() <= radiusSum)	// sonst nur radiusSum
    {
        //berechnung normalB und contactPoint
		distance.normalize();
        const Vector3<float>& normalB = distance;
        //const Vector3<float>& contactPoint = part->getPosition(); //+ 0.01f * normalB;
      
		// folgender Abschnitt aus: 
		// CollisionSystem::collisionResponse(part, sphere, contactPoint, normalB);

		//berechnung der relativen geschwindigkeit in richtung normalB
		const Vector3<float>& velocityA = part->getVelocity();
		const Vector3<float>& velocityB = sphere->getRigidBody()->getVelocity();
		Vector3<float> velA = part->getVelocity();
		Vector3<float> forceA = part->getForce();
		Vector3<float> velB = sphere->getRigidBody()->getVelocity();
		Vector3<float> forceB = sphere->getRigidBody()->getForce();
		
		const Vector3<float>& vR = velocityA - velocityB;
		float vN = dot(vR, normalB);		

		//behandlung für colliding contact
		if (vN <= 0.5)
		{
			//Kraftberechnung für Resting Contact
//Todo
//--------------bisherige Behandlung----------------------------------------------
			
			Vector3<float> normale = -1 * part->getPosition() + 
				sphere->getRigidBody()->getPosition();
			normale.normalize();
		
			float vADoN = dot(velA, normale);
			Vector3<float> vS = normale * vADoN; 
			
			float fADoN = dot(forceA, normale);
			Vector3<float> fS = normale * fADoN;

			float vBDoN = dot (velA, normale);
			Vector3<float> vS2 = normale * vBDoN;
				
			float fBDoN = dot (forceB, normale);
			Vector3<float> fS2 = normale * fBDoN;

			Vec3 nullvector = Vec3(0.0,0.0,0.0);
			Vector3<float> force = part->getForce();
			force.normalize();
			if (dot (force, normale) > 0 ){
				part->setVelocity(part->getVelocity() - vS);
				part->setVelocity(part->getVelocity() * 0.9f);	// Wert: 0.75
				part->setVelocity(part->getVelocity() + sphere->getRigidBody()->getVelocity());
				part->addForce((-1.f) * fS);
				part->setForce(part->getForce() * 0.9f);	// Wert: 0.75
				part->addForce(sphere->getRigidBody()->getForce());
				
				if (!(sphere->getRigidBody()->getVelocity() == Vec3(0.0,0.0,0.0))){
					sphere->getRigidBody()->addForce((-0.02f) * fS2);
					sphere->getRigidBody()->
						setVelocity(sphere->getRigidBody()->getVelocity() - 
									(vS2 * 0.02f));
				}
				
				part->setIsColliding(true);
			}else if (dot (force, normale) < 0){
				part->setVelocity(part->getVelocity() + vS);
				part->setVelocity(part->getVelocity() * 0.9f);	// Wert: 0.75
				part->setVelocity(part->getVelocity() + 
								  sphere->getRigidBody()->getVelocity());
				part->addForce((1.0) * fS);
				part->setForce(part->getForce() * 0.9f);	// Wert: 0.75
				part->addForce(sphere->getRigidBody()->getForce());
				
				if (!(sphere->getRigidBody()->getVelocity() == Vec3(0.0,0.0,0.0))){
					sphere->getRigidBody()->addForce((-0.02f) * fS2);
					sphere->getRigidBody()
						->setVelocity(sphere->getRigidBody()->getVelocity() - 
									  (vS2 * 0.02f));
				}
				
			}

		
//----------------alte Behandlung-------------------------------------------------
			//berechnung der impuls-kraft in richtung normalB
/*		float damping = 0.5f; //(0.6 + sphere->getBounciness()) / 2.0;
  float invMassA, invMassB = 0.0;
  Matrix<float> invTensorA(3,3);
  Matrix<float> invTensorB(3,3);
  Vec3 rA = part->getForce();
  Vec3 rB = sphere->getRigidBody()->getForce();
  //test ob dynamisch
  if(part->getIsDynamicFlag())
  {	
  invMassA = 1.0f / part->getMass();
  }
  else 
  invMassA = 0.0;

  if(sphere->getRigidBody()->getIsDynamicFlag())
  {	
  invMassB = 1.0f / sphere->getMass();
  invTensorB = sphere->getRigidBody()->getInvWorldInertiaTensor();
  }
  else 
  invMassB = 0.0;
		
  const Vector3<float>& crossA = cross(rA,normalB);
  const Vector3<float>& crossB = cross(rB,normalB);

  const Vector3<float>& uA = invTensorA * crossA;
  const Vector3<float>& uB = invTensorB * crossB;

  float fNum = -(1+damping)*(dot(normalB,(velocityA - velocityB)));
  float fDenom = invMassA + invMassB + dot(crossA,uA)+dot(crossB,uB);

  float f = fNum / fDenom;
		
  Vector3<float> impulseForce = 9.5 * f * normalB;
		
  //jetzt:
  part->setVelocity(part->getVelocity() + impulseForce/part->getMass());
*/
//----------neue Behandlung-------------------------------------------------------		 	
		
			////berechnung der impuls-kraft in richtung normalB
			//float damping = 0.1f;
			//float invMassA = part->getInvMass();
			//	float invMassB = sphere->getInvMass();
			// 
			//    // calculate impulse
			//float fNum = -(/*1+*/damping)*(dot(normalB,(velocityB - velocityA)));
			//float fDenom = invMassA + invMassB;
			//
			//float impulseMagnitude = fNum / fDenom;

			//if (impulseMagnitude < 0){

			//Vector3<float> impulseForce = impulseMagnitude * normalB;
			//                                   
			//if (part->getInvMass()!=0)
			//	part->setVelocity(part->getVelocity() - (impulseForce/invMassA));
			//
			//if (sphere->getInvMass()!=0)
			//	sphere->setVelocity(sphere->getVelocity() - (impulseForce * invMassB));
			//}
//--------------------------------------------------------------------------------
		}
	}
}