TriangleGrouperClosestCentroid.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #include <Jolt/Jolt.h>
  4. #include <Jolt/TriangleGrouper/TriangleGrouperClosestCentroid.h>
  5. #include <Jolt/Geometry/MortonCode.h>
  6. JPH_NAMESPACE_BEGIN
  7. void TriangleGrouperClosestCentroid::Group(const VertexList &inVertices, const IndexedTriangleList &inTriangles, int inGroupSize, vector<uint> &outGroupedTriangleIndices)
  8. {
  9. const uint triangle_count = (uint)inTriangles.size();
  10. const uint num_batches = (triangle_count + inGroupSize - 1) / inGroupSize;
  11. vector<Vec3> centroids;
  12. centroids.resize(triangle_count);
  13. outGroupedTriangleIndices.resize(triangle_count);
  14. for (uint t = 0; t < triangle_count; ++t)
  15. {
  16. // Store centroid
  17. centroids[t] = inTriangles[t].GetCentroid(inVertices);
  18. // Initialize sort table
  19. outGroupedTriangleIndices[t] = t;
  20. }
  21. vector<uint>::iterator triangles_end = outGroupedTriangleIndices.end();
  22. // Sort per batch
  23. for (uint b = 0; b < num_batches - 1; ++b)
  24. {
  25. // Get iterators
  26. vector<uint>::iterator batch_begin = outGroupedTriangleIndices.begin() + b * inGroupSize;
  27. vector<uint>::iterator batch_end = batch_begin + inGroupSize;
  28. vector<uint>::iterator batch_begin_plus_1 = batch_begin + 1;
  29. vector<uint>::iterator batch_end_minus_1 = batch_end - 1;
  30. // Find triangle with centroid with lowest X coordinate
  31. vector<uint>::iterator lowest_iter = batch_begin;
  32. float lowest_val = centroids[*lowest_iter].GetX();
  33. for (vector<uint>::iterator other = batch_begin; other != triangles_end; ++other)
  34. {
  35. float val = centroids[*other].GetX();
  36. if (val < lowest_val)
  37. {
  38. lowest_iter = other;
  39. lowest_val = val;
  40. }
  41. }
  42. // Make this triangle the first in a new batch
  43. swap(*batch_begin, *lowest_iter);
  44. Vec3 first_centroid = centroids[*batch_begin];
  45. // Sort remaining triangles in batch on distance to first triangle
  46. sort(batch_begin_plus_1, batch_end,
  47. [&first_centroid, &centroids](uint inLHS, uint inRHS)
  48. {
  49. return (centroids[inLHS] - first_centroid).LengthSq() < (centroids[inRHS] - first_centroid).LengthSq();
  50. });
  51. // Loop over remaining triangles
  52. float furthest_dist = (centroids[*batch_end_minus_1] - first_centroid).LengthSq();
  53. for (vector<uint>::iterator other = batch_end; other != triangles_end; ++other)
  54. {
  55. // Check if this triangle is closer than the furthest triangle in the batch
  56. float dist = (centroids[*other] - first_centroid).LengthSq();
  57. if (dist < furthest_dist)
  58. {
  59. // Replace furthest triangle
  60. uint other_val = *other;
  61. *other = *batch_end_minus_1;
  62. // Find first element that is bigger than this one and insert the current item before it
  63. vector<uint>::iterator upper = upper_bound(batch_begin_plus_1, batch_end, dist,
  64. [&first_centroid, &centroids](float inLHS, uint inRHS)
  65. {
  66. return inLHS < (centroids[inRHS] - first_centroid).LengthSq();
  67. });
  68. copy_backward(upper, batch_end_minus_1, batch_end);
  69. *upper = other_val;
  70. // Calculate new furthest distance
  71. furthest_dist = (centroids[*batch_end_minus_1] - first_centroid).LengthSq();
  72. }
  73. }
  74. }
  75. }
  76. JPH_NAMESPACE_END