# 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