TriangleGrouperClosestCentroid.cpp 3.1 KB

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