public bool CollideAgainst(AxisAlignedCube axisAlignedCube) { BoundingBox boundingBox = axisAlignedCube.AsBoundingBox(); float?result = this.AsRay().Intersects(boundingBox); return(result.HasValue && result.Value < this.GetLength()); }
public PositionedObjectList <FlatRedBall.Math.Geometry.AxisAlignedCube> ToAxisAlignedCubeList() { PositionedObjectList <FlatRedBall.Math.Geometry.AxisAlignedCube> listToReturn = new PositionedObjectList <FlatRedBall.Math.Geometry.AxisAlignedCube>(); foreach (AxisAlignedCubeSave cubeSave in AxisAlignedCubeSaves) { FlatRedBall.Math.Geometry.AxisAlignedCube cube = cubeSave.ToAxisAlignedCube(); listToReturn.Add(cube); } return(listToReturn); }
/// <summary> /// Returns whether this instance overlaps the argument AxisAlignedCube /// </summary> /// <param name="cube">The instance AxisAlignedCube to test against.</param> /// <returns>Whether collision has occurred</returns> public bool CollideAgainst(AxisAlignedCube cube) { UpdateDependencies(TimeManager.CurrentTime); cube.UpdateDependencies(TimeManager.CurrentTime); Vector3 relativeCenter = Position - cube.Position; if (System.Math.Abs(relativeCenter.X) - Radius > cube.ScaleX || System.Math.Abs(relativeCenter.Y) - Radius > cube.ScaleY || System.Math.Abs(relativeCenter.Z) - Radius > cube.ScaleZ) { return(false); } Vector3 nearest = GetNearestPoint(cube, relativeCenter); float distance = (nearest - relativeCenter).LengthSquared(); return(distance <= Radius * Radius); }
private Vector3 GetNearestPoint(AxisAlignedCube cube, Vector3 relativeCenter) { float distance; Vector3 nearest = new Vector3(); distance = relativeCenter.X; if (distance > cube.ScaleX) { distance = cube.ScaleX; } if (distance < -cube.ScaleX) { distance = -cube.ScaleX; } nearest.X = distance; distance = relativeCenter.Y; if (distance > cube.ScaleY) { distance = cube.ScaleY; } if (distance < -cube.ScaleY) { distance = -cube.ScaleY; } nearest.Y = distance; distance = relativeCenter.Z; if (distance > cube.ScaleZ) { distance = cube.ScaleZ; } if (distance < -cube.ScaleZ) { distance = -cube.ScaleZ; } nearest.Z = distance; return(nearest); }
/// <summary> /// Performs a bounce collision (a collision which modifies velocity and acceleration), and separates the objects if so. /// </summary> /// <param name="cube">The cube to perform collision against.</param> /// <param name="thisMass">The mass of this instance.</param> /// <param name="otherMass">Th e mass of the argument cube.</param> /// <param name="elasticity">The ratio of velocity to preserve.</param> /// <returns>Whether a collision occurred.</returns> public bool CollideAgainstBounce(AxisAlignedCube cube, float thisMass, float otherMass, float elasticity) { #if DEBUG if (thisMass == 0 && otherMass == 0) { throw new ArgumentException("Both masses cannot be 0. For equal masses pick a non-zero value"); } #endif if (CollideAgainstMove(cube, thisMass, otherMass)) { // Get the relative velocity of this circle to the argument circle: Vector3 relativeVelocity = new Vector3( this.TopParent.XVelocity - cube.TopParent.XVelocity, this.TopParent.YVelocity - cube.TopParent.YVelocity, this.TopParent.ZVelocity - cube.TopParent.ZVelocity); Vector3 reposition = LastMoveCollisionReposition; if (otherMass == 0) { reposition = -cube.mLastMoveCollisionReposition; } #if FRB_MDX float velocityNormalDotResult = Vector3.Dot(relativeVelocity, reposition); #else float velocityNormalDotResult; Vector3.Dot(ref relativeVelocity, ref reposition, out velocityNormalDotResult); #endif if (velocityNormalDotResult >= 0) { return(true); } #if FRB_MDX throw new NotImplementedException(); //Vector2 tangentVector = new Vector2((float)mLastCollisionTangent.X, (float)mLastCollisionTangent.Y); //// Perform the bounce if the relative velocity and the tangent are the opposite direction. Vector3 reverseNormal = -Vector3.Normalize(LastMoveCollisionReposition); float length = Vector3.Dot(relativeVelocity, reverseNormal); Vector3 velocityOnNormal = Vector3.Multiply(reverseNormal, length); #else Vector3 reverseNormal = -reposition; reverseNormal.Normalize(); float length = Vector3.Dot(relativeVelocity, reverseNormal); Vector3 velocityOnNormal; Vector3.Multiply(ref reverseNormal, length, out velocityOnNormal); #endif cube.TopParent.Velocity.X += (1 + elasticity) * thisMass / (thisMass + otherMass) * velocityOnNormal.X; cube.TopParent.Velocity.Y += (1 + elasticity) * thisMass / (thisMass + otherMass) * velocityOnNormal.Y; cube.TopParent.Velocity.Z += (1 + elasticity) * thisMass / (thisMass + otherMass) * velocityOnNormal.Z; this.TopParent.Velocity.X -= (1 + elasticity) * otherMass / (thisMass + otherMass) * velocityOnNormal.X; this.TopParent.Velocity.Y -= (1 + elasticity) * otherMass / (thisMass + otherMass) * velocityOnNormal.Y; this.TopParent.Velocity.Z -= (1 + elasticity) * otherMass / (thisMass + otherMass) * velocityOnNormal.Z; return(true); } return(false); }
/// <summary> /// Returns whether this instance overlaps the argument cube, and separates the two instances according to their relative masses. /// </summary> /// <param name="cube">The cube to perform collision against.</param> /// <param name="thisMass">The mass of this instance.</param> /// <param name="otherMass">The mass of the cube.</param> /// <returns>Whether the objects were overlapping before the reposition.</returns> public bool CollideAgainstMove(AxisAlignedCube cube, float thisMass, float otherMass) { #if DEBUG if (thisMass == 0 && otherMass == 0) { throw new ArgumentException("Both masses cannot be 0. For equal masses pick a non-zero value"); } #endif if (LastDependencyUpdate != TimeManager.CurrentTime) { UpdateDependencies(TimeManager.CurrentTime); } if (cube.LastDependencyUpdate != TimeManager.CurrentTime) { cube.UpdateDependencies(TimeManager.CurrentTime); } Vector3 relativeCenter = Position - cube.Position; if (System.Math.Abs(relativeCenter.X) - Radius > cube.ScaleX || System.Math.Abs(relativeCenter.Y) - Radius > cube.ScaleY || System.Math.Abs(relativeCenter.Z) - Radius > cube.ScaleZ) { return(false); } Vector3 nearest = GetNearestPoint(cube, relativeCenter); float distance = (nearest - relativeCenter).LengthSquared(); if (distance > Radius * Radius) { return(false); } double distanceToMove = Radius - System.Math.Sqrt((double)distance); Vector3 moveVector = relativeCenter - nearest; moveVector.Normalize(); float amountToMoveThis = otherMass / (thisMass + otherMass); LastMoveCollisionReposition = moveVector * (float)(distanceToMove * amountToMoveThis); Vector3 cubeReposition = moveVector * (float)(-distanceToMove * (1 - amountToMoveThis)); cube.mLastMoveCollisionReposition = cubeReposition; if (mParent != null) { TopParent.Position += LastMoveCollisionReposition; ForceUpdateDependencies(); } else { Position += LastMoveCollisionReposition; } if (cube.mParent != null) { cube.TopParent.Position += cube.LastMoveCollisionReposition; ForceUpdateDependencies(); } else { cube.Position += cube.LastMoveCollisionReposition; } return(true); }