_EagleOwle_

RotationLimit

Dec 9th, 2018
145
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. using UnityEngine;
  2. using System.Collections;
  3.  
  4. namespace RootMotion.FinalIK {
  5.  
  6.     /// <summary>
  7.     /// The base abstract class for all Rotation limits. Contains common functionality and static helper methods
  8.     /// </summary>
  9.     public abstract class RotationLimit : MonoBehaviour {
  10.        
  11.         #region Main Interface
  12.        
  13.         /// <summary>
  14.         /// The main axis of the rotation limit.
  15.         /// </summary>
  16.         public Vector3 axis = Vector3.forward;
  17.        
  18.         /// <summary>
  19.         /// Map the zero rotation point to the current rotation
  20.         /// </summary>
  21.         public void SetDefaultLocalRotation() {
  22.             defaultLocalRotation = transform.localRotation;
  23.         }
  24.  
  25.         /// <summary>
  26.         /// Returns the limited local rotation.
  27.         /// </summary>
  28.         public Quaternion GetLimitedLocalRotation(Quaternion localRotation, out bool changed) {
  29.             // Making sure the Rotation Limit is initiated
  30.             if (!initiated) Awake ();
  31.            
  32.             // Subtracting defaultLocalRotation
  33.             Quaternion rotation = Quaternion.Inverse(defaultLocalRotation) * localRotation;
  34.            
  35.             Quaternion limitedRotation = LimitRotation(rotation);
  36.             changed = limitedRotation != rotation;
  37.  
  38.             if (!changed) return localRotation;
  39.  
  40.             // Apply defaultLocalRotation back on
  41.             return defaultLocalRotation * limitedRotation;
  42.         }
  43.        
  44.         /// <summary>
  45.         /// Apply the rotation limit to transform.localRotation. Returns true if the limit has changed the rotation.
  46.         /// </summary>
  47.         public bool Apply() {
  48.             bool changed = false;
  49.  
  50.             transform.localRotation = GetLimitedLocalRotation(transform.localRotation, out changed);
  51.  
  52.             return changed;
  53.         }
  54.  
  55.         /// <summary>
  56.         /// Disable this instance making sure it is initiated. Use this if you intend to manually control the updating of this Rotation Limit.
  57.         /// </summary>
  58.         public void Disable() {
  59.             if (initiated) {
  60.                 enabled = false;
  61.                 return;
  62.             }
  63.  
  64.             Awake();
  65.             enabled = false;
  66.         }
  67.        
  68.         #endregion Main Interface
  69.        
  70.         /*
  71.          * An arbitrary secondary axis that we get by simply switching the axes
  72.          * */
  73.         public Vector3 secondaryAxis { get { return new Vector3(axis.y, axis.z ,axis.x); }}
  74.  
  75.         /*
  76.          * Cross product of axis and secondaryAxis
  77.          * */
  78.         public Vector3 crossAxis { get { return Vector3.Cross(axis, secondaryAxis); }}
  79.        
  80.         /*
  81.          * The default local rotation of the gameobject. By default stored in Awake.
  82.          * */
  83.         [HideInInspector] public Quaternion defaultLocalRotation;
  84.        
  85.         protected abstract Quaternion LimitRotation(Quaternion rotation);
  86.        
  87.         private bool initiated;
  88.         private bool applicationQuit;
  89.        
  90.         /*
  91.          * Initiating the Rotation Limit
  92.          * */
  93.         void Awake() {
  94.             // Store the local rotation to map the zero rotation point to the current rotation
  95.             SetDefaultLocalRotation();
  96.                
  97.             if (axis == Vector3.zero) Debug.LogError("Axis is Vector3.zero.");
  98.             initiated = true;
  99.         }
  100.  
  101.         /*
  102.          * Using LateUpdate here because you most probably want to apply the limits after animation.
  103.          * If you need precise control over the execution order, disable this script and call Apply() whenever you need
  104.          * */
  105.         void LateUpdate() {
  106.             Apply();
  107.         }
  108.        
  109.         /*
  110.          * Logs the warning if no other warning has beed logged in this session.
  111.          * */
  112.         public void LogWarning(string message) {
  113.             Warning.Log(message, transform);
  114.         }
  115.        
  116.         #region Static helper methods for all Rotation Limits
  117.        
  118.         /*
  119.          * Limits rotation to a single degree of freedom (along axis)
  120.          * */
  121.         protected static Quaternion Limit1DOF(Quaternion rotation, Vector3 axis) {
  122.             return Quaternion.FromToRotation(rotation * axis, axis) * rotation;
  123.         }
  124.  
  125.         /*
  126.          * Applies uniform twist limit to the rotation
  127.          * */
  128.         protected static Quaternion LimitTwist(Quaternion rotation, Vector3 axis, Vector3 orthoAxis, float twistLimit) {
  129.             twistLimit = Mathf.Clamp(twistLimit, 0, 180);
  130.             if (twistLimit >= 180) return rotation;
  131.            
  132.             Vector3 normal = rotation * axis;
  133.             Vector3 orthoTangent = orthoAxis;
  134.             Vector3.OrthoNormalize(ref normal, ref orthoTangent);
  135.            
  136.             Vector3 rotatedOrthoTangent = rotation * orthoAxis;
  137.             Vector3.OrthoNormalize(ref normal, ref rotatedOrthoTangent);
  138.            
  139.             Quaternion fixedRotation = Quaternion.FromToRotation(rotatedOrthoTangent, orthoTangent) * rotation;
  140.            
  141.             if (twistLimit <= 0) return fixedRotation;
  142.            
  143.             // Rotate from zero twist to free twist by the limited angle
  144.             return Quaternion.RotateTowards(fixedRotation, rotation, twistLimit);
  145.         }
  146.        
  147.         /*
  148.          * Returns the angle between two vectors on a plane with the specified normal
  149.          * */
  150.         protected static float GetOrthogonalAngle(Vector3 v1, Vector3 v2, Vector3 normal) {
  151.             Vector3.OrthoNormalize(ref normal, ref v1);
  152.             Vector3.OrthoNormalize(ref normal, ref v2);
  153.             return Vector3.Angle(v1, v2);
  154.         }
  155.        
  156.         #endregion
  157.     }
  158. }
RAW Paste Data