//---------------------------------------------------------------------------------------------------------------------------------------------------
//
// Copyright (C)2007 DarkWynter Studios. All rights reserved.
//
//---------------------------------------------------------------------------------------------------------------------------------------------------
// {Contact : darkwynter.com for licensing information
//---------------------------------------------------------------------------------------------------------------------------------------------------
#region Comments
/*
* We'll need to interface Collision when we do gpgpu collision
* This way we can call either cpu or gpu configurations dependent on machine caps
*
* This will also provide us a clean break for a dll
*
*
*/
#endregion
namespace DarkWynter.Engine.Physics
{
#region Using Statements
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Globals;
using ObjectLib;
using GameObjects;
#endregion
///
/// Main class where all of our object collisions are handled place
///
public class Collision
{
#region Attributes:
private Vector3 tangentialComponent = new Vector3();
private Vector3 normalComponent = new Vector3();
private Vector3 normalForce1, normalForce2; // Stores each object's normal force component
private float timeInterval;
#endregion
#region Methods
///
/// Constructor:
///
public Collision() { }
///
/// Calls all the Collision functions in order
///
/// ObjectLibrary
/// List of dynamic mass objects
public void UpdateCollision(ref ObjectLibrary objectLibrary, List dynamicMasses)
{
timeInterval = Statics_Engine.SystemSettings.dt;
List newDynamicObject = new List();
//List dynamicMasses = Statics.lookupMap.GetDynamicList();
bool deletedDynamic = false;
LinkedList collidingObjects = new LinkedList();
// Statics.lookupMap.GetCollisionObjects(dynamicMasses[i]);
for (int i = 0; i < dynamicMasses.Count; i++)
{
collidingObjects.AddLast(new LinkedListNode(dynamicMasses[i]));
}
// For each moving GameObject
for (int i = 0; i < dynamicMasses.Count; i++)
{
// For each object in the vicinity of the gameObject
LinkedListNode node = collidingObjects.First;
if (collidingObjects.Count != 0 && dynamicMasses[i].gameObjectPointer != null)
{
Mass cMass;
do
{
cMass = node.Value;
// If not already checked
if (!cMass.collisionChecked && cMass.gameObjectPointer != null)
{
// If collided
if (dynamicMasses[i].boundingVolume.Intersects(cMass.boundingVolume) &&
dynamicMasses[i] != cMass)
{
Enums_Engine.CollisionCleanup cleanup = ObjectObjectCollision(dynamicMasses[i], cMass, objectLibrary);
Mass removeMass;
if (cleanup == Enums_Engine.CollisionCleanup.NONE)
{
// Mark that object has been checked for collisions
dynamicMasses[i].collisionChecked = true;
}
else if (cleanup == Enums_Engine.CollisionCleanup.REMOVEMASS1)
{
// We have to remove dynamicMasses[i], it has been absorbed or destroyed
removeMass = dynamicMasses[i];
dynamicMasses.Remove(removeMass);
collidingObjects.Remove(removeMass);
// Remove from Object Library
objectLibrary.RemoveGameObject(removeMass.gameObjectPointer);
// Reset Mass for Darkmatter List
removeMass.ClearValues();
removeMass.deadObject = true;
deletedDynamic = true;
break;
}
else if (cleanup == Enums_Engine.CollisionCleanup.REMOVEMASS2)
{
// cMass has to be removed, it has been absorbed or destroyed
removeMass = cMass;
dynamicMasses.Remove(removeMass);
collidingObjects.Remove(removeMass);
// Remove from Object Library
objectLibrary.RemoveGameObject(removeMass.gameObjectPointer);
// Reset Mass for Darkmatter List
removeMass.ClearValues();
removeMass.deadObject = true;
}
else if (cleanup == Enums_Engine.CollisionCleanup.REMOVEBOTH)
{
// cMass has to be removed, it has been absorbed or destroyed
removeMass = cMass;
dynamicMasses.Remove(removeMass);
collidingObjects.Remove(removeMass);
// Remove from Object Library
objectLibrary.RemoveGameObject(removeMass.gameObjectPointer);
// Reset Mass for Darkmatter List
removeMass.ClearValues();
removeMass.deadObject = true;
// We have to remove dynamicMasses[i], it has been absorbed or destroyed
removeMass = dynamicMasses[i];
dynamicMasses.Remove(removeMass);
collidingObjects.Remove(removeMass);
// Remove from Object Library
objectLibrary.RemoveGameObject(removeMass.gameObjectPointer);
// Reset Mass for Darkmatter List
removeMass.ClearValues();
removeMass.deadObject = true;
deletedDynamic = true;
break;
}
}
#region Old Code
/*
//// Cohesion
//if (dynamicMasses[i].objectType == Enums_Engine.ObjectType.PARTICLE && cMass.objectType == Enums_Engine.ObjectType.PARTICLE)
//{
// // Particle Interaction
// if (ParticleInteraction(dynamicMasses[i], cMass))
// {
// if (i < dynamicMasses.Count)
// {
// deletedDynamic = true;
// ObjectTerrainCollision(dynamicMasses[i], (int)dynamicMasses[i].objectHeight, objectLibrary.terrain);
// i--;
// }
// else
// {
// i--;
// ObjectTerrainCollision(dynamicMasses[i], (int)dynamicMasses[i].objectHeight, objectLibrary.terrain);
// }
// break;
// }
//}
// Collectable Objects
if (dynamicMasses[i].objectType == Enums_Engine.ObjectType.PLAYER && cMass.gameObjectPointer.isCollectable)
{
// Increment Number of Keys found
Player player = (Player)dynamicMasses[i].gameObjectPointer;
if (player.IsHuman())
{
Audio.KeyFound();
if (Statics.GameSettings.gameType == Enums_Game.GameType.STORY_MODE)
{
player.numberOfKeysFound++;
}
player.ChangeHealth(Statics.GameSettings.HEALTH_BOOST_FOR_KEY, objectLibrary);
Statics.lookupMap.RemoveLast(cMass);
Statics.lookupMap.RemoveCurrent(cMass);
//if (Statics.lookupMap.DynamicContains(cMass))
//{
// Statics.lookupMap.RemoveDynamic(cMass);
//}
//if (newDynamicObject.Contains(cMass))
//{
// newDynamicObject.Remove(cMass);
//}
cMass.ClearValues();
cMass.deadObject = true;
((Human)player).ShowKeyIndicator();
}
}
else if (dynamicMasses[i].gameObjectPointer.isCollectable && cMass.objectType == Enums_Engine.ObjectType.PLAYER)
{
// Increment Number of Keys found
Player player = (Player)cMass.gameObjectPointer;
if (player.IsHuman())
{
Audio.KeyFound();
if (Statics.GameSettings.gameType == Enums_Game.GameType.STORY_MODE)
{
player.numberOfKeysFound++;
}
player.ChangeHealth(Statics.GameSettings.HEALTH_BOOST_FOR_KEY, objectLibrary);
Statics.lookupMap.RemoveLast(dynamicMasses[i]);
Statics.lookupMap.RemoveCurrent(dynamicMasses[i]);
if (Statics.lookupMap.DynamicContains(dynamicMasses[i]))
{
Statics.lookupMap.RemoveDynamic(dynamicMasses[i]);
}
dynamicMasses[i].ClearValues();
dynamicMasses[i].deadObject = true;
((Human)player).ShowKeyIndicator();
// Remove Collectable from list and give to player
if (i < dynamicMasses.Count)
{
deletedDynamic = true;
i--;
}
else
{
i--;
}
break;
}
}
else
{
// Handle collision physics
ObjectObjectCollision(dynamicMasses[i], cMass);
if ((dynamicMasses[i].objectType == Enums_Engine.ObjectType.PLAYER && cMass.objectType == Enums_Engine.ObjectType.PARTICLE) ||
(dynamicMasses[i].objectType == Enums_Engine.ObjectType.PARTICLE && cMass.objectType == Enums_Engine.ObjectType.PLAYER))
{
if (dynamicMasses[i].objectType == Enums_Engine.ObjectType.PLAYER)
{
Player player = (Player)dynamicMasses[i].gameObjectPointer;
if (player.IsAlive())
{
player.PlayerHitByParticle((Particle)cMass.gameObjectPointer, objectLibrary);
if (player.IsAlive() == false)
{
player.AssignKillCredit(objectLibrary);
}
}
}
else
{
Player player = (Player)cMass.gameObjectPointer;
if (player.IsAlive())
{
if (player.PlayerHitByParticle((Particle)dynamicMasses[i].gameObjectPointer, objectLibrary))
{
if (player.IsAlive() == false)
{
player.AssignKillCredit(objectLibrary);
}
if (i < dynamicMasses.Count)
{
deletedDynamic = true;
ObjectTerrainCollision(dynamicMasses[i], objectLibrary.terrain);
i--;
}
else
{
i--;
ObjectTerrainCollision(dynamicMasses[i], objectLibrary.terrain);
}
break;
}
}
}
}
}*/
#endregion
}
node = node.Next;
}
while (node != null);
if (deletedDynamic)
{
deletedDynamic = false;
i--;
continue;
}
}
ObjectTerrainCollision(dynamicMasses[i], objectLibrary.terrain);
}
}
///
/// Collisions between an object and the terrain. The float return value is the height difference of the object and the terrain
///
/// Mass of colliding object
/// Terrain
/// Height difference between object and terrain
private float ObjectTerrainCollision(Mass mass, Terrain terrain)
{
// Let each object override or supplemant collision logic
mass.gameObjectPointer.TerrainCollisionResponse(terrain);
return mass.gameObjectPointer.heightDifference;
}
private void CalculateNormalForces(float mass1, float mass2, Vector3 normalVelocity1, Vector3 normalVelocity2, float COR)
{
Vector3 resultantVelocity1, resultantVelocity2;
Vector3 eV1MinusV2, m1V1PlusM2V2;
float totalMass = mass1 + mass2;
eV1MinusV2 = COR * (normalVelocity1 - normalVelocity2);
m1V1PlusM2V2 = (mass1 * normalVelocity1) + (mass2 * normalVelocity2);
resultantVelocity1 = (m1V1PlusM2V2 - (mass2 * eV1MinusV2)) / totalMass;
resultantVelocity2 = ((mass1 * eV1MinusV2) + m1V1PlusM2V2) / totalMass;
normalForce1 = resultantVelocity1 * mass1 / Statics_Engine.SystemSettings.dt;
normalForce2 = resultantVelocity2 * mass2 / Statics_Engine.SystemSettings.dt;
}
///
/// Handles collisions between two objects. Note: All references to normal in this function refers to the normal of impact
///
/// Mass 1
/// Mass 2
/// ObjectLibrary
/// An enum telling us which (if any) of the mass need to be recycled after collision
private Enums_Engine.CollisionCleanup ObjectObjectCollision(Mass mass1, Mass mass2, ObjectLibrary objectLibrary)
{
Vector3 object1NormalVelocity = new Vector3(); // Stores the first object's normal velocity
Vector3 object2NormalVelocity = new Vector3(); // Stores the second object's normal velocity
//Vector3 totalNormalVelocity = new Vector3(); // Stores the sum of both object's normal velocities
//float totalMass = mass1.mass + mass2.mass; // Sum of both masses
Vector3 normalVectorOfImpact = new Vector3(); // Stores the normal vector of impact/contact
Vector3 mass1Velocity, mass2Velocity;
// Needed in case masses are in WALK mode, in which case they have no velocities
if (mass1.movementType == Enums_Engine.MovementType.WALK)
{
mass1Velocity = (mass1.currentPosition - mass1.lastPosition) / Statics_Engine.SystemSettings.dt;
}
else
{
mass1Velocity = mass1.velocity;
}
if (mass2.movementType == Enums_Engine.MovementType.WALK)
{
mass2Velocity = (mass2.currentPosition - mass2.lastPosition) / Statics_Engine.SystemSettings.dt;
}
else
{
mass2Velocity = mass2.velocity;
}
Enums_Engine.CollisionCleanup returnValue = Enums_Engine.CollisionCleanup.NONE;
// Mass1 has higher velocity so impact vector is mass2 - mass1, ie, from mass1 to mass2
normalVectorOfImpact = mass2.currentPosition - mass1.currentPosition;
if (normalVectorOfImpact != Vector3.Zero)
{
normalVectorOfImpact.Normalize();
}
if (mass1Velocity.Length() > mass2Velocity.Length())
{
// Ensure that mass1's velocity is not equal to 0
if (mass1Velocity.Length() != 0.0f)
{
// Check that the velocity is not moving away from the impact, ie, the angle between velocity
// and impact vector is between 90->0->270. If so the two objects are moving away from each
// other, so return.
if (Vector3.Dot(mass1Velocity, normalVectorOfImpact) / mass1Velocity.Length() < 0.0f)
{
return returnValue;
}
}
}
else
{
// Ensure that mass2's velocity is not equal to 0
if (mass2Velocity.Length() != 0.0f)
{
// Check that the velocity is not moving away from the impact, ie, the angle between velocity
// and impact vector is between 90->180->270. If so the two objects are moving away from each
// other, so return.
if (Vector3.Dot(mass2Velocity, normalVectorOfImpact) / mass2Velocity.Length() > 0.0f)
{
return returnValue;
}
}
}
// Calculate Mass1's normal velocity component
CalculateVectorComponents(normalVectorOfImpact, mass1Velocity);
object1NormalVelocity = normalComponent;
// Calculate Mass2's normal velocity component
CalculateVectorComponents(normalVectorOfImpact, mass2Velocity);
object2NormalVelocity = normalComponent;
CalculateNormalForces(mass1.mass, mass2.mass, object1NormalVelocity, object2NormalVelocity, 1.0f);
normalForce1 -= (2.0f * object1NormalVelocity * mass1.mass / Statics_Engine.SystemSettings.dt);
normalForce2 -= (2.0f * object2NormalVelocity * mass2.mass / Statics_Engine.SystemSettings.dt);
// Call GameObject.ObjectCollisionResponse and check return to determine if we should remove the GameObject from the board
bool mass1ReturnValue = mass1.gameObjectPointer.ObjectCollisionResponse(mass2.gameObjectPointer, normalForce1, objectLibrary);
bool mass2ReturnValue = mass2.gameObjectPointer.ObjectCollisionResponse(mass1.gameObjectPointer, normalForce2, objectLibrary);
if (mass1ReturnValue)
{
returnValue = Enums_Engine.CollisionCleanup.REMOVEMASS1;
}
if (mass2ReturnValue)
{
returnValue = Enums_Engine.CollisionCleanup.REMOVEMASS2;
}
if (mass1ReturnValue && mass2ReturnValue)
{
returnValue = Enums_Engine.CollisionCleanup.REMOVEBOTH;
}
// HACK: KEEP ALL OBJECTS ON THE BOARD FOR NOW
//returnValue = Enums_Engine.CollisionCleanup.NONE;
return returnValue;
}
private void CalculateVectorComponents(Vector3 surfaceNormal, Vector3 objectVelocity)
{
if (objectVelocity.Length() >= 0.01f || !float.IsInfinity(objectVelocity.Length()))
{
normalComponent = Vector3.Dot(objectVelocity, surfaceNormal) * surfaceNormal;
tangentialComponent = objectVelocity - normalComponent;
/*
// Based on vector dot product to get the angle between the two vectors
vectorToNormalAngle = (float)Math.Acos(Vector3.Dot(surfaceNormal, objectVelocity) / objectVelocity.Length());
// Stupid check required due to XNA's inaccuracy
if (float.IsNaN(vectorToNormalAngle))
{
vectorToNormalAngle = 0.0f;
}
// The angle between the ground and the vector is pi/2 - previous angle
vectorToSurfaceAngle = (float)Math.PI / 2.0f - vectorToNormalAngle;
// Scalar component of the vector in the the normal direction
normalComponentOfVector = objectVelocity.Length() * (float)Math.Sin(vectorToSurfaceAngle);
if (float.IsNaN(normalComponentOfVector))
{
//if objectVelocity.Length gives an invalid value
normalComponentOfVector = 0.0f;
}
// Above scalar component multiplied by the surface normal gives us the normal component of the vector
normalComponent = normalComponentOfVector * surfaceNormal;
// The vector plus the negative normalComponent will give us the tangential component in the reverse direction
tangentialComponent = -(objectVelocity + (-normalComponent));
*/
}
else
{
// Object velocity is equal to zero so set both components to zero
normalComponent = Vector3.Zero;
tangentialComponent = Vector3.Zero;
}
}
#endregion
}
}
#region Dead/Dying Code
// #region GameObject Terrain Collision
// else if (mass.objectType != Enums_Engine.ObjectType.PLAYER)
// {
// if (totalForce.Y > 0.0f){totalForce.Y = 0.0f;}
// if (velocity.Y > 0.0f){velocity.Y = 0.0f;}
// // Ground pushing up to negate gravity
// mass.AddForce(new Vector3(0.0f, heightDifference * terrain.propSurfaceTension, 0.0f) -
// (new Vector3(0.0f, totalForce.Y, 0.0f) +
// new Vector3(0.0f, velocity.Y * mass.mass / timeInterval, 0.0f)));
// }
// #endregion
// #region Particle Terrain
// if (mass.objectType == Enums_Engine.ObjectType.PARTICLE)
// {
// if (combinedNormalForce.Y < 0.0f)
// {
// mass.AddForce(-combinedNormalForce);
// }
// else
// {
// mass.AddForce(-velocityNormalComponent);
// }
// mass.AddForce(heightDifference * surfaceNormal * terrain.particleSurfaceTension * mass.COR);
// if (combinedTangentialForce.Length() >= 0.5f)
// {
// mass.AddForce(mass.mass * -gravityTangentialComponent);
// mass.AddFriction(mass.dynamicFrictionCoefficient + terrain.mass.dynamicFrictionCoefficient,
// (mass.mass * gravityNormalComponent) + totalForceNormalComponent,
// combinedTangentialForce);
// }
// else
// {
// mass.AddForce(mass.mass * -velocityTangentialComponent / timeInterval);
// mass.AddForce(-totalForceTangentialComponent);
// }
// }
// #endregion
//#region Player Terrain
// else if (mass.objectType == Enums_Engine.ObjectType.PLAYER)
// {
// #region Walk
// // Ground pushing up to negate gravity
// if (mass.movementType == Enums_Engine.MovementType.WALK)
// {
// //only if its NOT a wall
// if (heightDifference < Statics.PlayerSettings.DEFAULT_PLAYER_HEIGHT)
// {
// //just set their height!
// mass.currentPosition.Y = totalHeight + (objectHeight / 2);
// }
// else
// {
// mass.KickBack(5.0f);
// }
// }
// #endregion
// #region Hover
// else if (mass.movementType == Enums_Engine.MovementType.HOVER)
// {
// // Add terrain rebound force to object
// mass.AddForce((heightDifference * terrain.playerSurfaceTension * surfaceNormal) -
// (new Vector3(0.0f, totalForce.Y, 0.0f) +
// new Vector3(0.0f, velocity.Y * mass.mass / timeInterval, 0.0f)));
// if (velocityTangentialComponent.Length() > 0.5f)
// {
// // Static Friction
// if (mass.velocity.Length() < Statics.PlayerSettings.PLAYER_SPEED_ON_THE_GROUND / 10)
// {
// // Pass everything to friction (friction coefficients, the normal force on the body and the direction of friction)
// mass.AddFriction(mass.staticFrictionCoefficient + terrain.mass.staticFrictionCoefficient,
// (gravityNormalComponent * mass.mass),
// velocityTangentialComponent);
// }
// // Dynamic Friction
// else
// {
// // Pass everything to friction (friction coefficients, the normal force on the body and the direction of friction)
// mass.AddFriction(mass.dynamicFrictionCoefficient + terrain.mass.dynamicFrictionCoefficient,
// (gravityNormalComponent * mass.mass),
// velocityTangentialComponent);
// }
// }
// else
// {
// mass.AddForce(mass.mass * tangentialComponent / timeInterval);
// }
// }
// #endregion
// mass.lastMaxHeight = 0;
// }
//#endregion
// private bool ParticleInteraction(Mass mass1, Mass mass2)
// {
// Vector3 object1NormalVelocity = new Vector3(); // Stores the first object's normal velocity
// Vector3 object2NormalVelocity = new Vector3(); // Stores the second object's normal velocity
// Vector3 totalNormalVelocity = new Vector3(); // Stores the sum of both object's normal velocities
// float stickiness;
// float totalMass = mass1.mass + mass2.mass; // Sum of both masses
// Vector3 normalVectorOfImpact = new Vector3(); // Stores the normal vector of impact/contact
// Particle particle1 = ((Particle)mass1.gameObjectPointer);
// Particle particle2 = ((Particle)mass1.gameObjectPointer);
// if (particle1.particleType == particle2.particleType)
// {
// stickiness = (mass1.cohesion + mass2.cohesion) / 2.0f;
// }
// else
// {
// stickiness = (mass1.adhesion + mass2.adhesion) / 2.0f;
// }
// // Check which mass has the greater velocity and calculate the normal based on that
// if (mass1.velocity.Length() >= mass2.velocity.Length())
// {
// // Mass1 has higher velocity so impact vector is mass2 - mass1, ie, from mass1 to mass2
// normalVectorOfImpact = mass2.currentPosition - mass1.currentPosition;
// if (normalVectorOfImpact != Vector3.Zero)
// {
// normalVectorOfImpact.Normalize();
// }
// // Ensure that mass1's velocity is not equal to 0
// if (mass1.velocity.Length() != 0.0f)
// {
// // Check that the velocity is not moving away from the impact, ie, the angle between velocity
// // and impact vector is between 90->0->270. If so the two objects are moving away from each
// // other, so return.
// if (Vector3.Dot(mass1.velocity, normalVectorOfImpact) / mass1.velocity.Length() < 0.0f)
// {
// return false;
// }
// }
// // Calculate Mass1's normal velocity component
// CalculateVectorComponents(normalVectorOfImpact, mass1.velocity);
// object1NormalVelocity = normalComponent;
// // Calculate Mass2's normal velocity component
// CalculateVectorComponents(-normalVectorOfImpact, mass2.velocity);
// object2NormalVelocity = normalComponent;
// // Find the difference between these two velocity to give our final resultant velocity
// totalNormalVelocity = object1NormalVelocity - object2NormalVelocity;
// }
// else
// {
// // Mass2 has higher velocity so impact vector is mass1 - mass2, ie, from mass2 to mass1
// normalVectorOfImpact = mass1.currentPosition - mass2.currentPosition;
// if (normalVectorOfImpact != Vector3.Zero)
// {
// normalVectorOfImpact.Normalize();
// }
// if (mass2.velocity.Length() != 0.0f)
// {
// // Check that the velocity is not moving away from the impact, ie, the angle between velocity
// // and impact vector is between 90->0->270. If so the two objects are moving away from each
// // other, so return.
// if (Vector3.Dot(mass2.velocity, normalVectorOfImpact) / mass2.velocity.Length() < 0.0f)
// {
// return false;
// }
// }
// // Calculate Mass1's normal velocity component
// CalculateVectorComponents(normalVectorOfImpact, mass1.velocity);
// object1NormalVelocity = normalComponent;
// // Calculate Mass2's normal velocity component
// CalculateVectorComponents(-normalVectorOfImpact, mass2.velocity);
// object2NormalVelocity = normalComponent;
// // Find the difference between these two velocity to give our final resultant velocity
// totalNormalVelocity = object2NormalVelocity - object1NormalVelocity;
// }
// if (totalNormalVelocity.Length() >= 15.0f)
// {
// normalForce1 = 2.0f * mass2.mass * totalNormalVelocity * stickiness / (timeInterval * totalMass);
// normalForce2 = 2.0f * mass1.mass * -totalNormalVelocity * stickiness / (timeInterval * totalMass);
// // Add the forces to the respective masses
// mass1.AddForce(normalForce1);
// mass2.AddForce(normalForce2);
// mass1.isMoving = true;
// mass2.isMoving = true;
// }
// else
// {
// if (((Particle)mass1.gameObjectPointer).particleType == ((Particle)mass2.gameObjectPointer).particleType)
// {
// //Some particles can't combine..
// //Earth boulders don't combine
// if ((((Particle)mass1.gameObjectPointer).particleType == Particle.ParticleType.Earth && (mass1.energy < 0.2f && mass2.energy < 0.2f)) == false &&
// //Ice balls can't combine
// (((Particle)mass1.gameObjectPointer).particleType == Particle.ParticleType.Water && (mass1.energy < -0.2f && mass2.energy < -0.2f)) == false &&
// //Make sure things don't get TOO big
// (mass1.mass + mass2.mass) < MAXIMUM_MASS)
// {
// mass1.energy = ((mass1.energy * mass1.mass) + (mass2.energy * mass2.mass)) / (mass1.mass + mass2.mass);
// mass1.currentPosition = ((mass1.currentPosition * mass1.mass) + (mass2.currentPosition * mass2.mass)) / (mass1.mass + mass2.mass);
// mass1.lastPosition = ((mass1.lastPosition * mass1.mass) + (mass2.lastPosition * mass2.mass)) / (mass1.mass + mass2.mass);
// mass1.totalForce = ((mass1.totalForce * mass1.mass) + (mass2.totalForce * mass2.mass)) / (mass1.mass + mass2.mass);
// mass1.velocity = ((mass1.velocity * mass1.mass) + (mass2.velocity * mass2.mass)) / (mass1.mass + mass2.mass);
// mass1.objectHeight = mass1.objectHeight + mass2.objectHeight;
// mass1.mass += mass2.mass;
// mass1.scale = mass1.scale + mass2.scale;
// //a hack for fixing the bounding sphere issue
// particle1.mass.boundingSphere.Radius = particle1.mass.boundingSphere.Radius + particle2.mass.boundingSphere.Radius;
// particle1.mass.boundingSphere.Radius *= 0.8f;
// Statics.lookupMap.RemoveLast(mass2);
// Statics.lookupMap.RemoveCurrent(mass2);
// if (Statics.lookupMap.DynamicContains(mass2))
// {
// Statics.lookupMap.RemoveDynamic(mass2);
// mass2.ClearValues();
// mass2.deadObject = true;
// return true;
// }
// mass2.ClearValues();
// mass2.deadObject = true;
// return false;
// }
// normalForce1 = 2.0f * mass2.mass * -totalNormalVelocity * stickiness / (timeInterval * totalMass);
// normalForce2 = 2.0f * mass1.mass * totalNormalVelocity * stickiness / (timeInterval * totalMass);
// // Add the forces to the respective masses
// mass1.AddForce(normalForce1);
// mass2.AddForce(normalForce2);
// mass1.isMoving = true;
// mass2.isMoving = true;
// }
// }
// return false;
// }
/*
private Enums_Engine.CollisionCleanup ObjectObjectCollision1(Mass mass1, Mass mass2, ObjectLibrary objectLibrary)
{
Vector3 object1NormalVelocity = new Vector3(); // Stores the first object's normal velocity
Vector3 object2NormalVelocity = new Vector3(); // Stores the second object's normal velocity
Vector3 totalNormalVelocity = new Vector3(); // Stores the sum of both object's normal velocities
float totalMass = mass1.mass + mass2.mass; // Sum of both masses
Vector3 normalVectorOfImpact = new Vector3(); // Stores the normal vector of impact/contact
Enums_Engine.CollisionCleanup returnValue = Enums_Engine.CollisionCleanup.NONE;
// Check which mass has the greater velocity and calculate the normal based on that
if (mass1.velocity.Length() >= mass2.velocity.Length())
{
// Mass1 has higher velocity so impact vector is mass2 - mass1, ie, from mass1 to mass2
normalVectorOfImpact = mass2.currentPosition - mass1.currentPosition;
if (normalVectorOfImpact != Vector3.Zero)
{
normalVectorOfImpact.Normalize();
}
// Ensure that mass1's velocity is not equal to 0
if (mass1.velocity.Length() != 0.0f)
{
// Check that the velocity is not moving away from the impact, ie, the angle between velocity
// and impact vector is between 90->0->270. If so the two objects are moving away from each
// other, so return.
if (Vector3.Dot(mass1.velocity, normalVectorOfImpact) / mass1.velocity.Length() < 0.0f)
{
return returnValue;
}
}
// Calculate Mass1's normal velocity component
CalculateVectorComponents(normalVectorOfImpact, mass1.velocity);
object1NormalVelocity = normalComponent;
// Calculate Mass2's normal velocity component
CalculateVectorComponents(-normalVectorOfImpact, mass2.velocity);
object2NormalVelocity = normalComponent;
CalculateNormalForces(mass1.mass, mass2.mass, object1NormalVelocity, object2NormalVelocity, 1.0f);
//// Find the difference between these two velocity to give our final resultant velocity
//totalNormalVelocity = object1NormalVelocity - object2NormalVelocity;
//// Based on In-elastic collision v1 = (m2 * totalforce)/(m1 + m2). The rest of the stuff is
//// to convert a velocity into a force.
//normalForce1 = 2.0f * mass2.mass * -totalNormalVelocity / (timeInterval * totalMass);
//normalForce2 = 2.0f * mass1.mass * totalNormalVelocity / (timeInterval * totalMass);
}
else
{
// Mass2 has higher velocity so impact vector is mass1 - mass2, ie, from mass2 to mass1
normalVectorOfImpact = mass1.currentPosition - mass2.currentPosition;
if (normalVectorOfImpact != Vector3.Zero)
{
normalVectorOfImpact.Normalize();
}
if (mass2.velocity.Length() != 0.0f)
{
// Check that the velocity is not moving away from the impact, ie, the angle between velocity
// and impact vector is between 90->0->270. If so the two objects are moving away from each
// other, so return.
if (Vector3.Dot(mass2.velocity, normalVectorOfImpact) / mass2.velocity.Length() < 0.0f)
{
return returnValue;
}
}
// Calculate Mass1's normal velocity component
CalculateVectorComponents(normalVectorOfImpact, mass1.velocity);
object1NormalVelocity = normalComponent;
// Calculate Mass2's normal velocity component
CalculateVectorComponents(-normalVectorOfImpact, mass2.velocity);
object2NormalVelocity = normalComponent;
CalculateNormalForces(mass1.mass, mass2.mass, object1NormalVelocity, object2NormalVelocity, 1.0f);
//// Find the difference between these two velocity to give our final resultant velocity
//totalNormalVelocity = object2NormalVelocity - object1NormalVelocity;
//// Based on In-elastic collision v1 = (m2 * totalforce)/(m1 + m2). The rest of the stuff is
//// to convert a velocity into a force.
//normalForce1 = 2.0f * mass2.mass * totalNormalVelocity / (timeInterval * totalMass);
//normalForce2 = 2.0f * mass1.mass * -totalNormalVelocity / (timeInterval * totalMass);
}
// Call GameObject.ObjectCollisionResponse and check return to determine if we should remove the GameObject from the board
bool mass1ReturnValue = mass1.gameObjectPointer.ObjectCollisionResponse(mass2.gameObjectPointer, normalForce1, objectLibrary);
bool mass2ReturnValue = mass2.gameObjectPointer.ObjectCollisionResponse(mass1.gameObjectPointer, normalForce2, objectLibrary);
if (mass1ReturnValue)
{
returnValue = Enums_Engine.CollisionCleanup.REMOVEMASS1;
}
if (mass2ReturnValue)
{
returnValue = Enums_Engine.CollisionCleanup.REMOVEMASS2;
}
if (mass1ReturnValue && mass2ReturnValue)
{
returnValue = Enums_Engine.CollisionCleanup.REMOVEBOTH;
}
// HACK: KEEP ALL OBJECTS ON THE BOARD FOR NOW
//returnValue = Enums_Engine.CollisionCleanup.NONE;
return returnValue;
}
*/
#endregion