AxisAlignment.cs 4.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. #if UNITY_EDITOR
  2. using UnityEngine;
  3. namespace O3DWB
  4. {
  5. public static class AxisAlignment
  6. {
  7. #region Public Static Functions
  8. public static void AlignObjectAxis(GameObject gameObject, CoordinateSystemAxis alignmentAxis, Vector3 destinationAxis)
  9. {
  10. Transform objectTransform = gameObject.transform;
  11. objectTransform.rotation = CalculateRotationQuaternionForAxisAlignment(objectTransform.rotation, alignmentAxis, destinationAxis);
  12. }
  13. public static void AlignObjectAxis(GameObject gameObject, AxisAlignmentSettings adjustmentSettings, Vector3 destinationAxis)
  14. {
  15. if (adjustmentSettings.IsEnabled)
  16. {
  17. Transform objectTransform = gameObject.transform;
  18. objectTransform.rotation = CalculateRotationQuaternionForAxisAlignment(objectTransform.rotation, adjustmentSettings.AlignmentAxis, destinationAxis);
  19. }
  20. }
  21. public static Quaternion CalculateRotationQuaternionForAxisAlignment(Quaternion currentRotation, CoordinateSystemAxis alignmentAxis, Vector3 destinationAxis)
  22. {
  23. TransformMatrix rotationMatrix = TransformMatrix.GetIdentity();
  24. rotationMatrix.Rotation = currentRotation;
  25. Vector3 axisToAlign = CoordinateSystemAxes.GetLocalVector(alignmentAxis, rotationMatrix);
  26. bool isAlignmentAxisNegative = CoordinateSystemAxes.IsNegativeAxis(alignmentAxis);
  27. // Already aligned?
  28. bool pointsInSameDirection;
  29. bool isAlignedWithDestinationAxis = destinationAxis.IsAlignedWith(axisToAlign, out pointsInSameDirection);
  30. if (isAlignedWithDestinationAxis && pointsInSameDirection) return currentRotation;
  31. if (!isAlignedWithDestinationAxis)
  32. {
  33. Vector3 rotationAxis = Vector3.Cross(axisToAlign, destinationAxis);
  34. rotationAxis.Normalize();
  35. return Quaternion.AngleAxis(axisToAlign.AngleWith(destinationAxis), rotationAxis) * currentRotation;
  36. }
  37. else
  38. {
  39. // If this point is reached, it means the axis is aligned with the destination axis but points in the opposite
  40. // direction. In this case we can not use the cross product, so we will have to regenerate the axes.
  41. Vector3 newRightAxis, newUpAxis, newLookAxis;
  42. if (alignmentAxis == CoordinateSystemAxis.PositiveRight || alignmentAxis == CoordinateSystemAxis.NegativeRight)
  43. {
  44. newRightAxis = destinationAxis;
  45. if (isAlignmentAxisNegative) newRightAxis *= -1.0f;
  46. bool worldUpPointsSameDirAsRightAxis;
  47. if (newRightAxis.IsAlignedWith(Vector3.up, out worldUpPointsSameDirAsRightAxis)) newLookAxis = worldUpPointsSameDirAsRightAxis ? Vector3.forward : Vector3.back;
  48. else newLookAxis = Vector3.Cross(newRightAxis, Vector3.up);
  49. if (isAlignmentAxisNegative) newLookAxis *= -1.0f;
  50. newUpAxis = Vector3.Cross(newLookAxis, newRightAxis);
  51. }
  52. if (alignmentAxis == CoordinateSystemAxis.PositiveUp || alignmentAxis == CoordinateSystemAxis.NegativeUp)
  53. {
  54. newUpAxis = destinationAxis;
  55. if (isAlignmentAxisNegative) newUpAxis *= -1.0f;
  56. bool worldUpPointsSameDirAsUpAxis;
  57. if (newUpAxis.IsAlignedWith(Vector3.up, out worldUpPointsSameDirAsUpAxis)) newLookAxis = worldUpPointsSameDirAsUpAxis ? Vector3.forward : Vector3.back;
  58. else newLookAxis = Vector3.Cross(newUpAxis, Vector3.up);
  59. if (isAlignmentAxisNegative) newLookAxis *= -1.0f;
  60. }
  61. else
  62. {
  63. newLookAxis = destinationAxis;
  64. if (isAlignmentAxisNegative) newLookAxis *= -1.0f;
  65. bool worldUpPointsSameDirAsLookAxis;
  66. if (newLookAxis.IsAlignedWith(Vector3.up, out worldUpPointsSameDirAsLookAxis)) newUpAxis = worldUpPointsSameDirAsLookAxis ? Vector3.forward : Vector3.back;
  67. else newUpAxis = Vector3.Cross(newLookAxis, Vector3.up);
  68. if (isAlignmentAxisNegative) newUpAxis *= -1.0f;
  69. }
  70. // Normalize the axes which were calculated
  71. newUpAxis.Normalize();
  72. newLookAxis.Normalize();
  73. // Now use the axes to calculate the rotation quaternion
  74. return Quaternion.LookRotation(newLookAxis, newUpAxis);
  75. }
  76. }
  77. #endregion
  78. }
  79. }
  80. #endif