TriangleSplitterBinning.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  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/TriangleSplitter/TriangleSplitterBinning.h>
  6. JPH_NAMESPACE_BEGIN
  7. TriangleSplitterBinning::TriangleSplitterBinning(const VertexList &inVertices, const IndexedTriangleList &inTriangles, uint inMinNumBins, uint inMaxNumBins, uint inNumTrianglesPerBin) :
  8. TriangleSplitter(inVertices, inTriangles),
  9. mMinNumBins(inMinNumBins),
  10. mMaxNumBins(inMaxNumBins),
  11. mNumTrianglesPerBin(inNumTrianglesPerBin)
  12. {
  13. mBins.resize(mMaxNumBins);
  14. }
  15. bool TriangleSplitterBinning::Split(const Range &inTriangles, Range &outLeft, Range &outRight)
  16. {
  17. // Calculate bounds for this range
  18. AABox centroid_bounds;
  19. for (uint t = inTriangles.mBegin; t < inTriangles.mEnd; ++t)
  20. centroid_bounds.Encapsulate(Vec3(mCentroids[mSortedTriangleIdx[t]]));
  21. float best_cp = FLT_MAX;
  22. uint best_dim = 0xffffffff;
  23. float best_split = 0;
  24. // Bin in all dimensions
  25. uint num_bins = Clamp(inTriangles.Count() / mNumTrianglesPerBin, mMinNumBins, mMaxNumBins);
  26. for (uint dim = 0; dim < 3; ++dim)
  27. {
  28. float bounds_min = centroid_bounds.mMin[dim];
  29. float bounds_size = centroid_bounds.mMax[dim] - bounds_min;
  30. // Skip axis if too small
  31. if (bounds_size < 1.0e-5f)
  32. continue;
  33. // Initialize bins
  34. for (uint b = 0; b < num_bins; ++b)
  35. {
  36. Bin &bin = mBins[b];
  37. bin.mBounds.SetEmpty();
  38. bin.mMinCentroid = bounds_min + bounds_size * (b + 1) / num_bins;
  39. bin.mNumTriangles = 0;
  40. }
  41. // Bin all triangles
  42. for (uint t = inTriangles.mBegin; t < inTriangles.mEnd; ++t)
  43. {
  44. float centroid_pos = mCentroids[mSortedTriangleIdx[t]][dim];
  45. // Select bin
  46. uint bin_no = min(uint((centroid_pos - bounds_min) / bounds_size * num_bins), num_bins - 1);
  47. Bin &bin = mBins[bin_no];
  48. // Accumulate triangle in bin
  49. bin.mBounds.Encapsulate(mVertices, GetTriangle(t));
  50. bin.mMinCentroid = min(bin.mMinCentroid, centroid_pos);
  51. bin.mNumTriangles++;
  52. }
  53. // Calculate totals left to right
  54. AABox prev_bounds;
  55. int prev_triangles = 0;
  56. for (uint b = 0; b < num_bins; ++b)
  57. {
  58. Bin &bin = mBins[b];
  59. bin.mBoundsAccumulatedLeft = prev_bounds; // Don't include this node as we'll take a split on the left side of the bin
  60. bin.mNumTrianglesAccumulatedLeft = prev_triangles;
  61. prev_bounds.Encapsulate(bin.mBounds);
  62. prev_triangles += bin.mNumTriangles;
  63. }
  64. // Calculate totals right to left
  65. prev_bounds.SetEmpty();
  66. prev_triangles = 0;
  67. for (int b = num_bins - 1; b >= 0; --b)
  68. {
  69. Bin &bin = mBins[b];
  70. prev_bounds.Encapsulate(bin.mBounds);
  71. prev_triangles += bin.mNumTriangles;
  72. bin.mBoundsAccumulatedRight = prev_bounds;
  73. bin.mNumTrianglesAccumulatedRight = prev_triangles;
  74. }
  75. // Get best splitting plane
  76. for (uint b = 1; b < num_bins; ++b) // Start at 1 since selecting bin 0 would result in everything ending up on the right side
  77. {
  78. // Calculate surface area heuristic and see if it is better than the current best
  79. const Bin &bin = mBins[b];
  80. float cp = bin.mBoundsAccumulatedLeft.GetSurfaceArea() * bin.mNumTrianglesAccumulatedLeft + bin.mBoundsAccumulatedRight.GetSurfaceArea() * bin.mNumTrianglesAccumulatedRight;
  81. if (cp < best_cp)
  82. {
  83. best_cp = cp;
  84. best_dim = dim;
  85. best_split = bin.mMinCentroid;
  86. }
  87. }
  88. }
  89. // No split found?
  90. if (best_dim == 0xffffffff)
  91. return false;
  92. return SplitInternal(inTriangles, best_dim, best_split, outLeft, outRight);
  93. }
  94. JPH_NAMESPACE_END