initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
This commit is contained in:
73
thirdparty/jolt_physics/Jolt/TriangleSplitter/TriangleSplitter.cpp
vendored
Normal file
73
thirdparty/jolt_physics/Jolt/TriangleSplitter/TriangleSplitter.cpp
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <Jolt/Jolt.h>
|
||||
|
||||
#include <Jolt/TriangleSplitter/TriangleSplitter.h>
|
||||
|
||||
JPH_NAMESPACE_BEGIN
|
||||
|
||||
TriangleSplitter::TriangleSplitter(const VertexList &inVertices, const IndexedTriangleList &inTriangles) :
|
||||
mVertices(inVertices),
|
||||
mTriangles(inTriangles)
|
||||
{
|
||||
mSortedTriangleIdx.resize(inTriangles.size());
|
||||
mCentroids.resize(inTriangles.size() + 1); // Add 1 so we can load with Vec3::sLoadFloat3Unsafe
|
||||
|
||||
for (uint t = 0; t < inTriangles.size(); ++t)
|
||||
{
|
||||
// Initially triangles start unsorted
|
||||
mSortedTriangleIdx[t] = t;
|
||||
|
||||
// Calculate centroid
|
||||
inTriangles[t].GetCentroid(inVertices).StoreFloat3(&mCentroids[t]);
|
||||
}
|
||||
|
||||
// Make sure Vec3::sLoatFloat3Unsafe doesn't read uninitialized data
|
||||
mCentroids.back() = Float3(0, 0, 0);
|
||||
}
|
||||
|
||||
bool TriangleSplitter::SplitInternal(const Range &inTriangles, uint inDimension, float inSplit, Range &outLeft, Range &outRight)
|
||||
{
|
||||
// Divide triangles
|
||||
uint *start = mSortedTriangleIdx.data() + inTriangles.mBegin;
|
||||
uint *end = mSortedTriangleIdx.data() + inTriangles.mEnd;
|
||||
while (start < end)
|
||||
{
|
||||
// Search for first element that is on the right hand side of the split plane
|
||||
while (start < end && mCentroids[*start][inDimension] < inSplit)
|
||||
++start;
|
||||
|
||||
// Search for the first element that is on the left hand side of the split plane
|
||||
while (start < end && mCentroids[*(end - 1)][inDimension] >= inSplit)
|
||||
--end;
|
||||
|
||||
if (start < end)
|
||||
{
|
||||
// Swap the two elements
|
||||
--end;
|
||||
std::swap(*start, *end);
|
||||
++start;
|
||||
}
|
||||
}
|
||||
JPH_ASSERT(start == end);
|
||||
|
||||
uint start_idx = uint(start - mSortedTriangleIdx.data());
|
||||
|
||||
#ifdef JPH_ENABLE_ASSERTS
|
||||
// Validate division algorithm
|
||||
JPH_ASSERT(inTriangles.mBegin <= start_idx);
|
||||
JPH_ASSERT(start_idx <= inTriangles.mEnd);
|
||||
for (uint i = inTriangles.mBegin; i < start_idx; ++i)
|
||||
JPH_ASSERT(mCentroids[mSortedTriangleIdx[i]][inDimension] < inSplit);
|
||||
for (uint i = start_idx; i < inTriangles.mEnd; ++i)
|
||||
JPH_ASSERT(mCentroids[mSortedTriangleIdx[i]][inDimension] >= inSplit);
|
||||
#endif
|
||||
|
||||
outLeft = Range(inTriangles.mBegin, start_idx);
|
||||
outRight = Range(start_idx, inTriangles.mEnd);
|
||||
return outLeft.Count() > 0 && outRight.Count() > 0;
|
||||
}
|
||||
|
||||
JPH_NAMESPACE_END
|
84
thirdparty/jolt_physics/Jolt/TriangleSplitter/TriangleSplitter.h
vendored
Normal file
84
thirdparty/jolt_physics/Jolt/TriangleSplitter/TriangleSplitter.h
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Jolt/Geometry/IndexedTriangle.h>
|
||||
#include <Jolt/Core/NonCopyable.h>
|
||||
|
||||
JPH_NAMESPACE_BEGIN
|
||||
|
||||
/// A class that splits a triangle list into two parts for building a tree
|
||||
class JPH_EXPORT TriangleSplitter : public NonCopyable
|
||||
{
|
||||
public:
|
||||
/// Constructor
|
||||
TriangleSplitter(const VertexList &inVertices, const IndexedTriangleList &inTriangles);
|
||||
|
||||
/// Virtual destructor
|
||||
virtual ~TriangleSplitter() = default;
|
||||
|
||||
struct Stats
|
||||
{
|
||||
const char * mSplitterName = nullptr;
|
||||
int mLeafSize = 0;
|
||||
};
|
||||
|
||||
/// Get stats of splitter
|
||||
virtual void GetStats(Stats &outStats) const = 0;
|
||||
|
||||
/// Helper struct to indicate triangle range before and after the split
|
||||
struct Range
|
||||
{
|
||||
/// Constructor
|
||||
Range() = default;
|
||||
Range(uint inBegin, uint inEnd) : mBegin(inBegin), mEnd(inEnd) { }
|
||||
|
||||
/// Get number of triangles in range
|
||||
uint Count() const
|
||||
{
|
||||
return mEnd - mBegin;
|
||||
}
|
||||
|
||||
/// Start and end index (end = 1 beyond end)
|
||||
uint mBegin;
|
||||
uint mEnd;
|
||||
};
|
||||
|
||||
/// Range of triangles to start with
|
||||
Range GetInitialRange() const
|
||||
{
|
||||
return Range(0, (uint)mSortedTriangleIdx.size());
|
||||
}
|
||||
|
||||
/// Split triangles into two groups left and right, returns false if no split could be made
|
||||
/// @param inTriangles The range of triangles (in mSortedTriangleIdx) to process
|
||||
/// @param outLeft On return this will contain the ranges for the left subpart. mSortedTriangleIdx may have been shuffled.
|
||||
/// @param outRight On return this will contain the ranges for the right subpart. mSortedTriangleIdx may have been shuffled.
|
||||
/// @return Returns true when a split was found
|
||||
virtual bool Split(const Range &inTriangles, Range &outLeft, Range &outRight) = 0;
|
||||
|
||||
/// Get the list of vertices
|
||||
const VertexList & GetVertices() const
|
||||
{
|
||||
return mVertices;
|
||||
}
|
||||
|
||||
/// Get triangle by index
|
||||
const IndexedTriangle & GetTriangle(uint inIdx) const
|
||||
{
|
||||
return mTriangles[mSortedTriangleIdx[inIdx]];
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Helper function to split triangles based on dimension and split value
|
||||
bool SplitInternal(const Range &inTriangles, uint inDimension, float inSplit, Range &outLeft, Range &outRight);
|
||||
|
||||
const VertexList & mVertices; ///< Vertices of the indexed triangles
|
||||
const IndexedTriangleList & mTriangles; ///< Unsorted triangles
|
||||
Array<Float3> mCentroids; ///< Unsorted centroids of triangles
|
||||
Array<uint> mSortedTriangleIdx; ///< Indices to sort triangles
|
||||
};
|
||||
|
||||
JPH_NAMESPACE_END
|
139
thirdparty/jolt_physics/Jolt/TriangleSplitter/TriangleSplitterBinning.cpp
vendored
Normal file
139
thirdparty/jolt_physics/Jolt/TriangleSplitter/TriangleSplitterBinning.cpp
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <Jolt/Jolt.h>
|
||||
|
||||
#include <Jolt/TriangleSplitter/TriangleSplitterBinning.h>
|
||||
|
||||
JPH_NAMESPACE_BEGIN
|
||||
|
||||
TriangleSplitterBinning::TriangleSplitterBinning(const VertexList &inVertices, const IndexedTriangleList &inTriangles, uint inMinNumBins, uint inMaxNumBins, uint inNumTrianglesPerBin) :
|
||||
TriangleSplitter(inVertices, inTriangles),
|
||||
mMinNumBins(inMinNumBins),
|
||||
mMaxNumBins(inMaxNumBins),
|
||||
mNumTrianglesPerBin(inNumTrianglesPerBin)
|
||||
{
|
||||
mBins.resize(mMaxNumBins * 3); // mMaxNumBins per dimension
|
||||
}
|
||||
|
||||
bool TriangleSplitterBinning::Split(const Range &inTriangles, Range &outLeft, Range &outRight)
|
||||
{
|
||||
const uint *begin = mSortedTriangleIdx.data() + inTriangles.mBegin;
|
||||
const uint *end = mSortedTriangleIdx.data() + inTriangles.mEnd;
|
||||
|
||||
// Calculate bounds for this range
|
||||
AABox centroid_bounds;
|
||||
for (const uint *t = begin; t < end; ++t)
|
||||
centroid_bounds.Encapsulate(Vec3::sLoadFloat3Unsafe(mCentroids[*t]));
|
||||
|
||||
// Convert bounds to min coordinate and size
|
||||
// Prevent division by zero if one of the dimensions is zero
|
||||
constexpr float cMinSize = 1.0e-5f;
|
||||
Vec3 bounds_min = centroid_bounds.mMin;
|
||||
Vec3 bounds_size = Vec3::sMax(centroid_bounds.mMax - bounds_min, Vec3::sReplicate(cMinSize));
|
||||
|
||||
float best_cp = FLT_MAX;
|
||||
uint best_dim = 0xffffffff;
|
||||
float best_split = 0;
|
||||
|
||||
// Bin in all dimensions
|
||||
uint num_bins = Clamp(inTriangles.Count() / mNumTrianglesPerBin, mMinNumBins, mMaxNumBins);
|
||||
|
||||
// Initialize bins
|
||||
for (uint dim = 0; dim < 3; ++dim)
|
||||
{
|
||||
// Get bounding box size for this dimension
|
||||
float bounds_min_dim = bounds_min[dim];
|
||||
float bounds_size_dim = bounds_size[dim];
|
||||
|
||||
// Get the bins for this dimension
|
||||
Bin *bins_dim = &mBins[num_bins * dim];
|
||||
|
||||
for (uint b = 0; b < num_bins; ++b)
|
||||
{
|
||||
Bin &bin = bins_dim[b];
|
||||
bin.mBounds.SetEmpty();
|
||||
bin.mMinCentroid = bounds_min_dim + bounds_size_dim * (b + 1) / num_bins;
|
||||
bin.mNumTriangles = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Bin all triangles in all dimensions at once
|
||||
for (const uint *t = begin; t < end; ++t)
|
||||
{
|
||||
Vec3 centroid_pos = Vec3::sLoadFloat3Unsafe(mCentroids[*t]);
|
||||
|
||||
AABox triangle_bounds = AABox::sFromTriangle(mVertices, mTriangles[*t]);
|
||||
|
||||
Vec3 bin_no_f = (centroid_pos - bounds_min) / bounds_size * float(num_bins);
|
||||
UVec4 bin_no = UVec4::sMin(bin_no_f.ToInt(), UVec4::sReplicate(num_bins - 1));
|
||||
|
||||
for (uint dim = 0; dim < 3; ++dim)
|
||||
{
|
||||
// Select bin
|
||||
Bin &bin = mBins[num_bins * dim + bin_no[dim]];
|
||||
|
||||
// Accumulate triangle in bin
|
||||
bin.mBounds.Encapsulate(triangle_bounds);
|
||||
bin.mMinCentroid = min(bin.mMinCentroid, centroid_pos[dim]);
|
||||
bin.mNumTriangles++;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint dim = 0; dim < 3; ++dim)
|
||||
{
|
||||
// Skip axis if too small
|
||||
if (bounds_size[dim] <= cMinSize)
|
||||
continue;
|
||||
|
||||
// Get the bins for this dimension
|
||||
Bin *bins_dim = &mBins[num_bins * dim];
|
||||
|
||||
// Calculate totals left to right
|
||||
AABox prev_bounds;
|
||||
int prev_triangles = 0;
|
||||
for (uint b = 0; b < num_bins; ++b)
|
||||
{
|
||||
Bin &bin = bins_dim[b];
|
||||
bin.mBoundsAccumulatedLeft = prev_bounds; // Don't include this node as we'll take a split on the left side of the bin
|
||||
bin.mNumTrianglesAccumulatedLeft = prev_triangles;
|
||||
prev_bounds.Encapsulate(bin.mBounds);
|
||||
prev_triangles += bin.mNumTriangles;
|
||||
}
|
||||
|
||||
// Calculate totals right to left
|
||||
prev_bounds.SetEmpty();
|
||||
prev_triangles = 0;
|
||||
for (int b = num_bins - 1; b >= 0; --b)
|
||||
{
|
||||
Bin &bin = bins_dim[b];
|
||||
prev_bounds.Encapsulate(bin.mBounds);
|
||||
prev_triangles += bin.mNumTriangles;
|
||||
bin.mBoundsAccumulatedRight = prev_bounds;
|
||||
bin.mNumTrianglesAccumulatedRight = prev_triangles;
|
||||
}
|
||||
|
||||
// Get best splitting plane
|
||||
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
|
||||
{
|
||||
// Calculate surface area heuristic and see if it is better than the current best
|
||||
const Bin &bin = bins_dim[b];
|
||||
float cp = bin.mBoundsAccumulatedLeft.GetSurfaceArea() * bin.mNumTrianglesAccumulatedLeft + bin.mBoundsAccumulatedRight.GetSurfaceArea() * bin.mNumTrianglesAccumulatedRight;
|
||||
if (cp < best_cp)
|
||||
{
|
||||
best_cp = cp;
|
||||
best_dim = dim;
|
||||
best_split = bin.mMinCentroid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No split found?
|
||||
if (best_dim == 0xffffffff)
|
||||
return false;
|
||||
|
||||
return SplitInternal(inTriangles, best_dim, best_split, outLeft, outRight);
|
||||
}
|
||||
|
||||
JPH_NAMESPACE_END
|
52
thirdparty/jolt_physics/Jolt/TriangleSplitter/TriangleSplitterBinning.h
vendored
Normal file
52
thirdparty/jolt_physics/Jolt/TriangleSplitter/TriangleSplitterBinning.h
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Jolt/TriangleSplitter/TriangleSplitter.h>
|
||||
#include <Jolt/Geometry/AABox.h>
|
||||
|
||||
JPH_NAMESPACE_BEGIN
|
||||
|
||||
/// Binning splitter approach taken from: Realtime Ray Tracing on GPU with BVH-based Packet Traversal by Johannes Gunther et al.
|
||||
class JPH_EXPORT TriangleSplitterBinning : public TriangleSplitter
|
||||
{
|
||||
public:
|
||||
/// Constructor
|
||||
TriangleSplitterBinning(const VertexList &inVertices, const IndexedTriangleList &inTriangles, uint inMinNumBins = 8, uint inMaxNumBins = 128, uint inNumTrianglesPerBin = 6);
|
||||
|
||||
// See TriangleSplitter::GetStats
|
||||
virtual void GetStats(Stats &outStats) const override
|
||||
{
|
||||
outStats.mSplitterName = "TriangleSplitterBinning";
|
||||
}
|
||||
|
||||
// See TriangleSplitter::Split
|
||||
virtual bool Split(const Range &inTriangles, Range &outLeft, Range &outRight) override;
|
||||
|
||||
private:
|
||||
// Configuration
|
||||
const uint mMinNumBins;
|
||||
const uint mMaxNumBins;
|
||||
const uint mNumTrianglesPerBin;
|
||||
|
||||
struct Bin
|
||||
{
|
||||
// Properties of this bin
|
||||
AABox mBounds;
|
||||
float mMinCentroid;
|
||||
uint mNumTriangles;
|
||||
|
||||
// Accumulated data from left most / right most bin to current (including this bin)
|
||||
AABox mBoundsAccumulatedLeft;
|
||||
AABox mBoundsAccumulatedRight;
|
||||
uint mNumTrianglesAccumulatedLeft;
|
||||
uint mNumTrianglesAccumulatedRight;
|
||||
};
|
||||
|
||||
// Scratch area to store the bins
|
||||
Array<Bin> mBins;
|
||||
};
|
||||
|
||||
JPH_NAMESPACE_END
|
43
thirdparty/jolt_physics/Jolt/TriangleSplitter/TriangleSplitterMean.cpp
vendored
Normal file
43
thirdparty/jolt_physics/Jolt/TriangleSplitter/TriangleSplitterMean.cpp
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <Jolt/Jolt.h>
|
||||
|
||||
#include <Jolt/TriangleSplitter/TriangleSplitterMean.h>
|
||||
|
||||
JPH_NAMESPACE_BEGIN
|
||||
|
||||
TriangleSplitterMean::TriangleSplitterMean(const VertexList &inVertices, const IndexedTriangleList &inTriangles) :
|
||||
TriangleSplitter(inVertices, inTriangles)
|
||||
{
|
||||
}
|
||||
|
||||
bool TriangleSplitterMean::Split(const Range &inTriangles, Range &outLeft, Range &outRight)
|
||||
{
|
||||
const uint *begin = mSortedTriangleIdx.data() + inTriangles.mBegin;
|
||||
const uint *end = mSortedTriangleIdx.data() + inTriangles.mEnd;
|
||||
|
||||
// Calculate mean value for these triangles
|
||||
Vec3 mean = Vec3::sZero();
|
||||
for (const uint *t = begin; t < end; ++t)
|
||||
mean += Vec3::sLoadFloat3Unsafe(mCentroids[*t]);
|
||||
mean *= 1.0f / inTriangles.Count();
|
||||
|
||||
// Calculate deviation
|
||||
Vec3 deviation = Vec3::sZero();
|
||||
for (const uint *t = begin; t < end; ++t)
|
||||
{
|
||||
Vec3 delta = Vec3::sLoadFloat3Unsafe(mCentroids[*t]) - mean;
|
||||
deviation += delta * delta;
|
||||
}
|
||||
deviation *= 1.0f / inTriangles.Count();
|
||||
|
||||
// Calculate split plane
|
||||
uint dimension = deviation.GetHighestComponentIndex();
|
||||
float split = mean[dimension];
|
||||
|
||||
return SplitInternal(inTriangles, dimension, split, outLeft, outRight);
|
||||
}
|
||||
|
||||
JPH_NAMESPACE_END
|
28
thirdparty/jolt_physics/Jolt/TriangleSplitter/TriangleSplitterMean.h
vendored
Normal file
28
thirdparty/jolt_physics/Jolt/TriangleSplitter/TriangleSplitterMean.h
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Jolt/TriangleSplitter/TriangleSplitter.h>
|
||||
|
||||
JPH_NAMESPACE_BEGIN
|
||||
|
||||
/// Splitter using mean of axis with biggest centroid deviation
|
||||
class JPH_EXPORT TriangleSplitterMean : public TriangleSplitter
|
||||
{
|
||||
public:
|
||||
/// Constructor
|
||||
TriangleSplitterMean(const VertexList &inVertices, const IndexedTriangleList &inTriangles);
|
||||
|
||||
// See TriangleSplitter::GetStats
|
||||
virtual void GetStats(Stats &outStats) const override
|
||||
{
|
||||
outStats.mSplitterName = "TriangleSplitterMean";
|
||||
}
|
||||
|
||||
// See TriangleSplitter::Split
|
||||
virtual bool Split(const Range &inTriangles, Range &outLeft, Range &outRight) override;
|
||||
};
|
||||
|
||||
JPH_NAMESPACE_END
|
Reference in New Issue
Block a user