SceneSystem.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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 <AzCore/Math/Vector3.h>
  9. #include <SceneAPI/SceneBuilder/SceneSystem.h>
  10. #include <SceneAPI/SceneCore/Utilities/Reporting.h>
  11. #include <SceneAPI/SDKWrapper/AssImpSceneWrapper.h>
  12. #include <SceneAPI/SDKWrapper/AssImpTypeConverter.h>
  13. #include <assimp/scene.h>
  14. namespace AZ
  15. {
  16. namespace SceneAPI
  17. {
  18. SceneSystem::SceneSystem() :
  19. m_unitSizeInMeters(1.0f),
  20. m_originalUnitSizeInMeters(1.0f),
  21. m_adjustTransform(nullptr),
  22. m_adjustTransformInverse(nullptr)
  23. {
  24. }
  25. void SceneSystem::Set(const SDKScene::SceneWrapperBase* scene)
  26. {
  27. // Get unit conversion factor to meter.
  28. if (!azrtti_istypeof<AssImpSDKWrapper::AssImpSceneWrapper>(scene))
  29. {
  30. return;
  31. }
  32. const AssImpSDKWrapper::AssImpSceneWrapper* assImpScene = azrtti_cast<const AssImpSDKWrapper::AssImpSceneWrapper*>(scene);
  33. /* Check if metadata has information about "UnitScaleFactor" or "OriginalUnitScaleFactor".
  34. * This particular metadata is FBX format only. */
  35. if (assImpScene->GetAssImpScene()->mMetaData->HasKey("UnitScaleFactor") ||
  36. assImpScene->GetAssImpScene()->mMetaData->HasKey("OriginalUnitScaleFactor"))
  37. {
  38. // If either metadata piece is not available, the default of 1 will be used.
  39. assImpScene->GetAssImpScene()->mMetaData->Get("UnitScaleFactor", m_unitSizeInMeters);
  40. assImpScene->GetAssImpScene()->mMetaData->Get("OriginalUnitScaleFactor", m_originalUnitSizeInMeters);
  41. /* Conversion factor for converting from centimeters to meters.
  42. * This applies to an FBX format in which the default unit is a centimeter. */
  43. m_unitSizeInMeters = m_unitSizeInMeters * .01f;
  44. }
  45. else
  46. {
  47. // Some file formats (like DAE) embed the scale in the root transformation, so extract that scale from here.
  48. auto rootTransform =
  49. AssImpSDKWrapper::AssImpTypeConverter::ToTransform(assImpScene->GetAssImpScene()->mRootNode->mTransformation);
  50. m_unitSizeInMeters = rootTransform.ExtractScale().GetMaxElement();
  51. }
  52. AZStd::pair<AssImpSDKWrapper::AssImpSceneWrapper::AxisVector, int32_t> upAxisAndSign = assImpScene->GetUpVectorAndSign();
  53. if (upAxisAndSign.second <= 0)
  54. {
  55. AZ_TracePrintf(SceneAPI::Utilities::ErrorWindow, "Negative scene orientation is not a currently supported orientation.");
  56. return;
  57. }
  58. AZStd::pair<AssImpSDKWrapper::AssImpSceneWrapper::AxisVector, int32_t> frontAxisAndSign = assImpScene->GetFrontVectorAndSign();
  59. if (upAxisAndSign.first != AssImpSDKWrapper::AssImpSceneWrapper::AxisVector::Z &&
  60. upAxisAndSign.first != AssImpSDKWrapper::AssImpSceneWrapper::AxisVector::Unknown)
  61. {
  62. AZ::Matrix4x4 currentCoordMatrix = AZ::Matrix4x4::CreateIdentity();
  63. //(UpVector = +Z, FrontVector = +Y, CoordSystem = -X(RightHanded))
  64. AZ::Matrix4x4 targetCoordMatrix = AZ::Matrix4x4::CreateFromColumns(
  65. AZ::Vector4(-1, 0, 0, 0),
  66. AZ::Vector4(0, 0, 1, 0),
  67. AZ::Vector4(0, 1, 0, 0),
  68. AZ::Vector4(0, 0, 0, 1));
  69. switch (upAxisAndSign.first)
  70. {
  71. case AssImpSDKWrapper::AssImpSceneWrapper::AxisVector::X: {
  72. if (frontAxisAndSign.second == 1)
  73. {
  74. currentCoordMatrix = AZ::Matrix4x4::CreateFromColumns(
  75. AZ::Vector4(0, -1, 0, 0),
  76. AZ::Vector4(1, 0, 0, 0),
  77. AZ::Vector4(0, 0, 1, 0),
  78. AZ::Vector4(0, 0, 0, 1));
  79. }
  80. else
  81. {
  82. currentCoordMatrix = AZ::Matrix4x4::CreateFromColumns(
  83. AZ::Vector4(0, 1, 0, 0),
  84. AZ::Vector4(1, 0, 0, 0),
  85. AZ::Vector4(0, 0, -1, 0),
  86. AZ::Vector4(0, 0, 0, 1));
  87. }
  88. }
  89. break;
  90. case AssImpSDKWrapper::AssImpSceneWrapper::AxisVector::Y: {
  91. if (frontAxisAndSign.second == 1)
  92. {
  93. currentCoordMatrix = AZ::Matrix4x4::CreateFromColumns(
  94. AZ::Vector4(1, 0, 0, 0),
  95. AZ::Vector4(0, 1, 0, 0),
  96. AZ::Vector4(0, 0, 1, 0),
  97. AZ::Vector4(0, 0, 0, 1));
  98. }
  99. else
  100. {
  101. currentCoordMatrix = AZ::Matrix4x4::CreateFromColumns(
  102. AZ::Vector4(-1, 0, 0, 0),
  103. AZ::Vector4(0, 1, 0, 0),
  104. AZ::Vector4(0, 0, -1, 0),
  105. AZ::Vector4(0, 0, 0, 1));
  106. }
  107. }
  108. break;
  109. }
  110. AZ::Matrix4x4 adjustmatrix = targetCoordMatrix * currentCoordMatrix.GetInverseTransform();
  111. m_adjustTransform.reset(new DataTypes::MatrixType(AssImpSDKWrapper::AssImpTypeConverter::ToTransform(adjustmatrix)));
  112. m_adjustTransformInverse.reset(new DataTypes::MatrixType(m_adjustTransform->GetInverseFull()));
  113. }
  114. }
  115. void SceneSystem::SwapVec3ForUpAxis(Vector3& swapVector) const
  116. {
  117. if (m_adjustTransform)
  118. {
  119. swapVector = *m_adjustTransform * swapVector;
  120. }
  121. }
  122. void SceneSystem::SwapTransformForUpAxis(DataTypes::MatrixType& inOutTransform) const
  123. {
  124. if (m_adjustTransform)
  125. {
  126. inOutTransform = (*m_adjustTransform * inOutTransform) * *m_adjustTransformInverse;
  127. }
  128. }
  129. void SceneSystem::ConvertUnit(Vector3& scaleVector) const
  130. {
  131. scaleVector *= m_unitSizeInMeters;
  132. }
  133. void SceneSystem::ConvertUnit(DataTypes::MatrixType& inOutTransform) const
  134. {
  135. Vector3 translation = inOutTransform.GetTranslation();
  136. translation *= m_unitSizeInMeters;
  137. inOutTransform.SetTranslation(translation);
  138. }
  139. void SceneSystem::ConvertBoneUnit(DataTypes::MatrixType& inOutTransform) const
  140. {
  141. // Need to scale translation explicitly as MultiplyByScale won't change the translation component
  142. // and we need to convert to meter unit
  143. Vector3 translation = inOutTransform.GetTranslation();
  144. translation *= m_unitSizeInMeters;
  145. inOutTransform.SetTranslation(translation);
  146. }
  147. }
  148. }