145 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			145 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using UnityEngine;
 | 
						|
 | 
						|
namespace Passer {
 | 
						|
 | 
						|
    public static class UnityAngles {
 | 
						|
        // Clamp all vector axis between the given min and max values
 | 
						|
        // Angles are normalized
 | 
						|
        public static Vector3 Clamp(Vector3 angles, Vector3 min, Vector3 max) {
 | 
						|
            float x = Clamp(angles.x, min.x, max.x);
 | 
						|
            float y = Clamp(angles.y, min.y, max.y);
 | 
						|
            float z = Clamp(angles.z, min.z, max.z);
 | 
						|
            return new Vector3(x, y, z);
 | 
						|
        }
 | 
						|
 | 
						|
        // clamp the angle between the given min and max values
 | 
						|
        // Angles are normalized
 | 
						|
        public static float Clamp(float angle, float min, float max) {
 | 
						|
            float normalizedAngle = Normalize(angle);
 | 
						|
            return Mathf.Clamp(normalizedAngle, min, max);
 | 
						|
        }
 | 
						|
 | 
						|
        // Determine the angle difference, result is a normalized angle
 | 
						|
        public static float Difference(float a, float b) {
 | 
						|
            float r = Normalize(b - a);
 | 
						|
            return r;
 | 
						|
        }
 | 
						|
 | 
						|
        // Normalize an angle to the range -180 < angle <= 180
 | 
						|
        public static float Normalize(float angle) {
 | 
						|
            while (angle <= -180) angle += 360;
 | 
						|
            while (angle > 180) angle -= 360;
 | 
						|
            return angle;
 | 
						|
        }
 | 
						|
 | 
						|
        // Normalize all vector angles to the range -180 < angle < 180
 | 
						|
        public static Vector3 Normalize(Vector3 angles) {
 | 
						|
            float x = Normalize(angles.x);
 | 
						|
            float y = Normalize(angles.y);
 | 
						|
            float z = Normalize(angles.z);
 | 
						|
            return new Vector3(x, y, z);
 | 
						|
        }
 | 
						|
 | 
						|
        // Returns the signed angle in degrees between from and to.
 | 
						|
        public static float SignedAngle(Vector3 from, Vector3 to) {
 | 
						|
            float angle = Vector3.Angle(from, to);
 | 
						|
            Vector3 cross = Vector3.Cross(from, to);
 | 
						|
            if (cross.y < 0) angle = -angle;
 | 
						|
            return angle;
 | 
						|
        }
 | 
						|
 | 
						|
        // Returns the signed angle in degrees between from and to.
 | 
						|
        public static float SignedAngle(Vector2 from, Vector2 to) {
 | 
						|
            float sign = Mathf.Sign(from.y * to.x - from.x * to.y);
 | 
						|
            return Vector2.Angle(from, to) * sign;
 | 
						|
        }
 | 
						|
 | 
						|
        //public static Quaternion ToQuaternion(Rotation orientation) {
 | 
						|
        //    return new Quaternion(orientation.x, orientation.y, orientation.z, orientation.w);
 | 
						|
        //}
 | 
						|
    }
 | 
						|
 | 
						|
    public static class Rotations {
 | 
						|
        /// <summary>
 | 
						|
        /// Rotate a rotation.
 | 
						|
        /// Rotates rotation1 according to rotation2.
 | 
						|
        /// This is needed, because rotation1 * rotation2 rotates the orientation.
 | 
						|
        /// </summary>
 | 
						|
        /// <param name="rotation1">The rotation to rotate</param>
 | 
						|
        /// <param name="rotation2">The rotation</param>
 | 
						|
        /// <returns></returns>
 | 
						|
        public static Quaternion Rotate(Quaternion rotation1, Quaternion rotation2) {
 | 
						|
            float angle;
 | 
						|
            Vector3 axis;
 | 
						|
            rotation1.ToAngleAxis(out angle, out axis);
 | 
						|
 | 
						|
            Vector3 newAxis = rotation2 * axis;
 | 
						|
            Quaternion newRotation1 = Quaternion.AngleAxis(angle, newAxis);
 | 
						|
 | 
						|
            return newRotation1;
 | 
						|
        }
 | 
						|
 | 
						|
        public static void ToSwingTwist(this Quaternion q, Vector3 twistAxis, out Quaternion swing, out Quaternion twist) {
 | 
						|
            Vector3 r = new Vector3(q.x, q.y, q.z);
 | 
						|
 | 
						|
            // singularity: rotation by 180 degree
 | 
						|
            if (r.sqrMagnitude < Mathf.Epsilon) {
 | 
						|
                Vector3 rotatedTwistAxis = q * twistAxis;
 | 
						|
                Vector3 swingAxis =
 | 
						|
                  Vector3.Cross(twistAxis, rotatedTwistAxis);
 | 
						|
 | 
						|
                if (swingAxis.sqrMagnitude > Mathf.Epsilon) {
 | 
						|
                    float swingAngle =
 | 
						|
                      Vector3.Angle(twistAxis, rotatedTwistAxis);
 | 
						|
                    swing = Quaternion.AngleAxis(swingAngle, swingAxis);
 | 
						|
                }
 | 
						|
                else {
 | 
						|
                    // more singularity: 
 | 
						|
                    // rotation axis parallel to twist axis
 | 
						|
                    swing = Quaternion.identity; // no swing
 | 
						|
                }
 | 
						|
 | 
						|
                // always twist 180 degree on singularity
 | 
						|
                twist = Quaternion.AngleAxis(180.0f, twistAxis);
 | 
						|
                return;
 | 
						|
            }
 | 
						|
 | 
						|
            // meat of swing-twist decomposition
 | 
						|
            Vector3 p = Vector3.Project(r, twistAxis);
 | 
						|
            twist = new Quaternion(p.x, p.y, p.z, q.w);
 | 
						|
            twist = Quaternion.Normalize(twist);
 | 
						|
            swing = q * Quaternion.Inverse(twist);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    public static class Vectors {
 | 
						|
        public static float DistanceToRay(Ray ray, Vector3 point) {
 | 
						|
            return Vector3.Cross(ray.direction, point - ray.origin).magnitude;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    public static class Transforms {
 | 
						|
        // transform local rotation to world rotation
 | 
						|
        public static Quaternion TransformRotation(Transform transform, Quaternion localRotation) {
 | 
						|
            if (transform.parent == null)
 | 
						|
                return localRotation;
 | 
						|
            else
 | 
						|
                return transform.parent.rotation * localRotation;
 | 
						|
        }
 | 
						|
 | 
						|
        //
 | 
						|
        // Summary:
 | 
						|
        //     ///
 | 
						|
        //     Transforms rotation from local space to world space.
 | 
						|
        //     ///
 | 
						|
        //
 | 
						|
        // Parameters:
 | 
						|
        //   transform:
 | 
						|
        public static Quaternion InverseTransformRotation(Transform transform, Quaternion rotation) {
 | 
						|
            if (transform.parent == null)
 | 
						|
                return rotation;
 | 
						|
            else
 | 
						|
                return Quaternion.Inverse(transform.parent.rotation) * rotation;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
} |