/// <summary> /// This function returns a vector that is rotated by the opposite of me /// </summary> public MyVector GetRotatedVectorReverse(MyVector vector, bool isQuatNormalized) { if (!isQuatNormalized) { // I'm not normalized, clone myself and normalize it MyQuaternion myUnitClone = new MyQuaternion(this.X, this.Y, this.Z, this.W); myUnitClone.BecomeUnitQuaternion(); return(myUnitClone.GetRotatedVectorReverse(vector, true)); } MyVector qvec = new MyVector(this.X, this.Y, this.Z); //Vector uv = qvec.Cross(vector); MyVector uv = MyVector.Cross(qvec, vector); //Vector uuv = qvec.Cross(uv); MyVector uuv = MyVector.Cross(qvec, uv); //uv *= (2.0f * quat.w); uv.Multiply(this.W * -2d); //uuv *= 2.0f; uuv.Multiply(2d); //return vector + uv + uuv; MyVector retVal = vector.Clone(); retVal.Add(uv); retVal.Add(uuv); return(retVal); }
/// <summary> /// The vectors passed in are orientated to the body frame /// NOTE: This gets reset at the beginning of each timer tick /// </summary> /// <remarks> /// See Ball.InternalForce's remarks for when you would use this as apposed to ApplyExternalForce() /// </remarks> /// <param name="offset"> /// This is the displacement from my center where the force is applied (if you know this is always zero at compile time, /// just directly add force to base.InternalForce instead) /// </param> /// <param name="force">This is the direction and strength of the force being applied</param> public void ApplyInternalForce(MyVector offset, MyVector force) { //TODO: Convert forcePos from being relative to the center of position to being relative to the center of mass // Split the force acting on me into rotational and translational MyVector translationForce, torque; SplitForceIntoTranslationAndTorque(out translationForce, out torque, _centerOfMass, offset, force); // Add to my torque _internalTorque.Add(torque); // Add the translational force to my base this.InternalForce.Add(translationForce); }
/// <summary> /// This function will check to see if I've clipped the box boundry. If I have, I will change the ChangeInPosition, so that the ball /// won't cross the boundry line. /// </summary> /// <param name="curPositionCloned">The values of this will be changed if there is a boundry collision</param> /// <param name="changeInPos">This will get reset if there is a collision with the boundry</param> /// <param name="elapsedTime">This is needed to recalculate changeInPos if there is a boundry collision</param> private void TimerBoxBoundry(MyVector position, ref MyVector changeInPos, double elapsedTime) { List <Coords> affectedAxiis = new List <Coords>(); // Clone the Position in order to start generating the ProposedPosition MyVector proposedPosition = this.Position.Clone(); // Add the change in position to the proposed position to make it a real proposed position proposedPosition.Add(changeInPos); // Now compare the proposed position with the stated corner stones to see if I went to far #region X if (proposedPosition.X < _boundingLower.X) { affectedAxiis.Add(Coords.X); position.X = _boundingLower.X; } else if (proposedPosition.X > _boundingUpper.X) { affectedAxiis.Add(Coords.X); position.X = _boundingUpper.X; } #endregion #region Y if (proposedPosition.Y < _boundingLower.Y) { affectedAxiis.Add(Coords.Y); position.Y = _boundingLower.Y; } else if (proposedPosition.Y > _boundingUpper.Y) { affectedAxiis.Add(Coords.Y); position.Y = _boundingUpper.Y; } #endregion #region Z if (proposedPosition.Z < _boundingLower.Z) { affectedAxiis.Add(Coords.Z); position.Z = _boundingLower.Z; } else if (proposedPosition.Z > _boundingUpper.Z) { affectedAxiis.Add(Coords.Z); position.Z = _boundingUpper.Z; } #endregion if (affectedAxiis.Count > 0) { // Bounce the ball changeInPos = TimerBoxBoundrySprtBounceIt(affectedAxiis, elapsedTime); } }
/// <summary> /// This function will calculate the new velocity based on the current acceleration and elapsed time. I will store the result back into /// my velocity property. /// </summary> private void TimerSprtVel(double elapsedTime) { // Clone the current accel MyVector changeInVel = _acceleration.Clone(); // Now make the ChangeInVel a velocity instead of an acceleration by multiplying it by time changeInVel.Multiply(elapsedTime); // I have the change in velocity, so I will add it to the current velocity in order to make a new velocity _velocity.Add(changeInVel); }
/// <summary> /// This function will compute the new acceleration based on the force pushing against the ball. The result will overwrite the /// current acceleration /// </summary> private void TimerSprtAccel(MyVector force) { // Make the PartialAccel into a clone of the force passed in MyVector partialAccel = force.Clone(); // I will divide by mass, and it will no longer be force, it will be change in accel (the property guarantees that mass // isn't zero) partialAccel.Divide(_mass); // Add the partial accel to this ball's accel _acceleration.Add(partialAccel); }
private void button1_Click(object sender, EventArgs e) { MyVector v1 = new MyVector(3, 4, 5); v1.Add(1, 2, 3); v1.BecomeUnitVector(); MyVector v2 = v1.Clone(); v2.Multiply(3); v1.Divide(3); }
/// <summary> /// The vectors passed in are orientated to the world frame /// NOTE: This gets reset at the beginning of each timer tick /// </summary> /// <remarks> /// See Ball.ExternalForce's remarks for when you would use this as apposed to ApplyInternalForce() /// </remarks> /// <param name="offset"> /// This is the displacement from my center where the force is applied (if you know this is always zero at compile time, /// just directly add force to base.ExternalForce instead) /// </param> /// <param name="force">This is the direction and strength of the force being applied</param> public void ApplyExternalForce(MyVector offset, MyVector force) { // Split the force acting on me into rotational and translational MyVector translationForce, torque; SplitForceIntoTranslationAndTorque(out translationForce, out torque, _centerOfMass, offset, force); //System.Windows.Forms.MessageBox.Show(torque.X.ToString() + ", " + torque.Y.ToString() + ", " + torque.Z.ToString()); // Add to my torque _externalTorque.Add(torque); // Add the translational force to my base this.ExternalForce.Add(translationForce); }
private void ApplyTorque(double elapsedTime) { // Calculate the new angular momentum (current + (torque * time)) MyVector newMomentum = _internalTorque.Clone(); newMomentum.Multiply(elapsedTime); _angularMomentum.Add(newMomentum); // Figure out the inverse of the world frame's inertia tensor // (Rotation * bodyInertialTensorInverse * Transposed Rotation) MyMatrix3 curRotation = base.RotationMatrix.Clone(); MyMatrix3 inverseWorldInertiaTensor = MyMatrix3.Multiply(MyMatrix3.Multiply(curRotation, _inertialTensorBodyInverse), MyMatrix3.Transpose(curRotation)); // Now all that's left is to figure out the new angular velocity _angularVelocity.StoreNewValues(MyMatrix3.Multiply(inverseWorldInertiaTensor, _angularMomentum)); }
/// <summary> /// This function returns the addition of internal force and external force. Before I do that, I need to rotate a copy of internal /// force so that it is based off of the same orientation as the external force. /// </summary> private MyVector TimerSprtCombineForce() { if (_internalForce.IsZero) { // Internal force is zero, so there is nothing to rotate (or add) return(_externalForce.Clone()); } // The sphere's rotation quaternion already knows how to rotate from internal to external. So make a copy of // internal line up with external. MyVector retVal = base.Rotation.GetRotatedVector(_internalForce, true); // retVal holds the internal force in the same orientation as the external force. I will add external force to it, and retVal // will hold the net force placed on the ball retVal.Add(_externalForce); // Exit Function return(retVal); }
private void Copy() { if (_mode != SelectionMode.Selected || _selectedObjects.Count == 0) { return; } _myClipboard.Clear(); _clipboardPositionCenter = new MyVector(); foreach (RadarBlip blip in _map.GetAllBlips()) { if (_selectedObjects.Contains(blip.Token)) { _myClipboard.Add(Scenes.CloneBlip(blip, _map)); _clipboardPositionCenter.Add(blip.Sphere.Position); } } if (_myClipboard.Count > 0) { _clipboardPositionCenter.Divide(_myClipboard.Count); } }
/// <summary> /// This function prunes the list of positions that are too old. It then figures out the average velocity /// of the remaining positions. /// </summary> private MyVector TimerSprtCalculateVelocity() { const int RETENTION = 75; // milliseconds int curTick = Environment.TickCount; // Add the current to the list _prevMousePositions.Add(new MousePosition(_curMousePoint.Clone())); #region Prune List int lastIndex = -1; for (int cntr = _prevMousePositions.Count - 1; cntr >= 0; cntr--) { if (curTick - _prevMousePositions[cntr].Tick > RETENTION) { // This item is too old. And since the list is in time order, all the entries before this are also too old lastIndex = cntr; break; } } if (lastIndex >= 0) { //_prevMousePositions.RemoveRange(lastIndex, _prevMousePositions.Count - lastIndex); _prevMousePositions.RemoveRange(0, lastIndex + 1); } #endregion #region Calculate Velocity MyVector retVal = new MyVector(0, 0, 0); // Add up all the instantaneous velocities for (int cntr = 0; cntr < _prevMousePositions.Count - 1; cntr++) { retVal.Add(_prevMousePositions[cntr + 1].Position - _prevMousePositions[cntr].Position); } // Take the average if (_prevMousePositions.Count > 2) // if count is 0 or 1, then retVal will still be (0,0,0). If it's 2, then I would be dividing by 1, which is pointless { retVal.Divide(_prevMousePositions.Count - 1); } #endregion // Exit Function return retVal; }