94 lines
4.6 KiB
C#
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 |