SpiecsEngine
 
Loading...
Searching...
No Matches

◆ GenerateMeshLodClusterHierarchy()

void Spices::MeshProcessor::GenerateMeshLodClusterHierarchy ( MeshPack * meshPack)
static

Generate Mesh Lod Resources.

Parameters
[in]meshPackMeshPack.

Lod0

Pack to Points.

Calculate Bound Sphere.

Create Lod0 meshlets.

meshlets of last lod.

Build KDTree.

Pack to Points.

Calculate Bound Sphere.

Pack Sparse Inputs.

Simplify meshlets group primPoints.

Simplify succeed: merge result to meshlets.

Lod0

Pack to Points.

Calculate Bound Sphere.

Create Lod0 meshlets.

meshlets of last lod.

Build KDTree.

Pack to Points.

Calculate Bound Sphere.

Pack Sparse Inputs.

Simplify meshlets group primPoints.

Simplify succeed: merge result to meshlets.

Definition at line 17 of file MeshProcessor.cpp.

18 {
20
24 {
25 auto primVertices = meshPack->m_MeshResource.primitiveVertices.attributes;
26 meshPack->m_MeshResource.primitiveVertices.attributes = std::make_shared<std::vector<glm::uvec3>>();
27
31 std::vector<glm::vec3> initPoints;
32 PackVertexToPoints(meshPack, *primVertices, initPoints);
33
37 SpicesShader::Sphere initBoundSphere = CalculateBoundSphere(initPoints);
38
42 AppendMeshlets(meshPack, 0, initBoundSphere, *primVertices);
43 }
44
45 uint32_t meshletStart = 0;
46 const uint32_t maxLod = 0;
47 for (uint32_t lod = 0; lod < maxLod; ++lod)
48 {
49 auto in = std::chrono::high_resolution_clock::now();
50
51 float tLod = lod / (float)maxLod;
52
56 std::vector<Meshlet> meshlets = std::vector<Meshlet>(
57 meshPack->m_MeshResource.meshlets.attributes->begin() + meshletStart,
58 meshPack->m_MeshResource.meshlets.attributes->end()
59 );
60
61 if (meshlets.size() <= 1)
62 {
63 return;
64 }
65
66 const uint32_t nextStart = meshPack->m_MeshResource.meshlets.attributes->size();
67 meshletStart = nextStart;
68 auto groups = GroupMeshlets(meshPack, meshlets);
69
70 for (const auto& group : groups)
71 {
72 std::vector<glm::uvec3> groupPrimVertices;
73 auto ptr = meshPack->m_MeshResource.primitiveVertices.attributes;
74 for (const auto& meshletIndex : group.meshlets)
75 {
76 const auto& meshlet = meshlets[meshletIndex];
77
78 groupPrimVertices.insert(
79 groupPrimVertices.end(),
80 ptr->begin() + meshlet.primitiveOffset,
81 ptr->begin() + meshlet.primitiveOffset + meshlet.nPrimitives
82 );
83 }
84
88 scl::kd_tree<6> kdTree;
89 BuildKDTree(meshPack, groupPrimVertices, kdTree);
90
94 std::vector<glm::vec3> points;
95 PackVertexToPoints(meshPack, groupPrimVertices, points);
96
100 SpicesShader::Sphere clusterBoundSphere = CalculateBoundSphere(points);
101
102 float simplifyScale = meshopt_simplifyScale(&points[0].x, points.size(), sizeof(glm::vec3));
103 const float maxDistance = (tLod * 0.01f + (1 - tLod) * 0.001f) * simplifyScale;
104 const float maxUVDistance = tLod * 0.1f + (1 - tLod) * 0.001f;
105 MergeByDistance(meshPack, groupPrimVertices, kdTree, maxDistance, maxUVDistance);
106
110 std::vector<glm::vec3> packPoints;
111 std::vector<glm::uvec3> packPrimPoints;
112 std::unordered_map<uint32_t, uint32_t> primVerticesMapReverse;
113 PackPrimVerticesFromSparseInputs(meshPack, groupPrimVertices, packPoints, packPrimPoints, primVerticesMapReverse);
114
118 const float threshold = 0.5f;
119 size_t targetCount = packPrimPoints.size() * threshold * 3;
120 float targetError = 0.1f * tLod + 0.01f * (1 - tLod);
121 uint32_t options = meshopt_SimplifyLockBorder;
122
123 std::vector<glm::uvec3> simplifiedPrimPoints(packPrimPoints.size());
124 float simplificationError = 0.0f;
125
126 size_t simplifiedCount = meshopt_simplify(
127 &simplifiedPrimPoints[0].x ,
128 &packPrimPoints[0].x ,
129 packPrimPoints.size() * 3 ,
130 &packPoints[0].x ,
131 packPoints.size() ,
132 sizeof(glm::vec3) ,
133 targetCount ,
134 targetError ,
135 options ,
136 &simplificationError
137 );
138 simplifiedPrimPoints.resize(simplifiedCount / 3);
139
143 std::vector<glm::uvec3> primVerticesBuffer;
144 UnPackPrimVerticesToSparseInputs(primVerticesBuffer, primVerticesMapReverse, simplifiedPrimPoints);
145
146 AppendMeshlets(meshPack, lod + 1, clusterBoundSphere, primVerticesBuffer);
147 }
148
149 auto out = std::chrono::high_resolution_clock::now();
150 std::cout << " Lod Cost: " << std::chrono::duration_cast<std::chrono::milliseconds>(out - in).count() << " " << meshlets.size() << std::endl;
151 }
152 }
#define SPICES_PROFILE_ZONE
static bool PackPrimVerticesFromSparseInputs(MeshPack *meshPack, const std::vector< glm::uvec3 > primVertices, std::vector< glm::vec3 > &packPoints, std::vector< glm::uvec3 > &packPrimPoints, std::unordered_map< uint32_t, uint32_t > &primVerticesMapReverse)
Pack PrimVertices from Sparse PrimVertices Inputs.
static SpicesShader::Sphere CalculateBoundSphere(const std::vector< glm::vec3 > &points)
Calculate BoundSphere from Points.
static bool MergeByDistance(MeshPack *meshPack, std::vector< glm::uvec3 > &primVertices, scl::kd_tree< 6 > &kdTree, float maxDistance, float maxUVDistance)
Merge Vertex by Distance.
static bool PackVertexToPoints(MeshPack *meshPack, const std::vector< glm::uvec3 > &primVertices, std::vector< glm::vec3 > &points)
Pack Vertices to Points.
static bool UnPackPrimVerticesToSparseInputs(std::vector< glm::uvec3 > &primVertices, std::unordered_map< uint32_t, uint32_t > &primVerticesMapReverse, const std::vector< glm::uvec3 > &packPrimPoints)
Unpack PrimVertices to Sparse PrimVertices Inputs.
static void AppendMeshlets(MeshPack *meshPack, uint32_t lod, const SpicesShader::Sphere &clusterBoundSphere, const std::vector< glm::uvec3 > &primVertices)
Create and Append Meshlets to MeshPack use given indices.
static std::vector< MeshletGroup > GroupMeshlets(MeshPack *meshPack, std::vector< Meshlet > &meshlets)
Split Meshlets to Groups.
static bool BuildKDTree(MeshPack *meshPack, const std::vector< glm::uvec3 > &primVertices, scl::kd_tree< 6 > &kdTree)
Build KDTree use specific meshlets.
The kd_tree with K dimensions container Class. K the number of dimensions. Every node in the tree is ...
Definition KDTree.h:27

Referenced by Spices::MeshLoader::LoadFromOBJ(), Spices::GltfPack::OnCreatePack(), Spices::PlanePack::OnCreatePack(), Spices::CubePack::OnCreatePack(), and Spices::SpherePack::OnCreatePack().