Last active
December 4, 2024 23:25
-
-
Save insominx/eef82673c88c2b5f9224473bacf162c4 to your computer and use it in GitHub Desktop.
Functions for getting and applying inverse transforms
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
/// <summary> | |
/// Provides utility methods for inverting transforms in Unity. | |
/// </summary> | |
public static class TransformInverter | |
{ | |
/// <summary> | |
/// Inverts the local transform of the target based on the source transform. | |
/// Equivalent to the LocalInvert method in the original MonoBehaviour. | |
/// </summary> | |
/// <param name="target">The Transform to apply the inversion to.</param> | |
/// <param name="source">The Transform to take the inverse from.</param> | |
public static void InvertLocal(Transform target, Transform source) | |
{ | |
if (source == null || target == null) | |
{ | |
Debug.LogWarning("InvertLocal: Source or target transform is null."); | |
return; | |
} | |
// Get the source's local transform components | |
Vector3 sourceLocalPosition = source.localPosition; | |
Quaternion sourceLocalRotation = source.localRotation; | |
Vector3 sourceLocalScale = source.localScale; | |
// Invert the scale | |
Vector3 inverseScale = new Vector3( | |
sourceLocalScale.x != 0 ? 1f / sourceLocalScale.x : 0, | |
sourceLocalScale.y != 0 ? 1f / sourceLocalScale.y : 0, | |
sourceLocalScale.z != 0 ? 1f / sourceLocalScale.z : 0 | |
); | |
target.localScale = inverseScale; | |
// Invert the rotation | |
Quaternion inverseRotation = Quaternion.Inverse(sourceLocalRotation); | |
target.localRotation = inverseRotation; | |
// Invert the position | |
Vector3 scaledPosition = Vector3.Scale(inverseScale, sourceLocalPosition); | |
Vector3 rotatedPosition = inverseRotation * scaledPosition; | |
Vector3 inversePosition = -rotatedPosition; | |
target.localPosition = inversePosition; | |
} | |
/// <summary> | |
/// Inverts the global (world) transform of the target based on the source transform. | |
/// Equivalent to the GlobalInvert method in the original MonoBehaviour. | |
/// </summary> | |
/// <param name="target">The Transform to apply the inversion to.</param> | |
/// <param name="source">The Transform to take the inverse from.</param> | |
public static void InvertGlobal(Transform target, Transform source) | |
{ | |
if (source == null || target == null) | |
{ | |
Debug.LogWarning("InvertGlobal: Source or target transform is null."); | |
return; | |
} | |
// Get the source's world transform components | |
Vector3 sourceWorldPosition = source.position; | |
Quaternion sourceWorldRotation = source.rotation; | |
Vector3 sourceWorldScale = source.lossyScale; | |
// Invert the scale | |
Vector3 inverseScale = new Vector3( | |
sourceWorldScale.x != 0 ? 1f / sourceWorldScale.x : 0, | |
sourceWorldScale.y != 0 ? 1f / sourceWorldScale.y : 0, | |
sourceWorldScale.z != 0 ? 1f / sourceWorldScale.z : 0 | |
); | |
target.localScale = inverseScale; | |
// Invert the rotation | |
Quaternion inverseRotation = Quaternion.Inverse(sourceWorldRotation); | |
target.rotation = inverseRotation; | |
// Invert the position | |
Vector3 scaledPosition = Vector3.Scale(inverseScale, sourceWorldPosition); | |
Vector3 rotatedPosition = inverseRotation * scaledPosition; | |
Vector3 inversePosition = -rotatedPosition; | |
target.position = inversePosition; | |
} | |
/// <summary> | |
/// Retrieves the inverse local transform components based on the source transform. | |
/// </summary> | |
/// <param name="source">The Transform to take the inverse from.</param> | |
/// <param name="inversePosition">Output inverse local position.</param> | |
/// <param name="inverseRotation">Output inverse local rotation.</param> | |
/// <param name="inverseScale">Output inverse local scale.</param> | |
public static void GetInverseLocal(Transform source, out Vector3 inversePosition, out Quaternion inverseRotation, out Vector3 inverseScale) | |
{ | |
if (source == null) | |
{ | |
Debug.LogWarning("GetInverseLocal: Source transform is null."); | |
inversePosition = Vector3.zero; | |
inverseRotation = Quaternion.identity; | |
inverseScale = Vector3.one; | |
return; | |
} | |
// Get the source's local transform components | |
Vector3 sourceLocalPosition = source.localPosition; | |
Quaternion sourceLocalRotation = source.localRotation; | |
Vector3 sourceLocalScale = source.localScale; | |
// Invert the scale | |
inverseScale = new Vector3( | |
sourceLocalScale.x != 0 ? 1f / sourceLocalScale.x : 0, | |
sourceLocalScale.y != 0 ? 1f / sourceLocalScale.y : 0, | |
sourceLocalScale.z != 0 ? 1f / sourceLocalScale.z : 0 | |
); | |
// Invert the rotation | |
inverseRotation = Quaternion.Inverse(sourceLocalRotation); | |
// Invert the position | |
Vector3 scaledPosition = Vector3.Scale(inverseScale, sourceLocalPosition); | |
Vector3 rotatedPosition = inverseRotation * scaledPosition; | |
inversePosition = -rotatedPosition; | |
} | |
/// <summary> | |
/// Retrieves the inverse global (world) transform components based on the source transform. | |
/// </summary> | |
/// <param name="source">The Transform to take the inverse from.</param> | |
/// <param name="inversePosition">Output inverse world position.</param> | |
/// <param name="inverseRotation">Output inverse world rotation.</param> | |
/// <param name="inverseScale">Output inverse world scale.</param> | |
public static void GetInverseGlobal(Transform source, out Vector3 inversePosition, out Quaternion inverseRotation, out Vector3 inverseScale) | |
{ | |
if (source == null) | |
{ | |
Debug.LogWarning("GetInverseGlobal: Source transform is null."); | |
inversePosition = Vector3.zero; | |
inverseRotation = Quaternion.identity; | |
inverseScale = Vector3.one; | |
return; | |
} | |
// Get the source's world transform components | |
Vector3 sourceWorldPosition = source.position; | |
Quaternion sourceWorldRotation = source.rotation; | |
Vector3 sourceWorldScale = source.lossyScale; | |
// Invert the scale | |
inverseScale = new Vector3( | |
sourceWorldScale.x != 0 ? 1f / sourceWorldScale.x : 0, | |
sourceWorldScale.y != 0 ? 1f / sourceWorldScale.y : 0, | |
sourceWorldScale.z != 0 ? 1f / sourceWorldScale.z : 0 | |
); | |
// Invert the rotation | |
inverseRotation = Quaternion.Inverse(sourceWorldRotation); | |
// Invert the position | |
Vector3 scaledPosition = Vector3.Scale(inverseScale, sourceWorldPosition); | |
Vector3 rotatedPosition = inverseRotation * scaledPosition; | |
inversePosition = -rotatedPosition; | |
} | |
/// <summary> | |
/// Retrieves the inverse local transform as a TransformData structure based on the source transform. | |
/// </summary> | |
/// <param name="source">The Transform to take the inverse from.</param> | |
/// <returns>A TransformData struct containing the inverse position, rotation, and scale.</returns> | |
public static TransformData GetInverseLocal(Transform source) | |
{ | |
GetInverseLocal(source, out Vector3 inversePosition, out Quaternion inverseRotation, out Vector3 inverseScale); | |
return new TransformData(inversePosition, inverseRotation, inverseScale); | |
} | |
/// <summary> | |
/// Retrieves the inverse global (world) transform as a TransformData structure based on the source transform. | |
/// </summary> | |
/// <param name="source">The Transform to take the inverse from.</param> | |
/// <returns>A TransformData struct containing the inverse position, rotation, and scale.</returns> | |
public static TransformData GetInverseGlobal(Transform source) | |
{ | |
GetInverseGlobal(source, out Vector3 inversePosition, out Quaternion inverseRotation, out Vector3 inverseScale); | |
return new TransformData(inversePosition, inverseRotation, inverseScale); | |
} | |
/// <summary> | |
/// Represents a set of transformation data: position, rotation, and scale. | |
/// </summary> | |
public struct TransformData | |
{ | |
public Vector3 Position; | |
public Quaternion Rotation; | |
public Vector3 Scale; | |
/// <summary> | |
/// Initializes a new instance of the TransformData struct. | |
/// </summary> | |
/// <param name="position">The position component.</param> | |
/// <param name="rotation">The rotation component.</param> | |
/// <param name="scale">The scale component.</param> | |
public TransformData(Vector3 position, Quaternion rotation, Vector3 scale) | |
{ | |
Position = position; | |
Rotation = rotation; | |
Scale = scale; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment