BlendShapeData.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  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/Casting/numeric_cast.h>
  9. #include <SceneAPI/SceneData/GraphData/BlendShapeData.h>
  10. #include <AzCore/Serialization/SerializeContext.h>
  11. #include <AzCore/RTTI/BehaviorContext.h>
  12. #include <AzCore/std/containers/bitset.h>
  13. namespace AZ
  14. {
  15. AZ_TYPE_INFO_SPECIALIZE(SceneAPI::DataTypes::IBlendShapeData::Face, "{C972EC9A-3A5C-47CD-9A92-ECB4C0C0451C}");
  16. namespace SceneData
  17. {
  18. namespace GraphData
  19. {
  20. namespace DataTypes = SceneAPI::DataTypes;
  21. BlendShapeData::~BlendShapeData() = default;
  22. void BlendShapeData::Reflect(ReflectContext* context)
  23. {
  24. SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
  25. if (serializeContext)
  26. {
  27. serializeContext->Class<BlendShapeData, SceneAPI::DataTypes::IBlendShapeData>()
  28. ->Version(1);
  29. }
  30. BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context);
  31. if (behaviorContext)
  32. {
  33. behaviorContext->Class<SceneAPI::DataTypes::IBlendShapeData>()
  34. ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::ListOnly)
  35. ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
  36. ->Attribute(AZ::Script::Attributes::Module, "scene")
  37. ->Method("GetUsedControlPointCount", &SceneAPI::DataTypes::IBlendShapeData::GetUsedControlPointCount)
  38. ->Method("GetControlPointIndex", &SceneAPI::DataTypes::IBlendShapeData::GetControlPointIndex)
  39. ->Method("GetUsedPointIndexForControlPoint", &SceneAPI::DataTypes::IBlendShapeData::GetUsedPointIndexForControlPoint)
  40. ->Method("GetVertexCount", &SceneAPI::DataTypes::IBlendShapeData::GetVertexCount)
  41. ->Method("GetFaceCount", &SceneAPI::DataTypes::IBlendShapeData::GetFaceCount)
  42. ->Method("GetFaceInfo", &SceneAPI::DataTypes::IBlendShapeData::GetFaceInfo)
  43. ->Method("GetPosition", &SceneAPI::DataTypes::IBlendShapeData::GetPosition)
  44. ->Method("GetNormal", &SceneAPI::DataTypes::IBlendShapeData::GetNormal)
  45. ->Method("GetFaceVertexIndex", &SceneAPI::DataTypes::IBlendShapeData::GetFaceVertexIndex);
  46. behaviorContext->Class<SceneAPI::DataTypes::IBlendShapeData::Face>("BlendShapeDataFace")
  47. ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
  48. ->Attribute(AZ::Script::Attributes::Module, "scene")
  49. ->Method("GetVertexIndex", [](const SceneAPI::DataTypes::IBlendShapeData::Face& self, int index)
  50. {
  51. if (index >= 0 && index < 3)
  52. {
  53. return self.vertexIndex[index];
  54. }
  55. return aznumeric_cast<unsigned int>(0);
  56. });
  57. behaviorContext->Class<BlendShapeData>()
  58. ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
  59. ->Attribute(AZ::Script::Attributes::Module, "scene")
  60. ->Method("GetUV", &BlendShapeData::GetUV)
  61. ->Method("GetTangent", [](const BlendShapeData& self, size_t index)
  62. {
  63. if (index < self.GetTangents().size())
  64. {
  65. return self.GetTangents().at(index);
  66. }
  67. AZ_Error("SceneGraphData", false, "Cannot get to tangent at index(%zu)", index);
  68. return Vector4::CreateZero();
  69. })
  70. ->Method("GetBitangent", [](const BlendShapeData& self, size_t index)
  71. {
  72. if (index < self.GetBitangents().size())
  73. {
  74. return self.GetBitangents().at(index);
  75. }
  76. AZ_Error("SceneGraphData", false, "Cannot get to bitangents at index(%zu)", index);
  77. return Vector3::CreateZero();
  78. })
  79. ->Method("GetColor", [](const BlendShapeData& self, AZ::u8 colorSetIndex, AZ::u8 colorIndex)
  80. {
  81. SceneAPI::DataTypes::Color color(0,0,0,0);
  82. if (colorSetIndex < MaxNumColorSets)
  83. {
  84. const AZStd::vector<SceneAPI::DataTypes::Color>& colorChannel = self.GetColors(colorSetIndex);
  85. if (colorIndex < colorChannel.size())
  86. {
  87. return colorChannel[colorIndex];
  88. }
  89. }
  90. AZ_Error("SceneGraphData", false, "Cannot get to color setIndex(%d) at colorIndex(%d)", colorSetIndex, colorIndex);
  91. return color;
  92. });
  93. }
  94. }
  95. void BlendShapeData::AddPosition(const Vector3& position)
  96. {
  97. m_positions.push_back(position);
  98. }
  99. void BlendShapeData::AddNormal(const Vector3& normal)
  100. {
  101. m_normals.push_back(normal);
  102. }
  103. void BlendShapeData::AddTangentAndBitangent(const Vector4& tangent, const Vector3& bitangent)
  104. {
  105. m_tangents.push_back(tangent);
  106. m_bitangents.push_back(bitangent);
  107. }
  108. void BlendShapeData::AddUV(const Vector2& uv, AZ::u8 uvSetIndex)
  109. {
  110. if (uvSetIndex >= MaxNumUVSets)
  111. {
  112. AZ_ErrorOnce("SceneGraphData", false, "uvSetIndex %zu is greater or equal than the maximum uv sets %zu.", uvSetIndex, MaxNumUVSets);
  113. return;
  114. }
  115. m_uvs[uvSetIndex].push_back(uv);
  116. }
  117. void BlendShapeData::AddColor(const SceneAPI::DataTypes::Color& color, AZ::u8 colorSetIndex)
  118. {
  119. if (colorSetIndex >= MaxNumColorSets)
  120. {
  121. AZ_ErrorOnce("SceneGraphData", false, "colorSetIndex %zu is greater or equal than the maximum color sets %zu.", colorSetIndex, MaxNumColorSets);
  122. return;
  123. }
  124. m_colors[colorSetIndex].push_back(color);
  125. }
  126. void BlendShapeData::ReserveData(
  127. unsigned int numVertices, bool reserveTangents, const AZStd::bitset<MaxNumUVSets>& uvSetUsedFlags,
  128. const AZStd::bitset<MaxNumColorSets>& colorSetUsedFlags)
  129. {
  130. m_positions.reserve(numVertices);
  131. m_normals.reserve(numVertices);
  132. if (reserveTangents)
  133. {
  134. m_tangents.reserve(numVertices);
  135. m_bitangents.reserve(numVertices);
  136. }
  137. for (AZ::u8 uvSetIndex = 0; uvSetIndex < MaxNumUVSets; ++uvSetIndex)
  138. {
  139. if (uvSetUsedFlags[uvSetIndex])
  140. {
  141. m_uvs[uvSetIndex].reserve(numVertices);
  142. }
  143. }
  144. for (AZ::u8 colorSetIndex = 0; colorSetIndex < MaxNumColorSets; ++colorSetIndex)
  145. {
  146. if (colorSetUsedFlags[colorSetIndex])
  147. {
  148. m_colors[colorSetIndex].reserve(numVertices);
  149. }
  150. }
  151. }
  152. void BlendShapeData::AddFace(const Face& face)
  153. {
  154. m_faces.push_back(face);
  155. }
  156. void BlendShapeData::SetVertexIndexToControlPointIndexMap(int vertexIndex, int controlPointIndex)
  157. {
  158. m_vertexIndexToControlPointIndexMap[vertexIndex] = controlPointIndex;
  159. // The above hashmap stores the control point index (value) per vertex (key).
  160. // We construct an unordered set and fill in the control point indices in order to get access to the number of unique control points indices.
  161. m_controlPointToUsedVertexIndexMap.emplace(controlPointIndex, aznumeric_cast<unsigned int>(m_controlPointToUsedVertexIndexMap.size()));
  162. }
  163. int BlendShapeData::GetControlPointIndex(int vertexIndex) const
  164. {
  165. auto iter = m_vertexIndexToControlPointIndexMap.find(vertexIndex);
  166. AZ_Assert(iter != m_vertexIndexToControlPointIndexMap.end(), "Vertex index %i doesn't exist.", vertexIndex);
  167. // Note: AZStd::unordered_map's operator [] doesn't have const version...
  168. return iter->second;
  169. }
  170. size_t BlendShapeData::GetUsedControlPointCount() const
  171. {
  172. return m_controlPointToUsedVertexIndexMap.size();
  173. }
  174. int BlendShapeData::GetUsedPointIndexForControlPoint(int controlPointIndex) const
  175. {
  176. auto iter = m_controlPointToUsedVertexIndexMap.find(controlPointIndex);
  177. if (iter != m_controlPointToUsedVertexIndexMap.end())
  178. {
  179. return iter->second;
  180. }
  181. else
  182. {
  183. return -1; // That control point is not used in this mesh
  184. }
  185. }
  186. unsigned int BlendShapeData::GetVertexCount() const
  187. {
  188. return static_cast<unsigned int>(m_positions.size());
  189. }
  190. unsigned int BlendShapeData::GetFaceCount() const
  191. {
  192. return static_cast<unsigned int>(m_faces.size());
  193. }
  194. const BlendShapeData::Face& BlendShapeData::GetFaceInfo(unsigned int index) const
  195. {
  196. AZ_Assert(index < m_faces.size(), "GetFaceInfo index not in range");
  197. return m_faces[index];
  198. }
  199. const Vector3& BlendShapeData::GetPosition(unsigned int index) const
  200. {
  201. AZ_Assert(index < m_positions.size(), "GetPosition index not in range");
  202. return m_positions[index];
  203. }
  204. const Vector3& BlendShapeData::GetNormal(unsigned int index) const
  205. {
  206. AZ_Assert(index < m_normals.size(), "GetNormal index not in range");
  207. return m_normals[index];
  208. }
  209. const Vector2& BlendShapeData::GetUV(unsigned int vertexIndex, unsigned int uvSetIndex) const
  210. {
  211. AZ_Assert(uvSetIndex < MaxNumUVSets, "uvSet index out of range");
  212. AZ_Assert(vertexIndex < m_uvs[uvSetIndex].size(), "uvSet index out of range");
  213. return m_uvs[uvSetIndex][vertexIndex];
  214. }
  215. AZStd::vector<Vector4>& BlendShapeData::GetTangents()
  216. {
  217. return m_tangents;
  218. }
  219. const AZStd::vector<Vector4>& BlendShapeData::GetTangents() const
  220. {
  221. return m_tangents;
  222. }
  223. AZStd::vector<Vector3>& BlendShapeData::GetBitangents()
  224. {
  225. return m_bitangents;
  226. }
  227. const AZStd::vector<Vector3>& BlendShapeData::GetBitangents() const
  228. {
  229. return m_bitangents;
  230. }
  231. const AZStd::vector<Vector2>& BlendShapeData::GetUVs(AZ::u8 uvSetIndex) const
  232. {
  233. AZ_Assert(uvSetIndex < MaxNumUVSets, "uvSet index out of range");
  234. return m_uvs[uvSetIndex];
  235. }
  236. const AZStd::vector<SceneAPI::DataTypes::Color>& BlendShapeData::GetColors(AZ::u8 colorSetIndex) const
  237. {
  238. AZ_Assert(colorSetIndex < MaxNumColorSets, "colorSet index out of range");
  239. return m_colors[colorSetIndex];
  240. }
  241. unsigned int BlendShapeData::GetFaceVertexIndex(unsigned int face, unsigned int vertexIndex) const
  242. {
  243. AZ_Assert(face < m_faces.size(), "GetFaceVertexPositionIndex face index not in range");
  244. AZ_Assert(vertexIndex < 3, "GetFaceVertexPositionIndex vertexIndex index not in range");
  245. return m_faces[face].vertexIndex[vertexIndex];
  246. }
  247. void BlendShapeData::GetDebugOutput(SceneAPI::Utilities::DebugOutput& output) const
  248. {
  249. output.Write("Positions", m_positions);
  250. output.Write("Normals", m_normals);
  251. output.Write("Faces", m_faces);
  252. }
  253. } // GraphData
  254. } // SceneData
  255. } // AZ