CoordinateSystemConverter.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <SceneAPI/SceneCore/Utilities/CoordinateSystemConverter.h>
  9. #include <AzCore/Math/Matrix3x3.h>
  10. namespace AZ::SceneAPI
  11. {
  12. // Default constructor, initializes so that it basically does no conversion.
  13. CoordinateSystemConverter::CoordinateSystemConverter()
  14. : m_sourceTransform(AZ::Transform::CreateIdentity())
  15. , m_targetTransform(AZ::Transform::CreateIdentity())
  16. , m_conversionTransform(AZ::Transform::CreateIdentity())
  17. , m_conversionTransformInversed(AZ::Transform::CreateIdentity())
  18. , m_needsConversion(false)
  19. , m_sourceRightHanded(CheckIfIsRightHanded(m_sourceTransform))
  20. , m_targetRightHanded(CheckIfIsRightHanded(m_targetTransform))
  21. {
  22. m_targetBasisIndices[0] = 0;
  23. m_targetBasisIndices[1] = 1;
  24. m_targetBasisIndices[2] = 2;
  25. }
  26. CoordinateSystemConverter::CoordinateSystemConverter(const AZ::Vector3 sourceBasisVectors[3], const AZ::Vector3 targetBasisVectors[3], const AZ::u32 targetBasisIndices[3])
  27. {
  28. const AZ::Matrix3x3 sourceMatrix3x3 = AZ::Matrix3x3::CreateFromColumns(sourceBasisVectors[0], sourceBasisVectors[1], sourceBasisVectors[2]);
  29. m_sourceTransform = AZ::Transform::CreateFromMatrix3x3(sourceMatrix3x3);
  30. AZ_Assert(m_sourceTransform.IsOrthogonal(), "Invalid source transformation, basis vectors have to be orthogonal.");
  31. const AZ::Matrix3x3 targetMatrix3x3 = AZ::Matrix3x3::CreateFromColumns(targetBasisVectors[0], targetBasisVectors[1], targetBasisVectors[2]);
  32. m_targetTransform = AZ::Transform::CreateFromMatrix3x3(targetMatrix3x3);
  33. AZ_Assert(m_targetTransform.IsOrthogonal(), "Invalid target transformation, basis vectors have to be orthogonal.");
  34. m_conversionTransform = m_targetTransform * m_sourceTransform.GetInverse();
  35. m_conversionTransformInversed = m_conversionTransform.GetInverse();
  36. m_targetBasisIndices[0] = targetBasisIndices[0];
  37. m_targetBasisIndices[1] = targetBasisIndices[1];
  38. m_targetBasisIndices[2] = targetBasisIndices[2];
  39. m_needsConversion = (m_sourceTransform != m_targetTransform);
  40. m_sourceRightHanded = CheckIfIsRightHanded(m_sourceTransform);
  41. m_targetRightHanded = CheckIfIsRightHanded(m_targetTransform);
  42. }
  43. const CoordinateSystemConverter CoordinateSystemConverter::CreateFromBasisVectors(const AZ::Vector3 sourceBasisVectors[3], const AZ::Vector3 targetBasisVectors[3], const AZ::u32 targetBasisIndices[3])
  44. {
  45. return CoordinateSystemConverter(sourceBasisVectors, targetBasisVectors, targetBasisIndices);
  46. }
  47. const CoordinateSystemConverter CoordinateSystemConverter::CreateFromTransforms(const AZ::Transform& sourceTransform, const AZ::Transform& targetTransform, const AZ::u32 targetBasisIndices[3])
  48. {
  49. AZ::Vector3 sourceBasisVectors[3];
  50. sourceBasisVectors[0] = sourceTransform.GetBasisX();
  51. sourceBasisVectors[1] = sourceTransform.GetBasisY();
  52. sourceBasisVectors[2] = sourceTransform.GetBasisZ();
  53. AZ::Vector3 targetBasisVectors[3];
  54. targetBasisVectors[0] = targetTransform.GetBasisX();
  55. targetBasisVectors[1] = targetTransform.GetBasisY();
  56. targetBasisVectors[2] = targetTransform.GetBasisZ();
  57. return CoordinateSystemConverter(sourceBasisVectors, targetBasisVectors, targetBasisIndices);
  58. }
  59. bool CoordinateSystemConverter::CheckIfIsRightHanded(const AZ::Transform& transform) const
  60. {
  61. const AZ::Vector3 right = transform.GetBasisX();
  62. const AZ::Vector3 up = transform.GetBasisY();
  63. const AZ::Vector3 forward = transform.GetBasisZ();
  64. return ((right.Cross(up)).Dot(forward) <= 0.0f);
  65. }
  66. //-------------------------------------------------------------------------
  67. // Conversions
  68. //-------------------------------------------------------------------------
  69. AZ::Quaternion CoordinateSystemConverter::ConvertQuaternion(const AZ::Quaternion& input) const
  70. {
  71. if (!m_needsConversion)
  72. {
  73. return input;
  74. }
  75. const AZ::Vector3 vec = ConvertVector3( input.GetImaginary() );
  76. float w = input.GetW();
  77. if (m_sourceRightHanded != m_targetRightHanded)
  78. {
  79. w = -w;
  80. }
  81. return AZ::Quaternion(vec.GetX(), vec.GetY(), vec.GetZ(), w);
  82. }
  83. AZ::Vector3 CoordinateSystemConverter::ConvertVector3(const AZ::Vector3& input) const
  84. {
  85. if (!m_needsConversion)
  86. {
  87. return input;
  88. }
  89. return m_conversionTransform.TransformPoint(input);
  90. }
  91. AZ::Transform CoordinateSystemConverter::ConvertTransform(const AZ::Transform& input) const
  92. {
  93. if (!m_needsConversion)
  94. {
  95. return input;
  96. }
  97. return input * m_conversionTransform;
  98. }
  99. AZ::Matrix3x4 CoordinateSystemConverter::ConvertMatrix3x4(const AZ::Matrix3x4 & input) const
  100. {
  101. if (!m_needsConversion)
  102. {
  103. return input;
  104. }
  105. return input * AZ::Matrix3x4::CreateFromTransform(m_conversionTransform);
  106. }
  107. // Convert a scale value, which never flips some axis or so, just switches them.
  108. // Think of two coordinate systems, where for example the Z axis is inverted in one of them, the scale will remain the same, in both systems.
  109. // However, if we swap Y and Z, the scale Y and Z still have to be swapped.
  110. AZ::Vector3 CoordinateSystemConverter::ConvertScale(const AZ::Vector3& input) const
  111. {
  112. if (!m_needsConversion)
  113. {
  114. return input;
  115. }
  116. return AZ::Vector3( input.GetElement(m_targetBasisIndices[0]),
  117. input.GetElement(m_targetBasisIndices[1]),
  118. input.GetElement(m_targetBasisIndices[2]) );
  119. }
  120. //-------------------------------------------------------------------------
  121. // Inverse Conversions
  122. //-------------------------------------------------------------------------
  123. AZ::Quaternion CoordinateSystemConverter::InverseConvertQuaternion(const AZ::Quaternion& input) const
  124. {
  125. if (!m_needsConversion)
  126. {
  127. return input;
  128. }
  129. const AZ::Vector3 vec = InverseConvertVector3( input.GetImaginary() );
  130. float w = input.GetW();
  131. if (m_sourceRightHanded != m_targetRightHanded)
  132. {
  133. w = -w;
  134. }
  135. return AZ::Quaternion(vec.GetX(), vec.GetY(), vec.GetZ(), w);
  136. }
  137. AZ::Vector3 CoordinateSystemConverter::InverseConvertVector3(const AZ::Vector3& input) const
  138. {
  139. if (!m_needsConversion)
  140. {
  141. return input;
  142. }
  143. return m_conversionTransformInversed.TransformPoint(input);
  144. }
  145. AZ::Transform CoordinateSystemConverter::InverseConvertTransform(const AZ::Transform& input) const
  146. {
  147. if (!m_needsConversion)
  148. {
  149. return input;
  150. }
  151. return input * m_conversionTransformInversed;
  152. }
  153. AZ::Vector3 CoordinateSystemConverter::InverseConvertScale(const AZ::Vector3& input) const
  154. {
  155. return ConvertScale(input);
  156. }
  157. } // namespace AZ::SceneAPI