private void Body_ApplyForce(Body sender, BodyForceEventArgs e)
        {
            // Apply Gravity
            if (!_bodyForces.ContainsKey(sender))
            {
                return;
            }

            e.AddForce(_bodyForces[sender]);
        }
        private void Body_ApplyForce(Body sender, BodyForceEventArgs e)
        {
            if (_shouldRandomizeVelocities)
            {
                #region Set Velocities

                _didRandomizeVelocities = true;

                Vector3D newVelocity = Math3D.GetRandomVector_Spherical(MAXRANDVELOCITY * _randVelMultiplier);

                e.AddImpulse(newVelocity, sender.CenterOfMass.ToVector());

                #endregion
            }

            // Apply Gravity
            if (!_cubeForces.ContainsKey(sender))
            {
                return;
            }

            e.AddForce(_cubeForces[sender]);
        }
        private void Cube_ApplyForce(Body sender, BodyForceEventArgs e)
        {
            if (_shouldRandomizeVelocities)
            {
                #region Set Velocities

                _didRandomizeVelocities = true;

                Vector3D newVelocity = Math3D.GetRandomVector_Spherical(MAXRANDVELOCITY * _randVelMultiplier);

                //sender.Velocity.X = newVelocity.X;
                //sender.Velocity.Y = newVelocity.Y;
                //sender.Velocity.Z = newVelocity.Z;

                e.AddImpulse(newVelocity, sender.CenterOfMass.ToVector());

                #endregion
            }

            #region Do Gravity

            // Calculate force between the two
            //TODO:  Calculate these forces in one place and remember the results


            Point3D blueCenterWorld = GetWorldCenterMass(_blueCube);
            Point3D redCenterWorld = GetWorldCenterMass(_redCube);

            Vector3D gravityLink = blueCenterWorld - redCenterWorld;

            double force = GRAVITATIONALCONSTANT * (_blueCube.Mass * _redCube.Mass) / gravityLink.LengthSquared;

            gravityLink.Normalize();
            gravityLink = Vector3D.Multiply(force, gravityLink);

            // Apply the force
            if (sender == _blueCube)
            {
                e.AddForce(Vector3D.Multiply(-1d, gravityLink));
            }
            else if (sender == _redCube)
            {
                e.AddForce(gravityLink);
            }
            else
            {
                MessageBox.Show("Unknown Sender: " + sender.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            #endregion
        }
        private void Body_ApplyForce(Body sender, BodyForceEventArgs e)
        {
            ConvexBody3D senderCast = sender as ConvexBody3D;
            if (senderCast == null)
            {
                return;
            }

            #region Boundry Force

            Vector3D positionWorld = senderCast.PositionToWorld(senderCast.CenterOfMass).ToVector();

            // Just using one property from boundry assumes the boundry is square, and max is positive
            double boundryMax = _boundryMax.X;
            double maxDistance = _boundryMax.X * .85d;
            if (positionWorld.LengthSquared > maxDistance * maxDistance)
            {
                // Get the distance from the max distance
                double distFromMax = positionWorld.Length - maxDistance;     // wait till now to do the expensive operation.

                // I want an acceleration of zero when distFromMax is 1, but an accel of 10 when it's boundryMax
                //NOTE: _boundryMax.X is to the edge of the box.  If they are in the corner the distance will be greater, so the accel will be greater
                double accel = UtilityCore.GetScaledValue(0, 30, 0, boundryMax - maxDistance, distFromMax);

                // Apply a force
                Vector3D force = positionWorld;
                force.Normalize();
                force *= accel * senderCast.Mass * -1d;
                e.AddForce(force);
            }

            #endregion

            #region Gravity

            if (_hasGravity)
            {
                //TODO:  Attract all other objects to the asteroids
                if (senderCast.MaterialGroupID == _materialManager.AsteroidMaterialID && _asteroidGravityForces.ContainsKey(senderCast))
                {
                    e.AddForce(_asteroidGravityForces[senderCast]);
                }
                else if (senderCast.MaterialGroupID == _materialManager.ShipMaterialID && _asteroidGravityForces.Keys.Count > 0)		// the asteroids only attract every few frames.  If I attract every frame, the forces are unbalanced, and the ship ends up propelling the asteroid around
                {
                    #region Ship to asteroids

                    Point3D shipPos = senderCast.PositionToWorld(senderCast.CenterOfMass);
                    double shipMass = senderCast.Mass;

                    Vector3D gravityForce = new Vector3D(0, 0, 0);

                    foreach (Asteroid asteroid in _asteroids)
                    {
                        #region Apply Gravity

                        Vector3D gravityLink = shipPos - asteroid.PositionWorld;

                        double force = GRAVITATIONALCONSTANT * (asteroid.Mass * shipMass) / gravityLink.LengthSquared;

                        gravityLink.Normalize();
                        gravityLink *= force;

                        //_asteroidGravityForces[_asteroids[innerCntr].PhysicsBody] += gravityLink;
                        gravityForce -= gravityLink;

                        #endregion
                    }

                    e.AddForce(gravityForce);

                    #endregion
                }
            }

            #endregion

            #region Set Velocities

            if (_setVelocityArgs != null)
            {
                _hasSetVelocities = true;

                // See if the velocity should be set for this type of object
                bool shouldSetVelocity = false;
                if (_setVelocityArgs.Asteroids && senderCast.MaterialGroupID == _materialManager.AsteroidMaterialID)
                {
                    shouldSetVelocity = true;
                }
                else if (_setVelocityArgs.Minerals && senderCast.MaterialGroupID == _materialManager.MineralMaterialID)
                {
                    shouldSetVelocity = true;
                }

                if (shouldSetVelocity)
                {
                    // Figure out the velocity
                    Vector3D velocity = new Vector3D(0, 0, 0);
                    Vector3D angularVelocity = new Vector3D(0, 0, 0);
                    if (_setVelocityArgs.Speed > 0d)
                    {
                        velocity = Math3D.GetRandomVector_Spherical(_setVelocityArgs.Speed);
                        angularVelocity = Math3D.GetRandomVector_Spherical(_setVelocityArgs.Speed / 10d);

                        if (_setVelocityArgs.IsRandom)
                        {
                            double halfSpeed = _setVelocityArgs.Speed / 2d;
                            if (velocity.Length < halfSpeed)
                            {
                                // It's going too slow, choose a new speed between half and full
                                velocity.Normalize();
                                double newSpeed = halfSpeed + (StaticRandom.NextDouble() * halfSpeed);
                                velocity *= newSpeed;
                            }
                        }
                        else
                        {
                            // GetRandomVectorSpherical returns random, but this should be fixed
                            velocity.Normalize();
                            velocity *= _setVelocityArgs.Speed;
                        }
                    }

                    // Set it (and clear rotation)
                    senderCast.Omega = angularVelocity;
                    senderCast.Velocity = velocity;
                }
            }

            #endregion
        }