MeshBuilder.h 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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. #pragma once
  9. #include <AzCore/base.h>
  10. #include <AzCore/std/containers/vector.h>
  11. #include <AzCore/std/smart_ptr/unique_ptr.h>
  12. #include <AzCore/std/tuple.h>
  13. #include <AzCore/std/typetraits/is_convertible.h>
  14. #include <AzCore/std/typetraits/is_same.h>
  15. #include "MeshBuilderVertexAttributeLayers.h"
  16. #include "MeshBuilderSubMesh.h"
  17. #include "MeshBuilderSkinningInfo.h"
  18. namespace AZ::MeshBuilder
  19. {
  20. /*
  21. * Small usage tutorial:
  22. *
  23. * For all your vertex data types (position, normal, uvs etc)
  24. * AddLayer( layer );
  25. *
  26. * For all polygons inside a mesh you want to export
  27. * BeginPolygon( polyMaterialIndex )
  28. * For all added layers you added to the mesh
  29. * layer->SetCurrentVertexValue( )
  30. * AddPolygonVertex( originalVertexNr )
  31. * EndPolygon()
  32. *
  33. * OptimizeTriangleList()
  34. */
  35. class MeshBuilder
  36. {
  37. friend class MeshBuilderSubMesh;
  38. public:
  39. AZ_CLASS_ALLOCATOR_DECL
  40. explicit MeshBuilder(size_t numOrgVerts, bool optimizeDuplicates = true);
  41. explicit MeshBuilder(size_t numOrgVerts, size_t maxBonesPerSubMesh, size_t maxSubMeshVertices, bool optimizeDuplicates = true);
  42. template <class LayerType, class... Args>
  43. AZStd::enable_if_t<AZStd::is_convertible_v<LayerType*, MeshBuilderVertexAttributeLayer*>, LayerType*> AddLayer(Args&&... args)
  44. {
  45. if constexpr (AZStd::is_same_v<AZStd::tuple_element_t<0, AZStd::tuple<Args...>>, AZStd::unique_ptr<LayerType>>)
  46. {
  47. // If the thing we were passed is already a unique_ptr, just move it in
  48. m_layers.emplace_back(AZStd::move(args)...);
  49. }
  50. else
  51. {
  52. m_layers.emplace_back(AZStd::make_unique<LayerType>(AZStd::forward<Args>(args)...));
  53. }
  54. return static_cast<LayerType*>(m_layers.back().get());
  55. }
  56. void BeginPolygon(size_t materialIndex); // begin a poly
  57. void AddPolygonVertex(size_t orgVertexNr); // add a vertex to it (do this n-times, for an n-gon)
  58. void EndPolygon(); // end the polygon, after adding all polygon vertices
  59. size_t CalcNumIndices() const; // calculate the number of indices in the mesh
  60. size_t CalcNumVertices() const; // calculate the number of vertices in the mesh
  61. size_t GetNumOrgVerts() const { return m_numOrgVerts; }
  62. void SetSkinningInfo(AZStd::unique_ptr<MeshBuilderSkinningInfo> skinningInfo);
  63. const MeshBuilderSkinningInfo* GetSkinningInfo() const { return m_skinningInfo.get(); }
  64. MeshBuilderSkinningInfo* GetSkinningInfo() { return m_skinningInfo.get(); }
  65. size_t GetMaxBonesPerSubMesh() const { return m_maxBonesPerSubMesh; }
  66. size_t GetMaxVerticesPerSubMesh() const { return m_maxSubMeshVertices; }
  67. void SetMaxBonesPerSubMesh(size_t maxBones) { m_maxBonesPerSubMesh = maxBones; }
  68. size_t GetNumLayers() const { return m_layers.size(); }
  69. size_t GetNumSubMeshes() const { return m_subMeshes.size(); }
  70. const MeshBuilderSubMesh* GetSubMesh(size_t index) const { return m_subMeshes[index].get(); }
  71. const MeshBuilderVertexAttributeLayer* GetLayer(size_t index) const { return m_layers[index].get(); }
  72. size_t GetNumPolygons() const { return m_polyVertexCounts.size(); }
  73. struct SubMeshVertex
  74. {
  75. size_t m_realVertexNr;
  76. size_t m_dupeNr;
  77. MeshBuilderSubMesh* m_subMesh;
  78. };
  79. size_t FindRealVertexNr(const MeshBuilderSubMesh* subMesh, size_t orgVtx, size_t dupeNr) const;
  80. void SetRealVertexNrForSubMeshVertex(const MeshBuilderSubMesh* subMesh, size_t orgVtx, size_t dupeNr, size_t realVertexNr);
  81. const SubMeshVertex* FindSubMeshVertex(const MeshBuilderSubMesh* subMesh, size_t orgVtx, size_t dupeNr) const;
  82. size_t CalcNumVertexDuplicates(const MeshBuilderSubMesh* subMesh, size_t orgVtx) const;
  83. void GenerateSubMeshVertexOrders();
  84. void AddSubMeshVertex(size_t orgVtx, SubMeshVertex&& vtx);
  85. size_t GetNumSubMeshVertices(size_t orgVtx) const;
  86. const SubMeshVertex& GetSubMeshVertex(size_t orgVtx, size_t index) const { return m_vertices[orgVtx][index]; }
  87. private:
  88. static constexpr inline int s_defaultMaxBonesPerSubMesh = 512;
  89. static constexpr inline int s_defaultMaxSubMeshVertices = 65535;
  90. AZStd::vector<AZStd::unique_ptr<MeshBuilderSubMesh>> m_subMeshes;
  91. AZStd::vector<AZStd::unique_ptr<MeshBuilderVertexAttributeLayer>> m_layers;
  92. AZStd::vector<AZStd::vector<SubMeshVertex>> m_vertices;
  93. AZStd::vector<size_t> m_polyJointList;
  94. AZStd::unique_ptr<MeshBuilderSkinningInfo> m_skinningInfo{};
  95. AZStd::vector<MeshBuilderVertexLookup> m_polyIndices;
  96. AZStd::vector<size_t> m_polyOrgVertexNumbers;
  97. AZStd::vector<AZ::u8> m_polyVertexCounts;
  98. size_t m_materialIndex = 0;
  99. size_t m_maxBonesPerSubMesh = s_defaultMaxBonesPerSubMesh;
  100. size_t m_maxSubMeshVertices = s_defaultMaxSubMeshVertices;
  101. size_t m_numOrgVerts = 0;
  102. bool m_optimizeDuplicates = true;
  103. const MeshBuilderVertexLookup FindMatchingDuplicate(size_t orgVertexNr) const;
  104. const MeshBuilderVertexLookup AddVertex(size_t orgVertexNr);
  105. const MeshBuilderVertexLookup FindVertexIndex(size_t orgVertexNr) const;
  106. const MeshBuilderSubMesh* FindSubMeshForPolygon(const AZStd::vector<size_t>& orgVertexNumbers, size_t materialIndex) const;
  107. MeshBuilderSubMesh* FindSubMeshForPolygon(const AZStd::vector<size_t>& orgVertexNumbers, size_t materialIndex)
  108. {
  109. return const_cast<MeshBuilderSubMesh*>(static_cast<const MeshBuilder*>(this)->FindSubMeshForPolygon(orgVertexNumbers, materialIndex));
  110. }
  111. SubMeshVertex* FindSubMeshVertex(const MeshBuilderSubMesh* subMesh, size_t orgVtx, size_t dupeNr)
  112. {
  113. return const_cast<SubMeshVertex*>(static_cast<const MeshBuilder*>(this)->FindSubMeshVertex(subMesh, orgVtx, dupeNr));
  114. }
  115. void ExtractBonesForPolygon(const AZStd::vector<size_t>& orgVertexNumbers, AZStd::vector<size_t>& outPolyJointList) const;
  116. void AddPolygon(const AZStd::vector<MeshBuilderVertexLookup>& indices, const AZStd::vector<size_t>& orgVertexNumbers, size_t materialIndex);
  117. };
  118. } // namespace AZ::MeshBuilder