ZeroVR/ZeroPacientVR/Assets/Octave3D World Builder/Scripts/Objects/Object Rotation/AxisAlignment.cs

94 lines
4.6 KiB
C#

#if UNITY_EDITOR
using UnityEngine;
namespace O3DWB
{
public static class AxisAlignment
{
#region Public Static Functions
public static void AlignObjectAxis(GameObject gameObject, CoordinateSystemAxis alignmentAxis, Vector3 destinationAxis)
{
Transform objectTransform = gameObject.transform;
objectTransform.rotation = CalculateRotationQuaternionForAxisAlignment(objectTransform.rotation, alignmentAxis, destinationAxis);
}
public static void AlignObjectAxis(GameObject gameObject, AxisAlignmentSettings adjustmentSettings, Vector3 destinationAxis)
{
if (adjustmentSettings.IsEnabled)
{
Transform objectTransform = gameObject.transform;
objectTransform.rotation = CalculateRotationQuaternionForAxisAlignment(objectTransform.rotation, adjustmentSettings.AlignmentAxis, destinationAxis);
}
}
public static Quaternion CalculateRotationQuaternionForAxisAlignment(Quaternion currentRotation, CoordinateSystemAxis alignmentAxis, Vector3 destinationAxis)
{
TransformMatrix rotationMatrix = TransformMatrix.GetIdentity();
rotationMatrix.Rotation = currentRotation;
Vector3 axisToAlign = CoordinateSystemAxes.GetLocalVector(alignmentAxis, rotationMatrix);
bool isAlignmentAxisNegative = CoordinateSystemAxes.IsNegativeAxis(alignmentAxis);
// Already aligned?
bool pointsInSameDirection;
bool isAlignedWithDestinationAxis = destinationAxis.IsAlignedWith(axisToAlign, out pointsInSameDirection);
if (isAlignedWithDestinationAxis && pointsInSameDirection) return currentRotation;
if (!isAlignedWithDestinationAxis)
{
Vector3 rotationAxis = Vector3.Cross(axisToAlign, destinationAxis);
rotationAxis.Normalize();
return Quaternion.AngleAxis(axisToAlign.AngleWith(destinationAxis), rotationAxis) * currentRotation;
}
else
{
// If this point is reached, it means the axis is aligned with the destination axis but points in the opposite
// direction. In this case we can not use the cross product, so we will have to regenerate the axes.
Vector3 newRightAxis, newUpAxis, newLookAxis;
if (alignmentAxis == CoordinateSystemAxis.PositiveRight || alignmentAxis == CoordinateSystemAxis.NegativeRight)
{
newRightAxis = destinationAxis;
if (isAlignmentAxisNegative) newRightAxis *= -1.0f;
bool worldUpPointsSameDirAsRightAxis;
if (newRightAxis.IsAlignedWith(Vector3.up, out worldUpPointsSameDirAsRightAxis)) newLookAxis = worldUpPointsSameDirAsRightAxis ? Vector3.forward : Vector3.back;
else newLookAxis = Vector3.Cross(newRightAxis, Vector3.up);
if (isAlignmentAxisNegative) newLookAxis *= -1.0f;
newUpAxis = Vector3.Cross(newLookAxis, newRightAxis);
}
if (alignmentAxis == CoordinateSystemAxis.PositiveUp || alignmentAxis == CoordinateSystemAxis.NegativeUp)
{
newUpAxis = destinationAxis;
if (isAlignmentAxisNegative) newUpAxis *= -1.0f;
bool worldUpPointsSameDirAsUpAxis;
if (newUpAxis.IsAlignedWith(Vector3.up, out worldUpPointsSameDirAsUpAxis)) newLookAxis = worldUpPointsSameDirAsUpAxis ? Vector3.forward : Vector3.back;
else newLookAxis = Vector3.Cross(newUpAxis, Vector3.up);
if (isAlignmentAxisNegative) newLookAxis *= -1.0f;
}
else
{
newLookAxis = destinationAxis;
if (isAlignmentAxisNegative) newLookAxis *= -1.0f;
bool worldUpPointsSameDirAsLookAxis;
if (newLookAxis.IsAlignedWith(Vector3.up, out worldUpPointsSameDirAsLookAxis)) newUpAxis = worldUpPointsSameDirAsLookAxis ? Vector3.forward : Vector3.back;
else newUpAxis = Vector3.Cross(newLookAxis, Vector3.up);
if (isAlignmentAxisNegative) newUpAxis *= -1.0f;
}
// Normalize the axes which were calculated
newUpAxis.Normalize();
newLookAxis.Normalize();
// Now use the axes to calculate the rotation quaternion
return Quaternion.LookRotation(newLookAxis, newUpAxis);
}
}
#endregion
}
}
#endif