Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using UnityEngine;
- using System.Collections;
- namespace RootMotion.FinalIK {
- /// <summary>
- /// The base abstract class for all Rotation limits. Contains common functionality and static helper methods
- /// </summary>
- public abstract class RotationLimit : MonoBehaviour {
- #region Main Interface
- /// <summary>
- /// The main axis of the rotation limit.
- /// </summary>
- public Vector3 axis = Vector3.forward;
- /// <summary>
- /// Map the zero rotation point to the current rotation
- /// </summary>
- public void SetDefaultLocalRotation() {
- defaultLocalRotation = transform.localRotation;
- }
- /// <summary>
- /// Returns the limited local rotation.
- /// </summary>
- public Quaternion GetLimitedLocalRotation(Quaternion localRotation, out bool changed) {
- // Making sure the Rotation Limit is initiated
- if (!initiated) Awake ();
- // Subtracting defaultLocalRotation
- Quaternion rotation = Quaternion.Inverse(defaultLocalRotation) * localRotation;
- Quaternion limitedRotation = LimitRotation(rotation);
- changed = limitedRotation != rotation;
- if (!changed) return localRotation;
- // Apply defaultLocalRotation back on
- return defaultLocalRotation * limitedRotation;
- }
- /// <summary>
- /// Apply the rotation limit to transform.localRotation. Returns true if the limit has changed the rotation.
- /// </summary>
- public bool Apply() {
- bool changed = false;
- transform.localRotation = GetLimitedLocalRotation(transform.localRotation, out changed);
- return changed;
- }
- /// <summary>
- /// Disable this instance making sure it is initiated. Use this if you intend to manually control the updating of this Rotation Limit.
- /// </summary>
- public void Disable() {
- if (initiated) {
- enabled = false;
- return;
- }
- Awake();
- enabled = false;
- }
- #endregion Main Interface
- /*
- * An arbitrary secondary axis that we get by simply switching the axes
- * */
- public Vector3 secondaryAxis { get { return new Vector3(axis.y, axis.z ,axis.x); }}
- /*
- * Cross product of axis and secondaryAxis
- * */
- public Vector3 crossAxis { get { return Vector3.Cross(axis, secondaryAxis); }}
- /*
- * The default local rotation of the gameobject. By default stored in Awake.
- * */
- [HideInInspector] public Quaternion defaultLocalRotation;
- protected abstract Quaternion LimitRotation(Quaternion rotation);
- private bool initiated;
- private bool applicationQuit;
- /*
- * Initiating the Rotation Limit
- * */
- void Awake() {
- // Store the local rotation to map the zero rotation point to the current rotation
- SetDefaultLocalRotation();
- if (axis == Vector3.zero) Debug.LogError("Axis is Vector3.zero.");
- initiated = true;
- }
- /*
- * Using LateUpdate here because you most probably want to apply the limits after animation.
- * If you need precise control over the execution order, disable this script and call Apply() whenever you need
- * */
- void LateUpdate() {
- Apply();
- }
- /*
- * Logs the warning if no other warning has beed logged in this session.
- * */
- public void LogWarning(string message) {
- Warning.Log(message, transform);
- }
- #region Static helper methods for all Rotation Limits
- /*
- * Limits rotation to a single degree of freedom (along axis)
- * */
- protected static Quaternion Limit1DOF(Quaternion rotation, Vector3 axis) {
- return Quaternion.FromToRotation(rotation * axis, axis) * rotation;
- }
- /*
- * Applies uniform twist limit to the rotation
- * */
- protected static Quaternion LimitTwist(Quaternion rotation, Vector3 axis, Vector3 orthoAxis, float twistLimit) {
- twistLimit = Mathf.Clamp(twistLimit, 0, 180);
- if (twistLimit >= 180) return rotation;
- Vector3 normal = rotation * axis;
- Vector3 orthoTangent = orthoAxis;
- Vector3.OrthoNormalize(ref normal, ref orthoTangent);
- Vector3 rotatedOrthoTangent = rotation * orthoAxis;
- Vector3.OrthoNormalize(ref normal, ref rotatedOrthoTangent);
- Quaternion fixedRotation = Quaternion.FromToRotation(rotatedOrthoTangent, orthoTangent) * rotation;
- if (twistLimit <= 0) return fixedRotation;
- // Rotate from zero twist to free twist by the limited angle
- return Quaternion.RotateTowards(fixedRotation, rotation, twistLimit);
- }
- /*
- * Returns the angle between two vectors on a plane with the specified normal
- * */
- protected static float GetOrthogonalAngle(Vector3 v1, Vector3 v2, Vector3 normal) {
- Vector3.OrthoNormalize(ref normal, ref v1);
- Vector3.OrthoNormalize(ref normal, ref v2);
- return Vector3.Angle(v1, v2);
- }
- #endregion
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement