TriangleSplitterMorton.cpp 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  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/TriangleSplitterMorton.h>
  6. #include <Jolt/Geometry/MortonCode.h>
  7. #include <Jolt/Core/QuickSort.h>
  8. JPH_NAMESPACE_BEGIN
  9. TriangleSplitterMorton::TriangleSplitterMorton(const VertexList &inVertices, const IndexedTriangleList &inTriangles) :
  10. TriangleSplitter(inVertices, inTriangles)
  11. {
  12. // Calculate bounds of centroids
  13. AABox bounds;
  14. for (uint t = 0; t < inTriangles.size(); ++t)
  15. bounds.Encapsulate(Vec3(mCentroids[t]));
  16. // Make sure box is not degenerate
  17. bounds.EnsureMinimalEdgeLength(1.0e-5f);
  18. // Calculate morton codes
  19. mMortonCodes.resize(inTriangles.size());
  20. for (uint t = 0; t < inTriangles.size(); ++t)
  21. mMortonCodes[t] = MortonCode::sGetMortonCode(Vec3(mCentroids[t]), bounds);
  22. // Sort triangles on morton code
  23. const Array<uint32> &morton_codes = mMortonCodes;
  24. QuickSort(mSortedTriangleIdx.begin(), mSortedTriangleIdx.end(), [&morton_codes](uint inLHS, uint inRHS) { return morton_codes[inLHS] < morton_codes[inRHS]; });
  25. }
  26. bool TriangleSplitterMorton::Split(const Range &inTriangles, Range &outLeft, Range &outRight)
  27. {
  28. uint32 first_code = mMortonCodes[mSortedTriangleIdx[inTriangles.mBegin]];
  29. uint32 last_code = mMortonCodes[mSortedTriangleIdx[inTriangles.mEnd - 1]];
  30. uint common_prefix = CountLeadingZeros(first_code ^ last_code);
  31. // Use binary search to find where the next bit differs
  32. uint split = inTriangles.mBegin; // Initial guess
  33. uint step = inTriangles.Count();
  34. do
  35. {
  36. step = (step + 1) >> 1; // Exponential decrease
  37. uint new_split = split + step; // Proposed new position
  38. if (new_split < inTriangles.mEnd)
  39. {
  40. uint32 split_code = mMortonCodes[mSortedTriangleIdx[new_split]];
  41. uint split_prefix = CountLeadingZeros(first_code ^ split_code);
  42. if (split_prefix > common_prefix)
  43. split = new_split; // Accept proposal
  44. }
  45. }
  46. while (step > 1);
  47. outLeft = Range(inTriangles.mBegin, split + 1);
  48. outRight = Range(split + 1, inTriangles.mEnd);
  49. return outLeft.Count() > 0 && outRight.Count() > 0;
  50. }
  51. JPH_NAMESPACE_END