Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- void PointRotorAtVector(
- IMyMotorStator rotor, // Rotor of interest
- Vector3D targetDirection, // World direction to the target
- Vector3D currentDirection, // World direction of current orientation
- double proportionalGain) // Essentially how fast this thing will spin
- {
- // This is also the rotation axis of the rotor
- var upDirection = rotor.WorldMatrix.Up;
- // This removes any out-of-rotation-plane vector components
- var currentDirectionFlat = VectorMath.Rejection(currentDirection, upDirection);
- var targetDirectionFlat = VectorMath.Rejection(targetDirection, upDirection);
- // Get the unsigned angle between the target direction and current direction
- var angle = VectorMath.AngleBetween(currentDirectionFlat, targetDirectionFlat);
- // Get the sign of the angle
- var num = Vector3D.Dot(Vector3D.Cross(targetDirectionFlat, currentDirectionFlat), upDirection);
- num = num > 0 ? 1 : -1;
- rotor.TargetVelocityRPM = (float)(proportionalGain * angle * num);
- }
- public static class VectorMath
- {
- /// <summary>
- /// Normalizes a vector only if it is non-zero and non-unit
- /// </summary>
- public static Vector3D SafeNormalize(Vector3D a)
- {
- if (Vector3D.IsZero(a))
- return Vector3D.Zero;
- if (Vector3D.IsUnit(ref a))
- return a;
- return Vector3D.Normalize(a);
- }
- /// <summary>
- /// Reflects vector a over vector b with an optional rejection factor
- /// </summary>
- public static Vector3D Reflection(Vector3D a, Vector3D b, double rejectionFactor = 1) //reflect a over b
- {
- Vector3D project_a = Projection(a, b);
- Vector3D reject_a = a - project_a;
- return project_a - reject_a * rejectionFactor;
- }
- /// <summary>
- /// Rejects vector a on vector b
- /// </summary>
- public static Vector3D Rejection(Vector3D a, Vector3D b) //reject a on b
- {
- if (Vector3D.IsZero(a) || Vector3D.IsZero(b))
- return Vector3D.Zero;
- return a - a.Dot(b) / b.LengthSquared() * b;
- }
- /// <summary>
- /// Projects vector a onto vector b
- /// </summary>
- public static Vector3D Projection(Vector3D a, Vector3D b)
- {
- if (Vector3D.IsZero(a) || Vector3D.IsZero(b))
- return Vector3D.Zero;
- return a.Dot(b) / b.LengthSquared() * b;
- }
- /// <summary>
- /// Scalar projection of a onto b
- /// </summary>
- public static double ScalarProjection(Vector3D a, Vector3D b)
- {
- if (Vector3D.IsZero(a) || Vector3D.IsZero(b))
- return 0;
- if (Vector3D.IsUnit(ref b))
- return a.Dot(b);
- return a.Dot(b) / b.Length();
- }
- /// <summary>
- /// Computes angle between 2 vectors
- /// </summary>
- public static double AngleBetween(Vector3D a, Vector3D b) //returns radians
- {
- if (Vector3D.IsZero(a) || Vector3D.IsZero(b))
- return 0;
- else
- return Math.Acos(MathHelper.Clamp(a.Dot(b) / Math.Sqrt(a.LengthSquared() * b.LengthSquared()), -1, 1));
- }
- /// <summary>
- /// Computes cosine of the angle between 2 vectors
- /// </summary>
- public static double CosBetween(Vector3D a, Vector3D b, bool useSmallestAngle = false) //returns radians
- {
- if (Vector3D.IsZero(a) || Vector3D.IsZero(b))
- return 0;
- else
- return MathHelper.Clamp(a.Dot(b) / Math.Sqrt(a.LengthSquared() * b.LengthSquared()), -1, 1);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment