2
3
4
5
11#include <src/meshoptimizer.h>
13#include <glm/gtx/norm.hpp>
22
23
25 auto primVertices = meshPack->m_MeshResource.primitiveVertices.attributes;
26 meshPack->m_MeshResource.primitiveVertices.attributes = std::make_shared<std::vector<glm::uvec3>>();
29
30
31 std::vector<glm::vec3> initPoints;
32 PackVertexToPoints(meshPack, *primVertices, initPoints);
35
36
37 SpicesShader::Sphere initBoundSphere = CalculateBoundSphere(initPoints);
40
41
42 AppendMeshlets(meshPack, 0, initBoundSphere, *primVertices);
45 uint32_t meshletStart = 0;
46 const uint32_t maxLod = 0;
47 for (uint32_t lod = 0; lod < maxLod; ++lod)
49 auto in = std::chrono::high_resolution_clock::now();
51 float tLod = lod / (
float)maxLod;
54
55
56 std::vector<Meshlet> meshlets = std::vector<Meshlet>(
57 meshPack->m_MeshResource.meshlets.attributes->begin() + meshletStart,
58 meshPack->m_MeshResource.meshlets.attributes->end()
61 if (meshlets.size() <= 1)
66 const uint32_t nextStart = meshPack->m_MeshResource.meshlets.attributes->size();
67 meshletStart = nextStart;
68 auto groups = GroupMeshlets(meshPack, meshlets);
70 for (
const auto& group : groups)
72 std::vector<glm::uvec3> groupPrimVertices;
73 auto ptr = meshPack->m_MeshResource.primitiveVertices.attributes;
74 for (
const auto& meshletIndex : group.meshlets)
76 const auto& meshlet = meshlets[meshletIndex];
78 groupPrimVertices.insert(
79 groupPrimVertices.end(),
80 ptr->begin() + meshlet.primitiveOffset,
81 ptr->begin() + meshlet.primitiveOffset + meshlet.nPrimitives
86
87
88 scl::kd_tree<6> kdTree;
89 BuildKDTree(meshPack, groupPrimVertices, kdTree);
92
93
94 std::vector<glm::vec3> points;
95 PackVertexToPoints(meshPack, groupPrimVertices, points);
98
99
100 SpicesShader::Sphere clusterBoundSphere = CalculateBoundSphere(points);
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);
108
109
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);
116
117
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;
123 std::vector<glm::uvec3> simplifiedPrimPoints(packPrimPoints.size());
124 float simplificationError = 0.0f;
126 size_t simplifiedCount = meshopt_simplify(
127 &simplifiedPrimPoints[0].x ,
128 &packPrimPoints[0].x ,
129 packPrimPoints.size() * 3 ,
138 simplifiedPrimPoints.resize(simplifiedCount / 3);
141
142
143 std::vector<glm::uvec3> primVerticesBuffer;
144 UnPackPrimVerticesToSparseInputs(primVerticesBuffer, primVerticesMapReverse, simplifiedPrimPoints);
146 AppendMeshlets(meshPack, lod + 1, clusterBoundSphere, primVerticesBuffer);
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;
157 const SpicesShader::Sphere& clusterBoundSphere ,
158 const std::vector<glm::uvec3>& primVertices
164
165
166
167 const float coneWeight = 0.5f;
168 const uint32_t primLocationsOffset = meshPack->m_MeshResource.primitiveLocations.attributes->size();
169 const uint32_t primVerticesOffset = meshPack->m_MeshResource.primitiveVertices.attributes->size();
170 const uint32_t meshletsOffset = meshPack->m_MeshResource.meshlets.attributes->size();
173
174
175 size_t max_meshlets = meshopt_buildMeshletsBound(primVertices.size() * 3, SpicesShader::MESHLET_NVERTICES, SpicesShader::MESHLET_NPRIMITIVES);
176 std::vector<meshopt_Meshlet> meshoptlets(max_meshlets);
177 std::vector<
unsigned int> meshlet_vertices(max_meshlets * SpicesShader::MESHLET_NVERTICES);
178 std::vector<
unsigned char> meshlet_triangles(max_meshlets * SpicesShader::MESHLET_NPRIMITIVES * 3);
181
182
183 std::vector<glm::vec3> packPoints;
184 std::vector<glm::uvec3> packPrimPoints;
185 std::unordered_map<uint32_t, uint32_t> primVerticesMapReverse;
186 PackPrimVerticesFromSparseInputs(meshPack, primVertices, packPoints, packPrimPoints, primVerticesMapReverse);
189
190
191 size_t nMeshlet = meshopt_buildMeshlets(
193 meshlet_vertices.data() ,
194 meshlet_triangles.data() ,
195 &packPrimPoints[0].x ,
196 packPrimPoints.size() * 3 ,
200 SpicesShader::MESHLET_NVERTICES ,
201 SpicesShader::MESHLET_NPRIMITIVES ,
206
207
208 const meshopt_Meshlet& last = meshoptlets[nMeshlet - 1];
209 meshoptlets .resize(nMeshlet);
210 meshlet_vertices .resize(last.vertex_offset + last.vertex_count);
211 meshlet_triangles.resize(last.triangle_offset + (last.triangle_count * 3 + 3) & ~3);
214
215
216 uint32_t nPrimitives = 0;
217 for (size_t i = 0; i < nMeshlet; ++i)
219 meshopt_optimizeMeshlet(
220 &meshlet_vertices[meshoptlets[i].vertex_offset] ,
221 &meshlet_triangles[meshoptlets[i].triangle_offset] ,
222 meshoptlets[i].triangle_count, meshoptlets[i].vertex_count
225 const meshopt_Meshlet& m = meshoptlets[i];
226 meshopt_Bounds bounds = meshopt_computeMeshletBounds(
227 &meshlet_vertices[m.vertex_offset] ,
228 &meshlet_triangles[m.triangle_offset] ,
236 meshlet.FromMeshopt(meshoptlets[i], bounds);
237 meshlet.primitiveOffset = nPrimitives;
239 meshlet.vertexOffset += primLocationsOffset;
240 meshlet.primitiveOffset += primVerticesOffset;
243 meshlet.clusterBoundSphere = clusterBoundSphere;
245 meshPack->m_MeshResource.meshlets.attributes->push_back(std::move(meshlet));
247 nPrimitives += m.triangle_count;
251
252
253 std::unordered_map<glm::uvec3, uint32_t> inPrimPointsLayoutMap;
254 auto& vertices = *meshPack->m_MeshResource.vertices.attributes;
255 for (
auto& primVertex : primVertices)
257 inPrimPointsLayoutMap[{ vertices[primVertex.x].x, vertices[primVertex.y].x, vertices[primVertex.z].x }] = inPrimPointsLayoutMap.size();
261
262
263 const Meshlet& lastm = (*meshPack->m_MeshResource.meshlets.attributes)[meshletsOffset + nMeshlet - 1];
264 meshPack->m_MeshResource.primitivePoints .attributes->resize(lastm.primitiveOffset + lastm.nPrimitives);
265 meshPack->m_MeshResource.primitiveVertices .attributes->resize(lastm.primitiveOffset + lastm.nPrimitives);
266 meshPack->m_MeshResource.primitiveLocations .attributes->resize(lastm.primitiveOffset + lastm.nPrimitives);
268 for (uint32_t i = 0; i < nMeshlet; i++)
270 const meshopt_Meshlet& m = meshoptlets[i];
271 const Meshlet& ml = (*meshPack->m_MeshResource.meshlets.attributes)[meshletsOffset + i];
273 for (uint32_t j = 0; j < m.triangle_count; j++)
275 uint32_t a = (uint32_t)meshlet_triangles[m.triangle_offset + 3 * j + 0] + m.vertex_offset;
276 uint32_t b = (uint32_t)meshlet_triangles[m.triangle_offset + 3 * j + 1] + m.vertex_offset;
277 uint32_t c = (uint32_t)meshlet_triangles[m.triangle_offset + 3 * j + 2] + m.vertex_offset;
279 uint32_t& x = vertices[primVerticesMapReverse[meshlet_vertices[a]]].x;
280 uint32_t& y = vertices[primVerticesMapReverse[meshlet_vertices[b]]].x;
281 uint32_t& z = vertices[primVerticesMapReverse[meshlet_vertices[c]]].x;
283 (*meshPack->m_MeshResource.primitivePoints.attributes)[ml.primitiveOffset + j] = { x, y, z };
285 (*meshPack->m_MeshResource.primitiveLocations.attributes)[ml.primitiveOffset + j].x = a + primLocationsOffset;
286 (*meshPack->m_MeshResource.primitiveLocations.attributes)[ml.primitiveOffset + j].y = b + primLocationsOffset;
287 (*meshPack->m_MeshResource.primitiveLocations.attributes)[ml.primitiveOffset + j].z = c + primLocationsOffset;
289 (*meshPack->m_MeshResource.primitiveVertices.attributes)[ml.primitiveOffset + j] = primVertices[inPrimPointsLayoutMap[{ x, y, z }]];
294
295
296 uint32_t nLods = meshPack->m_MeshResource.lods.attributes->size();
298 if (nLods == lod + 1)
300 Lod& lodRef = (*meshPack->m_MeshResource.lods.attributes)[lod];
302 lodRef
.nPrimitives += lastm.primitiveOffset + lastm.nPrimitives - primVerticesOffset;
303 lodRef.nMeshlets += nMeshlet;
309 lodData
.nPrimitives = lastm.primitiveOffset + lastm.nPrimitives - primVerticesOffset;
310 lodData.nMeshlets = nMeshlet;
313 meshPack->m_MeshResource.lods.attributes->push_back(std::move(lodData));
317 std::vector<MeshletGroup>
MeshProcessor::GroupMeshlets(MeshPack* meshPack, std::vector<Meshlet>& meshlets)
322
323
324 auto groupWithMeshlets = [&]()
327 for (
int i = 0; i < meshlets.size(); ++i)
329 group.meshlets.push_back(i);
331 return std::vector{ group };
335
336
337 if (meshlets.size() < 8)
339 return groupWithMeshlets();
342 std::unordered_map<Edge, std::set<size_t>> edges2Meshlets;
343 std::unordered_map<size_t, std::vector<Edge>> meshlets2Edges;
345 for (size_t meshletIndex = 0; meshletIndex < meshlets.size(); meshletIndex++)
347 const auto& meshlet = meshlets[meshletIndex];
349 for (size_t triangleIndex = 0; triangleIndex < meshlet.nPrimitives; triangleIndex++)
351 const glm::uvec3& primPts = (*meshPack->m_MeshResource.primitivePoints.attributes)[meshlet.primitiveOffset + triangleIndex];
353 Edge edge0{ primPts.x , primPts.y };
354 Edge edge1{ primPts.y , primPts.z };
355 Edge edge2{ primPts.z , primPts.x };
357 edges2Meshlets[edge0].insert(meshletIndex);
358 edges2Meshlets[edge1].insert(meshletIndex);
359 edges2Meshlets[edge2].insert(meshletIndex);
361 meshlets2Edges[meshletIndex].push_back(edge0);
362 meshlets2Edges[meshletIndex].push_back(edge1);
363 meshlets2Edges[meshletIndex].push_back(edge2);
368
369
370 for (
auto first = edges2Meshlets.begin(), last = edges2Meshlets.end(); first != last;)
372 if ((*first).second.size() <= 1)
374 first = edges2Meshlets.erase(first);
383
384
385 if (edges2Meshlets.empty())
387 return groupWithMeshlets();
390 idx_t vertexCount = meshlets.size();
392 idx_t nparts = meshlets.size() / 4;
395 idx_t options[METIS_NOPTIONS];
396 METIS_SetDefaultOptions(options);
398 options[METIS_OPTION_OBJTYPE] = METIS_OBJTYPE_CUT;
399 options[METIS_OPTION_CCORDER] = 1;
401 std::vector<idx_t> partition;
402 partition.resize(vertexCount);
405
406
407 std::vector<idx_t> xadjacency;
408 xadjacency.reserve(vertexCount + 1);
411
412
413
414 std::vector<idx_t> edgeAdjacency;
417
418
419 std::vector<idx_t> edgeWeights;
421 for (size_t meshletIndex = 0; meshletIndex < meshlets.size(); meshletIndex++)
423 size_t startIndexInEdgeAdjacency = edgeAdjacency.size();
424 for (
const auto& edge : meshlets2Edges[meshletIndex])
427
428
429 auto connectionsIter = edges2Meshlets.find(edge);
430 if (connectionsIter == edges2Meshlets.end())
436
437
438 const auto& connections = connectionsIter->second;
439 for (
const auto& connectedMeshlet : connections)
442
443
444 if (connectedMeshlet != meshletIndex)
446 auto existingEdgeIter = std::find(edgeAdjacency.begin() + startIndexInEdgeAdjacency, edgeAdjacency.end(), connectedMeshlet);
447 if (existingEdgeIter == edgeAdjacency.end())
449 edgeAdjacency.emplace_back(connectedMeshlet);
450 edgeWeights.emplace_back(1);
454 std::ptrdiff_t d = std::distance(edgeAdjacency.begin(), existingEdgeIter);
455 assert(d >= 0 && d < edgeWeights.size());
461 xadjacency.push_back(startIndexInEdgeAdjacency);
463 xadjacency.push_back(edgeAdjacency.size());
465 assert(xadjacency.size() == meshlets.size() + 1);
466 assert(edgeAdjacency.size() == edgeWeights.size());
469
470
472 int result = METIS_PartGraphKway(
476 edgeAdjacency.data(),
488 assert(result == METIS_OK);
491
492
493 std::vector<MeshletGroup> groups;
494 groups.resize(nparts);
495 for (size_t i = 0; i < meshlets.size(); i++)
497 idx_t partitionNumber = partition[i];
498 groups[partitionNumber].meshlets.push_back(i);
506 std::vector<glm::uvec3>& primVertices ,
514 auto& positions = *meshPack->m_MeshResource.positions.attributes;
515 auto& texCoords = *meshPack->m_MeshResource.texCoords.attributes;
516 auto& vertices = *meshPack->m_MeshResource.vertices .attributes;
519
520
521 std::unordered_map<uint32_t,
bool> boundaryPoints;
522 std::unordered_map<uint32_t,
bool> stableBoundaryPoints;
523 std::unordered_map<uint32_t, EdgePoint> boundaryEdgePoints;
524 std::unordered_map<uint32_t, std::unordered_map<uint32_t,
bool>> pointConnect;
529 stableBoundaryPoints ,
534 std::unordered_map<uint32_t, uint32_t> primVerticesMap;
535 auto addToMap = [&](
const uint32_t& k,
const uint32_t& v) {
536 if (primVerticesMap.find(k) == primVerticesMap.end())
538 primVerticesMap[k] = v;
543
544
545 for (
int i = 0; i < primVertices.size(); i++)
547 auto& primVertex = primVertices[i];
549 std::array<uint32_t, 3> primVertexArray = { primVertex.x, primVertex.y, primVertex.z };
551 for (
int j = 0; j < 3; j++)
553 const glm::uvec4& vertex = vertices[primVertexArray[j]];
556
557
558 scl::kd_tree<6>::item item = {
559 positions[vertex.x].x,
560 positions[vertex.x].y,
561 positions[vertex.x].z,
562 texCoords[vertex.w].x,
563 texCoords[vertex.w].y,
564 (
float)primVertexArray[j]
566 auto rangeVts = kdTree.range_search(item, {
576
577
578 std::vector<scl::kd_tree<6>::item> nearVts;
579 for (
auto& vt : rangeVts)
581 uint32_t pt = vertices[(uint32_t)vt[5]].x;
583 if (pointConnect[vertex.x].find(pt) != pointConnect[vertex.x].end())
585 nearVts.push_back(vt);
590
591
592
593 if (stableBoundaryPoints.find(vertex.x) != stableBoundaryPoints.end())
595 std::unordered_map<uint32_t,
bool> mergedVertex;
597 for (
auto& rangeVt : nearVts)
599 uint32_t primVertexIndex = (uint32_t)rangeVt[5];
600 mergedVertex[vertices[primVertexIndex].x] =
true;
603 bool canBeTriangle =
true;
604 for (
int k = 0; k < primVertexArray.size(); k++)
606 if (mergedVertex.find(vertices[primVertexArray[k]].x) != mergedVertex.end())
608 canBeTriangle =
false;
615 for (
auto& rangeVt : nearVts)
617 uint32_t primVertexIndex = (uint32_t)rangeVt[5];
618 addToMap(primVertexIndex, primVertexArray[j]);
623 addToMap(primVertexArray[j], primVertexArray[j]);
628
629
630
631 else if (boundaryPoints.find(vertex.x) != boundaryPoints.end())
633 for (
auto& rangeVt : nearVts)
635 uint32_t primVertexIndex = (uint32_t)rangeVt[5];
636 uint32_t pt = vertices[primVertexIndex].x;
638 if (boundaryPoints.find(pt) == boundaryPoints.end())
640 addToMap(primVertexIndex, primVertexArray[j]);
642 else if (stableBoundaryPoints.find(pt) == stableBoundaryPoints.end())
644 if (boundaryEdgePoints[vertex.x].next == pt ||
645 boundaryEdgePoints[vertex.x].prev == pt ||
646 boundaryEdgePoints[vertex.x].self == pt
649 addToMap(primVertexIndex, primVertexArray[j]);
656
657
660 for (
auto& rangeVt : nearVts)
662 uint32_t primVertexIndex = (uint32_t)rangeVt[5];
663 uint32_t pt = vertices[primVertexIndex].x;
665 if (boundaryPoints.find(pt) == boundaryPoints.end())
667 addToMap(primVertexIndex, primVertexArray[j]);
675
676
677 std::vector<glm::uvec3> tempPrimVertices = primVertices;
678 for (
int i = 0; i < primVertices.size(); i++)
680 auto primVertex = primVertices[i];
682 if(primVerticesMap.find(primVertex.x) != primVerticesMap.end()) tempPrimVertices[i].x = primVerticesMap[primVertex.x];
683 if(primVerticesMap.find(primVertex.y) != primVerticesMap.end()) tempPrimVertices[i].y = primVerticesMap[primVertex.y];
684 if(primVerticesMap.find(primVertex.z) != primVerticesMap.end()) tempPrimVertices[i].z = primVerticesMap[primVertex.z];
688
689
690 primVertices.clear();
691 for (
auto& primVertex : tempPrimVertices)
693 std::set<uint32_t> set;
695 set.insert(primVertex.x);
696 set.insert(primVertex.y);
697 set.insert(primVertex.z);
699 if (set.size() < 3)
continue;
701 primVertices.push_back(primVertex);
709 const std::vector<glm::uvec3>& primVertices ,
710 std::vector<glm::vec3>& points
715 std::unordered_map<uint32_t,
bool> pointsMap;
717 auto& positions = *meshPack->m_MeshResource.positions.attributes;
718 auto& vertices = *meshPack->m_MeshResource.vertices .attributes;
719 for (
auto& primVertex : primVertices)
721 const glm::uvec4& vertex0 = vertices[primVertex.x];
722 const glm::uvec4& vertex1 = vertices[primVertex.y];
723 const glm::uvec4& vertex2 = vertices[primVertex.z];
725 pointsMap[vertex0.x] =
true;
726 pointsMap[vertex1.x] =
true;
727 pointsMap[vertex2.x] =
true;
730 points.resize(pointsMap.size());
732 for (
auto& [pt, ignore] : pointsMap)
734 points[i] = positions[pt];
741 SpicesShader::Sphere
MeshProcessor::CalculateBoundSphere(
const std::vector<glm::vec3>& points)
745 SpicesShader::Sphere sphere;
747 glm::vec3 min = { 1E11, 1E11, 1E11 };
748 glm::vec3 max = { -1E11, -1E11, -1E11 };
750 for (
const auto& point : points)
752 min = glm::min(min, point);
753 max = glm::max(max, point);
756 glm::vec3 bound = max - min;
757 sphere.c = 0.5f * (max + min);
758 sphere.r = 0.5f * glm::sqrt(bound.x * bound.x + bound.y * bound.y + bound.z * bound.z);
765 const std::vector<glm::uvec3>& primVertices ,
771 std::unordered_map<uint32_t,
bool> primVerticesMap;
772 for (
auto& primVertex : primVertices)
774 primVerticesMap[primVertex.x] =
true;
775 primVerticesMap[primVertex.y] =
true;
776 primVerticesMap[primVertex.z] =
true;
779 auto& positions = *meshPack->m_MeshResource.positions.attributes;
780 auto& texCoords = *meshPack->m_MeshResource.texCoords.attributes;
781 auto& vertices = *meshPack->m_MeshResource.vertices .attributes;
783 std::vector<scl::kd_tree<6>::item> items;
784 items.resize(primVerticesMap.size());
787 for (
auto& [primVertex, ignore] : primVerticesMap)
789 glm::uvec4 vertex = vertices[primVertex];
793 positions[vertex.x].x,
794 positions[vertex.x].y,
795 positions[vertex.x].z,
796 texCoords[vertex.w].x,
797 texCoords[vertex.w].y,
804 kdTree.insert(items);
811 const std::vector<glm::uvec3>& primVertices ,
812 std::unordered_map<uint32_t,
bool>& boundaryPoints ,
813 std::unordered_map<uint32_t,
bool>& stableBoundaryPoints ,
814 std::unordered_map<uint32_t, EdgePoint>& boundaryEdgePoints ,
815 std::unordered_map<uint32_t, std::unordered_map<uint32_t,
bool>>& pointConnect
821
822
823 std::unordered_map<Edge, uint32_t> edgesConnects;
824 auto& vertices = *meshPack->m_MeshResource.vertices.attributes;
825 for (uint32_t triangleIndex = 0; triangleIndex < primVertices.size(); triangleIndex++)
827 auto& primVertex = primVertices[triangleIndex];
828 std::array<uint32_t, 3> primVertexArray = { primVertex.x, primVertex.y, primVertex.z };
830 for (uint32_t i = 0; i < 3; i++)
833 edge.first = vertices[primVertexArray[i]].x;
834 edge.second = vertices[primVertexArray[(i + 1) % 3]].x;
836 if (edgesConnects.find(edge) == edgesConnects.end())
838 edgesConnects[edge] = 1;
842 edgesConnects[edge]++;
848
849
850 for (
auto& [edge, connects] : edgesConnects)
852 pointConnect[edge.first][edge.second] =
true;
853 pointConnect[edge.first][edge.first] =
true;
855 pointConnect[edge.second][edge.first] =
true;
856 pointConnect[edge.second][edge.second] =
true;
860
861
862 for (
auto first = edgesConnects.begin(), last = edgesConnects.end(); first != last;)
864 if ((*first).second != 1)
866 first = edgesConnects.erase(first);
874 for (
auto& [edge, connects] : edgesConnects)
876 boundaryPoints[edge.first] =
true;
877 boundaryPoints[edge.second] =
true;
881
882
883 for (
auto& [edge, connects] : edgesConnects)
885 if (boundaryEdgePoints.find(edge.first) == boundaryEdgePoints.end())
887 boundaryEdgePoints[edge.first].self = edge.first;
888 boundaryEdgePoints[edge.first].next = edge.second;
892 boundaryEdgePoints[edge.first].prev = edge.second;
895 if (boundaryEdgePoints.find(edge.second) == boundaryEdgePoints.end())
897 boundaryEdgePoints[edge.second].self = edge.second;
898 boundaryEdgePoints[edge.second].next = edge.first;
902 boundaryEdgePoints[edge.second].prev = edge.first;
907
908
909 auto& position = *meshPack->m_MeshResource.positions.attributes;
910 for (
auto& pair : boundaryEdgePoints)
912 if (!pair.second.valid())
continue;
914 glm::vec3 l = glm::normalize(position[pair.second.next] - position[pair.first]);
915 glm::vec3 r = glm::normalize(position[pair.second.prev] - position[pair.first]);
917 if (glm::dot(l, r) > -0.98f)
919 stableBoundaryPoints[pair.second.self] =
true;
921#define ExpandStablePoint
924 stableBoundaryPoints[pair.second.next] =
true;
925 stableBoundaryPoints[pair.second.prev] =
true;
937 const std::vector<glm::uvec3> primVertices ,
938 std::vector<glm::vec3>& packPoints ,
939 std::vector<glm::uvec3>& packPrimPoints ,
940 std::unordered_map<uint32_t, uint32_t>& primVerticesMapReverse
946
947
948 std::unordered_map<uint32_t, uint32_t> primVerticesMap;
949 for (
auto& primVertex : primVertices)
951 if (primVerticesMap.find(primVertex.x) == primVerticesMap.end()) primVerticesMap[primVertex.x] = primVerticesMap.size();
952 if (primVerticesMap.find(primVertex.y) == primVerticesMap.end()) primVerticesMap[primVertex.y] = primVerticesMap.size();
953 if (primVerticesMap.find(primVertex.z) == primVerticesMap.end()) primVerticesMap[primVertex.z] = primVerticesMap.size();
957
958
959 packPoints.resize(primVerticesMap.size());
960 auto& vertices = *meshPack->m_MeshResource.vertices.attributes;
961 for (
auto& pair : primVerticesMap)
963 packPoints[pair.second] = (*meshPack->m_MeshResource.positions.attributes)[vertices[pair.first].x];
964 primVerticesMapReverse[pair.second] = pair.first;
967 packPrimPoints.resize(primVertices.size());
968 for (
int i = 0; i < primVertices.size(); i++)
970 glm::uvec3 primVertex = primVertices[i];
972 packPrimPoints[i].x = primVerticesMap[primVertex.x];
973 packPrimPoints[i].y = primVerticesMap[primVertex.y];
974 packPrimPoints[i].z = primVerticesMap[primVertex.z];
981 std::vector<glm::uvec3>& primVertices ,
982 std::unordered_map<uint32_t, uint32_t>& primVerticesMapReverse ,
983 const std::vector<glm::uvec3>& packPrimPoints
988 primVertices.resize(packPrimPoints.size());
989 for (
int i = 0; i < packPrimPoints.size(); i++)
991 uint32_t x = primVerticesMapReverse[packPrimPoints[i].x];
992 uint32_t y = primVerticesMapReverse[packPrimPoints[i].y];
993 uint32_t z = primVerticesMapReverse[packPrimPoints[i].z];
995 primVertices[i] = glm::uvec3(x, y, z);
#define ExpandStablePoint
#define SPICES_PROFILE_ZONE
MeshPack Class. This class defines some basic behaves and variables. This class need to be inherited ...
static void GenerateMeshLodClusterHierarchy(MeshPack *meshPack)
Generate Mesh Lod Resources.
Class for provide functions of process Meshpack.
The kd_tree with K dimensions container Class. K the number of dimensions. Every node in the tree is ...
uint32_t primVertexOffset
MeshletGroup for simplify.
Meshlet Class. This class defines what Meshlet data.