/// <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> /// 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 needs to be called before the timer is called. Between this function and the timer function is when all the outside /// forces have a chance to influence the object (gravity, explosion blasts, conveyor belts, etc) /// </summary> /// <remarks> /// I've given this function a bit of thought. It's really not needed, because when TimerFinish is done, that should be the equivalent /// of a new cycle. But I like having more defined phases (even though there is an extra round of function calls to make) /// </remarks> public virtual void PrepareForNewTimerCycle() { // I can't decide whether to put this here, or the timerfinish _savedPosition = null; _elapsedTime = 0; // Reset stuff _internalForce.Multiply(0); _externalForce.Multiply(0); _acceleration.Multiply(0); }
public override void TimerTestPosition(double elapsedTime) { base.TimerTestPosition(elapsedTime); // Either remember the orig rotation, or restore to that orig rotation (as of PrepareForNew) if (_savedRotation == null) { _savedRotation = this.Rotation.Clone(); } else { this.Rotation.StoreNewValues(_savedRotation); } // Remember the elapsed time that was passed in _elapsedTime = elapsedTime; // Figure out the new rotation (the body has been rotating at some velocity during the previous tick) if (!_angularVelocity.IsZero) { // Figure out what the angle will be double timedAngle = _angularVelocity.GetMagnitude(); timedAngle *= elapsedTime; if (!_centerOfMass.IsZero) { #region Rotate around center of mass // Remember where the center of mass is in world coords MyVector cmRotated = this.Rotation.GetRotatedVector(_centerOfMass, true); MyVector cmWorld = this.Position + cmRotated; // Get the opposite of the cm MyVector posRelativeToCM = cmRotated.Clone(); posRelativeToCM.Multiply(-1d); // Rotate the center of position around the center of mass posRelativeToCM.RotateAroundAxis(_angularVelocity, timedAngle); // Now figure out the new center of position this.Position.X = cmWorld.X + posRelativeToCM.X; this.Position.Y = cmWorld.Y + posRelativeToCM.Y; this.Position.Z = cmWorld.Z + posRelativeToCM.Z; #endregion } // Rotate myself this.RotateAroundAxis(_angularVelocity, timedAngle); } }
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)); }
protected void GetCollisionNormalAndPointsOfContact_SphereSphere(out MyVector normal, out double normalMagnitude, out MyVector pointOfContact1, out MyVector pointOfContact2, BallBlip ball1, BallBlip ball2) { // Vector that is perpendicular to the tangent of the collision, and it points in the direction of object 1. Real // easy when dealing with spheres :) normal = ball2.Ball.Position - ball1.Ball.Position; // Remember this length normalMagnitude = normal.GetMagnitude(); // This needs to be returned as a unit vector normal.Divide(normalMagnitude); // Start them off as unit vectors pointOfContact1 = normal.Clone(); pointOfContact2 = normal.Clone(); // Finish (use the ratio of their radii) pointOfContact1.Multiply((ball1.Ball.Radius / (ball1.Ball.Radius + ball2.Ball.Radius)) * normalMagnitude); pointOfContact2.Multiply((ball2.Ball.Radius / (ball1.Ball.Radius + ball2.Ball.Radius)) * normalMagnitude * -1); // I want this one pointing the other direction // Now that I have the points of contact relative to the centers of position, I need to make them // relative to the centers of mass if (ball1.TorqueBall != null) { pointOfContact1.Subtract(ball1.TorqueBall.CenterOfMass); } if (ball2.TorqueBall != null) { pointOfContact2.Subtract(ball2.TorqueBall.CenterOfMass); } }
private void StoreMouseMove(int x, int y) { MyVector safe = new MyVector(); safe.X = UtilityCore.GetScaledValue(_multiplier * -1d, _multiplier, 0, this.Width, x); safe.Y = UtilityCore.GetScaledValue(_multiplier * -1d, _multiplier, 0, this.Height, y); double safeMultiplier = _multiplier * SAFEPERCENT; // I don't want to butt up against the multiplier, or store value will increase it on me if (safe.GetMagnitudeSquared() > safeMultiplier * safeMultiplier) { safe.BecomeUnitVector(); safe.Multiply(safeMultiplier); } StoreNewValue(safe.X, safe.Y, 0d); }