예제 #1
0
bool CollisionDetector::CylinderSphereCollision(PhysicsNode& p0, PhysicsNode& p1, CollisionData* data) {
	CollisionCylinder& cylinder = *(CollisionCylinder*)p0.GetCollisionVolume();
	CollisionSphere& sphere = *(CollisionSphere*)p1.GetCollisionVolume();

	Vector3 cylCenterVector = cylinder.GetEnd() - cylinder.GetStart();

	Vector3 pos1 = p1.GetPosition() - cylinder.GetStart();

	float distanceFactorFromEP1 = Vector3::Dot(p1.GetPosition() - cylinder.GetStart(), cylCenterVector) / Vector3::Dot(cylCenterVector, cylCenterVector);
	if(distanceFactorFromEP1 < 0) distanceFactorFromEP1 = 0;// clamp to endpoints if neccesary
	if(distanceFactorFromEP1 > 1) distanceFactorFromEP1 = 1;
	Vector3 closestPoint = cylinder.GetStart() + (cylCenterVector * distanceFactorFromEP1);

	Vector3 collisionVector = p1.GetPosition() - closestPoint;
	float distance = collisionVector.Length();
	Vector3 collisionNormal = collisionVector / distance;

	if(distance < sphere.GetRadius() + cylinder.GetRadius())
	{
	  //collision occurred. use collisionNormal to reflect sphere off cyl

		float factor = Vector3::Dot(p1.GetLinearVelocity(), collisionNormal);

		p1.SetLinearVelocity(p1.GetLinearVelocity() - (collisionNormal * factor * 0.8f));

		const float distSq = LengthSq(collisionNormal);

		//get the max distance before collision
		const float sumRadius = sphere.GetRadius() + cylinder.GetRadius();

		p1.SetPosition(p1.GetPosition() + Vector3(collisionNormal * (sumRadius - sqrtf(distSq))));
		return true;
	}
	return false;
}
예제 #2
0
void TerrainClass::BuildFloorEntity() {
	for (int i = 0; i < ChunckManager::NUM_VOXEL_CHUNCKS; i++) {
		SceneNode* sNode = new SceneNode();
		sNode->SetMesh(terrain->getMeshAt(i));
		sNode->SetModelScale(Vector3(SCALE_TERRAIN, SCALE_TERRAIN, SCALE_TERRAIN));

		PhysicsNode* pNode = new PhysicsNode();
		pNode->SetPosition(START_TERRAIN_POSITION);
		pNode->SetLinearVelocity(Vector3(0, 0, linearVelocityZ));
		pNode->setLD(false);
		pNode->setSkyBox(true);
		terrainPhysicsNodes.push_back(pNode);
		countTerrainEntities++;

		GameEntity* geFirst = new GameEntity(sNode, pNode);
		geFirst->ConnectToSystems();
		terrainEntities.push_back(geFirst);

		//add the id of the chunck just created
		//terrainChuncksId.push_back(geFirst->getId());
		//reset the chunck id to be the same as the entity added; for consistency purposes
		//terrain->getChunckAt(i)->setId(i);
	}
}
예제 #3
0
void CollisionDetector::AddCollisionImpulse(PhysicsNode &p0, PhysicsNode &p1, CollisionData &data) {

	// if neither objects have mass
	if(p0.GetInverseMass() + p1.GetInverseMass() == 0.0f) {
		return;
	}

	Vector3 r0 = data.m_point - p0.GetPosition();
	Vector3 r1 = data.m_point - p1.GetPosition();

	//get velocities
	Vector3 v0 = p0.GetLinearVelocity() + Vector3::Cross(p0.GetAngularVelocity(), r0);
	Vector3 v1 = p1.GetLinearVelocity() + Vector3::Cross(p1.GetAngularVelocity(), r1);
	Vector3 dv = v0 - v1;

	float relMov = -Vector3::Dot(dv, data.m_normal);

	//if(relMov < -0.01f) return;
	
	{
		float e = 0.0f;
		float normDiv = (p0.GetInverseMass() + p1.GetInverseMass()) + Vector3::Dot(data.m_normal, Vector3::Cross(p0.GetInverseInertia()
		* Vector3::Cross(r0, data.m_normal), r0) + Vector3::Cross(p1.GetInverseInertia() * Vector3::Cross(r1, data.m_normal), r1));
		float jn = -1 * (1+e) * Vector3::Dot(dv, data.m_normal) / normDiv;

		jn = jn + (data.m_penetration * 0.1f);

		//set p0's velocity
		Vector3 l0 = p0.GetLinearVelocity() + data.m_normal * (jn * p0.GetInverseMass());
		p0.SetLinearVelocity(l0);

		//set p0's rotation velocity
		Vector3 a0 = p0.GetAngularVelocity() + p0.GetInverseInertia() * Vector3::Cross(r0, data.m_normal * jn);
		p0.SetAngularVelocity(a0);

		//set p1's velocity
		Vector3 l1 = p1.GetLinearVelocity() - data.m_normal * ( jn * p1.GetInverseMass());
		p1.SetLinearVelocity(l1);

		//set p1's rotation velocity
		Vector3 a1 = p1 . GetAngularVelocity () - p1.GetInverseInertia() * Vector3::Cross(r1, data.m_normal * jn);
		p1.SetAngularVelocity(a1);
	}

	//if (false)
	{
		Vector3 tangent = dv - data.m_normal * Vector3::Dot(dv, data.m_normal);
		tangent.Normalise();
		float tangDiv = (p0.GetInverseMass() + p1.GetInverseMass()) + Vector3::Dot(tangent, Vector3::Cross(p0.GetInverseInertia() * Vector3::Cross(r0,
		tangent),r0) + Vector3::Cross(p1.GetInverseInertia() * Vector3::Cross(r1, tangent), r1));

		float jt = -1 * Vector3::Dot(dv, tangent) / tangDiv;

		Vector3 l0 = p0.GetLinearVelocity() + tangent * (jt * p0.GetInverseMass());
		//p0.SetLinearVelocity(l0);

		Vector3 a0 = p0.GetAngularVelocity() + p0.GetInverseInertia() * Vector3::Cross(r0, tangent * jt);
		p0.SetAngularVelocity(a0);

		Vector3 l1 = p1.GetLinearVelocity() - tangent * (jt * p1.GetInverseMass());
		//p1.SetLinearVelocity(l1);

		Vector3 a1 = p1.GetAngularVelocity() - p1.GetInverseInertia() * Vector3::Cross(r1, tangent * jt);
		p1.SetAngularVelocity(a1);
	}
}