//--------------------------------------------------------------------------------------------------------------------------------------------------- // // 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