mirror of
https://github.com/godotengine/godot.git
synced 2026-01-03 18:11:19 +03:00
Merge pull request #113964 from akien-mga/manifold-3.3.2
manifold: Update to 3.3.2
This commit is contained in:
2
thirdparty/README.md
vendored
2
thirdparty/README.md
vendored
@@ -658,7 +658,7 @@ See `linuxbsd_headers/README.md`.
|
|||||||
## manifold
|
## manifold
|
||||||
|
|
||||||
- Upstream: https://github.com/elalish/manifold
|
- Upstream: https://github.com/elalish/manifold
|
||||||
- Version: git (76208dc02b069d2be50ed2d8a9279ee5622fa5fd, 2025)
|
- Version: 3.3.2 (798d83c8d7fabcddd23c1617097b95ba40f2597c, 2025)
|
||||||
- License: Apache 2.0
|
- License: Apache 2.0
|
||||||
|
|
||||||
File extracted from upstream source:
|
File extracted from upstream source:
|
||||||
|
|||||||
111
thirdparty/manifold/include/manifold/common.h
vendored
111
thirdparty/manifold/include/manifold/common.h
vendored
@@ -488,80 +488,12 @@ constexpr double DEFAULT_LENGTH = 1.0;
|
|||||||
*/
|
*/
|
||||||
class Quality {
|
class Quality {
|
||||||
private:
|
private:
|
||||||
inline static int circularSegments_ = DEFAULT_SEGMENTS;
|
|
||||||
inline static double circularAngle_ = DEFAULT_ANGLE;
|
|
||||||
inline static double circularEdgeLength_ = DEFAULT_LENGTH;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
static void SetMinCircularAngle(double angle);
|
||||||
* Sets an angle constraint the default number of circular segments for the
|
static void SetMinCircularEdgeLength(double length);
|
||||||
* CrossSection::Circle(), Manifold::Cylinder(), Manifold::Sphere(), and
|
static void SetCircularSegments(int number);
|
||||||
* Manifold::Revolve() constructors. The number of segments will be rounded up
|
static int GetCircularSegments(double radius);
|
||||||
* to the nearest factor of four.
|
static void ResetToDefaults();
|
||||||
*
|
|
||||||
* @param angle The minimum angle in degrees between consecutive segments. The
|
|
||||||
* angle will increase if the the segments hit the minimum edge length.
|
|
||||||
* Default is 10 degrees.
|
|
||||||
*/
|
|
||||||
static void SetMinCircularAngle(double angle) {
|
|
||||||
if (angle <= 0) return;
|
|
||||||
circularAngle_ = angle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a length constraint the default number of circular segments for the
|
|
||||||
* CrossSection::Circle(), Manifold::Cylinder(), Manifold::Sphere(), and
|
|
||||||
* Manifold::Revolve() constructors. The number of segments will be rounded up
|
|
||||||
* to the nearest factor of four.
|
|
||||||
*
|
|
||||||
* @param length The minimum length of segments. The length will
|
|
||||||
* increase if the the segments hit the minimum angle. Default is 1.0.
|
|
||||||
*/
|
|
||||||
static void SetMinCircularEdgeLength(double length) {
|
|
||||||
if (length <= 0) return;
|
|
||||||
circularEdgeLength_ = length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the default number of circular segments for the
|
|
||||||
* CrossSection::Circle(), Manifold::Cylinder(), Manifold::Sphere(), and
|
|
||||||
* Manifold::Revolve() constructors. Overrides the edge length and angle
|
|
||||||
* constraints and sets the number of segments to exactly this value.
|
|
||||||
*
|
|
||||||
* @param number Number of circular segments. Default is 0, meaning no
|
|
||||||
* constraint is applied.
|
|
||||||
*/
|
|
||||||
static void SetCircularSegments(int number) {
|
|
||||||
if (number < 3 && number != 0) return;
|
|
||||||
circularSegments_ = number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine the result of the SetMinCircularAngle(),
|
|
||||||
* SetMinCircularEdgeLength(), and SetCircularSegments() defaults.
|
|
||||||
*
|
|
||||||
* @param radius For a given radius of circle, determine how many default
|
|
||||||
* segments there will be.
|
|
||||||
*/
|
|
||||||
static int GetCircularSegments(double radius) {
|
|
||||||
if (circularSegments_ > 0) return circularSegments_;
|
|
||||||
int nSegA = 360.0 / circularAngle_;
|
|
||||||
int nSegL = 2.0 * radius * kPi / circularEdgeLength_;
|
|
||||||
int nSeg = fmin(nSegA, nSegL) + 3;
|
|
||||||
nSeg -= nSeg % 4;
|
|
||||||
return std::max(nSeg, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets the circular construction parameters to their defaults if
|
|
||||||
* SetMinCircularAngle, SetMinCircularEdgeLength, or SetCircularSegments have
|
|
||||||
* been called.
|
|
||||||
*/
|
|
||||||
static void ResetToDefaults() {
|
|
||||||
circularSegments_ = DEFAULT_SEGMENTS;
|
|
||||||
circularAngle_ = DEFAULT_ANGLE;
|
|
||||||
circularEdgeLength_ = DEFAULT_LENGTH;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
@@ -600,39 +532,6 @@ struct ExecutionParams {
|
|||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
#ifdef MANIFOLD_DEBUG
|
#ifdef MANIFOLD_DEBUG
|
||||||
template <class T>
|
|
||||||
std::ostream& operator<<(std::ostream& out, const la::vec<T, 1>& v) {
|
|
||||||
return out << '{' << v[0] << '}';
|
|
||||||
}
|
|
||||||
template <class T>
|
|
||||||
std::ostream& operator<<(std::ostream& out, const la::vec<T, 2>& v) {
|
|
||||||
return out << '{' << v[0] << ',' << v[1] << '}';
|
|
||||||
}
|
|
||||||
template <class T>
|
|
||||||
std::ostream& operator<<(std::ostream& out, const la::vec<T, 3>& v) {
|
|
||||||
return out << '{' << v[0] << ',' << v[1] << ',' << v[2] << '}';
|
|
||||||
}
|
|
||||||
template <class T>
|
|
||||||
std::ostream& operator<<(std::ostream& out, const la::vec<T, 4>& v) {
|
|
||||||
return out << '{' << v[0] << ',' << v[1] << ',' << v[2] << ',' << v[3] << '}';
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T, int M>
|
|
||||||
std::ostream& operator<<(std::ostream& out, const la::mat<T, M, 1>& m) {
|
|
||||||
return out << '{' << m[0] << '}';
|
|
||||||
}
|
|
||||||
template <class T, int M>
|
|
||||||
std::ostream& operator<<(std::ostream& out, const la::mat<T, M, 2>& m) {
|
|
||||||
return out << '{' << m[0] << ',' << m[1] << '}';
|
|
||||||
}
|
|
||||||
template <class T, int M>
|
|
||||||
std::ostream& operator<<(std::ostream& out, const la::mat<T, M, 3>& m) {
|
|
||||||
return out << '{' << m[0] << ',' << m[1] << ',' << m[2] << '}';
|
|
||||||
}
|
|
||||||
template <class T, int M>
|
|
||||||
std::ostream& operator<<(std::ostream& out, const la::mat<T, M, 4>& m) {
|
|
||||||
return out << '{' << m[0] << ',' << m[1] << ',' << m[2] << ',' << m[3] << '}';
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::ostream& operator<<(std::ostream& stream, const Box& box) {
|
inline std::ostream& operator<<(std::ostream& stream, const Box& box) {
|
||||||
return stream << "min: " << box.min << ", "
|
return stream << "min: " << box.min << ", "
|
||||||
|
|||||||
40
thirdparty/manifold/include/manifold/linalg.h
vendored
40
thirdparty/manifold/include/manifold/linalg.h
vendored
@@ -2360,6 +2360,46 @@ struct converter<std::array<T, 4>, vec<T, 4>> {
|
|||||||
/** @} */
|
/** @} */
|
||||||
} // namespace linalg
|
} // namespace linalg
|
||||||
|
|
||||||
|
#ifdef MANIFOLD_DEBUG
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace linalg {
|
||||||
|
template <class T>
|
||||||
|
std::ostream& operator<<(std::ostream& out, const vec<T, 1>& v) {
|
||||||
|
return out << '{' << v[0] << '}';
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
std::ostream& operator<<(std::ostream& out, const vec<T, 2>& v) {
|
||||||
|
return out << '{' << v[0] << ',' << v[1] << '}';
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
std::ostream& operator<<(std::ostream& out, const vec<T, 3>& v) {
|
||||||
|
return out << '{' << v[0] << ',' << v[1] << ',' << v[2] << '}';
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
std::ostream& operator<<(std::ostream& out, const vec<T, 4>& v) {
|
||||||
|
return out << '{' << v[0] << ',' << v[1] << ',' << v[2] << ',' << v[3] << '}';
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, int M>
|
||||||
|
std::ostream& operator<<(std::ostream& out, const mat<T, M, 1>& m) {
|
||||||
|
return out << '{' << m[0] << '}';
|
||||||
|
}
|
||||||
|
template <class T, int M>
|
||||||
|
std::ostream& operator<<(std::ostream& out, const mat<T, M, 2>& m) {
|
||||||
|
return out << '{' << m[0] << ',' << m[1] << '}';
|
||||||
|
}
|
||||||
|
template <class T, int M>
|
||||||
|
std::ostream& operator<<(std::ostream& out, const mat<T, M, 3>& m) {
|
||||||
|
return out << '{' << m[0] << ',' << m[1] << ',' << m[2] << '}';
|
||||||
|
}
|
||||||
|
template <class T, int M>
|
||||||
|
std::ostream& operator<<(std::ostream& out, const mat<T, M, 4>& m) {
|
||||||
|
return out << '{' << m[0] << ',' << m[1] << ',' << m[2] << ',' << m[3] << '}';
|
||||||
|
}
|
||||||
|
} // namespace linalg
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
/** @addtogroup hash
|
/** @addtogroup hash
|
||||||
* @ingroup LinAlg
|
* @ingroup LinAlg
|
||||||
|
|||||||
4
thirdparty/manifold/src/boolean_result.cpp
vendored
4
thirdparty/manifold/src/boolean_result.cpp
vendored
@@ -878,10 +878,6 @@ Manifold::Impl Boolean3::Result(OpType op) const {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Level 6
|
// Level 6
|
||||||
|
|
||||||
if (ManifoldParams().intermediateChecks)
|
|
||||||
DEBUG_ASSERT(outR.IsManifold(), logicErr, "polygon mesh is not manifold!");
|
|
||||||
|
|
||||||
outR.Face2Tri(faceEdge, halfedgeRef);
|
outR.Face2Tri(faceEdge, halfedgeRef);
|
||||||
halfedgeRef.clear();
|
halfedgeRef.clear();
|
||||||
faceEdge.clear();
|
faceEdge.clear();
|
||||||
|
|||||||
63
thirdparty/manifold/src/csg_tree.cpp
vendored
63
thirdparty/manifold/src/csg_tree.cpp
vendored
@@ -342,7 +342,9 @@ std::shared_ptr<CsgLeafNode> BatchBoolean(
|
|||||||
std::vector<std::shared_ptr<CsgLeafNode>> tmp;
|
std::vector<std::shared_ptr<CsgLeafNode>> tmp;
|
||||||
#if MANIFOLD_PAR == 1
|
#if MANIFOLD_PAR == 1
|
||||||
tbb::task_group group;
|
tbb::task_group group;
|
||||||
std::mutex mutex;
|
// make sure the order of result is deterministic
|
||||||
|
std::vector<std::shared_ptr<CsgLeafNode>> parallelTmp;
|
||||||
|
for (int i = 0; i < 4; i++) parallelTmp.push_back(nullptr);
|
||||||
#endif
|
#endif
|
||||||
while (results.size() > 1) {
|
while (results.size() > 1) {
|
||||||
for (size_t i = 0; i < 4 && results.size() > 1; i++) {
|
for (size_t i = 0; i < 4 && results.size() > 1; i++) {
|
||||||
@@ -353,11 +355,8 @@ std::shared_ptr<CsgLeafNode> BatchBoolean(
|
|||||||
auto b = std::move(results.back());
|
auto b = std::move(results.back());
|
||||||
results.pop_back();
|
results.pop_back();
|
||||||
#if MANIFOLD_PAR == 1
|
#if MANIFOLD_PAR == 1
|
||||||
group.run([&, a, b]() {
|
group.run([&, i, a, b]() {
|
||||||
auto result = SimpleBoolean(*a->GetImpl(), *b->GetImpl(), operation);
|
parallelTmp[i] = SimpleBoolean(*a->GetImpl(), *b->GetImpl(), operation);
|
||||||
mutex.lock();
|
|
||||||
tmp.push_back(result);
|
|
||||||
mutex.unlock();
|
|
||||||
});
|
});
|
||||||
#else
|
#else
|
||||||
auto result = SimpleBoolean(*a->GetImpl(), *b->GetImpl(), operation);
|
auto result = SimpleBoolean(*a->GetImpl(), *b->GetImpl(), operation);
|
||||||
@@ -366,6 +365,8 @@ std::shared_ptr<CsgLeafNode> BatchBoolean(
|
|||||||
}
|
}
|
||||||
#if MANIFOLD_PAR == 1
|
#if MANIFOLD_PAR == 1
|
||||||
group.wait();
|
group.wait();
|
||||||
|
for (int i = 0; i < 4 && parallelTmp[i]; i++)
|
||||||
|
tmp.emplace_back(std::move(parallelTmp[i]));
|
||||||
#endif
|
#endif
|
||||||
for (auto result : tmp) {
|
for (auto result : tmp) {
|
||||||
results.push_back(result);
|
results.push_back(result);
|
||||||
@@ -617,33 +618,35 @@ std::shared_ptr<CsgLeafNode> CsgOpNode::ToLeafNode() const {
|
|||||||
std::shared_ptr<CsgStackFrame> frame = stack.back();
|
std::shared_ptr<CsgStackFrame> frame = stack.back();
|
||||||
auto impl = frame->op_node->impl_.GetGuard();
|
auto impl = frame->op_node->impl_.GetGuard();
|
||||||
if (frame->finalize) {
|
if (frame->finalize) {
|
||||||
switch (frame->op_node->op_) {
|
if (!frame->op_node->cache_) {
|
||||||
case OpType::Add:
|
switch (frame->op_node->op_) {
|
||||||
*impl = {BatchUnion(frame->positive_children)};
|
case OpType::Add:
|
||||||
break;
|
*impl = {BatchUnion(frame->positive_children)};
|
||||||
case OpType::Intersect: {
|
break;
|
||||||
*impl = {BatchBoolean(OpType::Intersect, frame->positive_children)};
|
case OpType::Intersect: {
|
||||||
break;
|
*impl = {BatchBoolean(OpType::Intersect, frame->positive_children)};
|
||||||
};
|
break;
|
||||||
case OpType::Subtract:
|
};
|
||||||
if (frame->positive_children.empty()) {
|
case OpType::Subtract:
|
||||||
// nothing to subtract from, so the result is empty.
|
if (frame->positive_children.empty()) {
|
||||||
*impl = {std::make_shared<CsgLeafNode>()};
|
// nothing to subtract from, so the result is empty.
|
||||||
} else {
|
*impl = {std::make_shared<CsgLeafNode>()};
|
||||||
auto positive = BatchUnion(frame->positive_children);
|
|
||||||
if (frame->negative_children.empty()) {
|
|
||||||
// nothing to subtract, result equal to the LHS.
|
|
||||||
*impl = {frame->positive_children[0]};
|
|
||||||
} else {
|
} else {
|
||||||
auto negative = BatchUnion(frame->negative_children);
|
auto positive = BatchUnion(frame->positive_children);
|
||||||
*impl = {SimpleBoolean(*positive->GetImpl(), *negative->GetImpl(),
|
if (frame->negative_children.empty()) {
|
||||||
OpType::Subtract)};
|
// nothing to subtract, result equal to the LHS.
|
||||||
|
*impl = {frame->positive_children[0]};
|
||||||
|
} else {
|
||||||
|
auto negative = BatchUnion(frame->negative_children);
|
||||||
|
*impl = {SimpleBoolean(*positive->GetImpl(),
|
||||||
|
*negative->GetImpl(), OpType::Subtract)};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
break;
|
}
|
||||||
|
frame->op_node->cache_ = std::static_pointer_cast<CsgLeafNode>(
|
||||||
|
(*impl)[0]->Transform(frame->op_node->transform_));
|
||||||
}
|
}
|
||||||
frame->op_node->cache_ = std::static_pointer_cast<CsgLeafNode>(
|
|
||||||
(*impl)[0]->Transform(frame->op_node->transform_));
|
|
||||||
if (frame->positive_dest != nullptr)
|
if (frame->positive_dest != nullptr)
|
||||||
frame->positive_dest->push_back(std::static_pointer_cast<CsgLeafNode>(
|
frame->positive_dest->push_back(std::static_pointer_cast<CsgLeafNode>(
|
||||||
frame->op_node->cache_->Transform(frame->transform)));
|
frame->op_node->cache_->Transform(frame->transform)));
|
||||||
|
|||||||
1
thirdparty/manifold/src/edge_op.cpp
vendored
1
thirdparty/manifold/src/edge_op.cpp
vendored
@@ -202,6 +202,7 @@ namespace manifold {
|
|||||||
*/
|
*/
|
||||||
void Manifold::Impl::CleanupTopology() {
|
void Manifold::Impl::CleanupTopology() {
|
||||||
if (!halfedge_.size()) return;
|
if (!halfedge_.size()) return;
|
||||||
|
DEBUG_ASSERT(IsManifold(), logicErr, "polygon mesh is not manifold!");
|
||||||
|
|
||||||
// In the case of a very bad triangulation, it is possible to create pinched
|
// In the case of a very bad triangulation, it is possible to create pinched
|
||||||
// verts. They must be removed before edge collapse.
|
// verts. They must be removed before edge collapse.
|
||||||
|
|||||||
9
thirdparty/manifold/src/impl.cpp
vendored
9
thirdparty/manifold/src/impl.cpp
vendored
@@ -149,8 +149,12 @@ int GetLabels(std::vector<int>& components,
|
|||||||
namespace manifold {
|
namespace manifold {
|
||||||
|
|
||||||
#if (MANIFOLD_PAR == 1)
|
#if (MANIFOLD_PAR == 1)
|
||||||
|
#if (TBB_VERSION_MAJOR < 2021)
|
||||||
|
tbb::task_arena gc_arena(1, 1);
|
||||||
|
#else
|
||||||
tbb::task_arena gc_arena(1, 1, tbb::task_arena::priority::low);
|
tbb::task_arena gc_arena(1, 1, tbb::task_arena::priority::low);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
std::atomic<uint32_t> Manifold::Impl::meshIDCounter_(1);
|
std::atomic<uint32_t> Manifold::Impl::meshIDCounter_(1);
|
||||||
|
|
||||||
@@ -484,8 +488,9 @@ void Manifold::Impl::CreateHalfedges(const Vec<ivec3>& triProp,
|
|||||||
const int pair1 = ids[k];
|
const int pair1 = ids[k];
|
||||||
Halfedge& h1 = halfedge_[pair1];
|
Halfedge& h1 = halfedge_[pair1];
|
||||||
if (h0.startVert != h1.endVert || h0.endVert != h1.startVert) break;
|
if (h0.startVert != h1.endVert || h0.endVert != h1.startVert) break;
|
||||||
if (halfedge_[NextHalfedge(pair0)].endVert ==
|
if (h1.pairedHalfedge != kRemovedHalfedge &&
|
||||||
halfedge_[NextHalfedge(pair1)].endVert) {
|
halfedge_[NextHalfedge(pair0)].endVert ==
|
||||||
|
halfedge_[NextHalfedge(pair1)].endVert) {
|
||||||
h0.pairedHalfedge = h1.pairedHalfedge = kRemovedHalfedge;
|
h0.pairedHalfedge = h1.pairedHalfedge = kRemovedHalfedge;
|
||||||
// Reorder so that remaining edges pair up
|
// Reorder so that remaining edges pair up
|
||||||
if (k != i + numEdge) std::swap(ids[i + numEdge], ids[k]);
|
if (k != i + numEdge) std::swap(ids[i + numEdge], ids[k]);
|
||||||
|
|||||||
10
thirdparty/manifold/src/impl.h
vendored
10
thirdparty/manifold/src/impl.h
vendored
@@ -68,6 +68,16 @@ struct Manifold::Impl {
|
|||||||
const uint32_t numVert = meshGL.NumVert();
|
const uint32_t numVert = meshGL.NumVert();
|
||||||
const uint32_t numTri = meshGL.NumTri();
|
const uint32_t numTri = meshGL.NumTri();
|
||||||
|
|
||||||
|
if (numVert == 0 && numTri == 0) {
|
||||||
|
MakeEmpty(Error::NoError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numVert < 4 || numTri < 4) {
|
||||||
|
MakeEmpty(Error::NotManifold);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (meshGL.numProp < 3) {
|
if (meshGL.numProp < 3) {
|
||||||
MakeEmpty(Error::MissingPositionProperties);
|
MakeEmpty(Error::MissingPositionProperties);
|
||||||
return;
|
return;
|
||||||
|
|||||||
74
thirdparty/manifold/src/manifold.cpp
vendored
74
thirdparty/manifold/src/manifold.cpp
vendored
@@ -200,6 +200,80 @@ MeshGLP<Precision, I> GetMeshGLImpl(const manifold::Manifold::Impl& impl,
|
|||||||
|
|
||||||
namespace manifold {
|
namespace manifold {
|
||||||
|
|
||||||
|
static int circularSegments_ = DEFAULT_SEGMENTS;
|
||||||
|
static double circularAngle_ = DEFAULT_ANGLE;
|
||||||
|
static double circularEdgeLength_ = DEFAULT_LENGTH;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets an angle constraint the default number of circular segments for the
|
||||||
|
* CrossSection::Circle(), Manifold::Cylinder(), Manifold::Sphere(), and
|
||||||
|
* Manifold::Revolve() constructors. The number of segments will be rounded up
|
||||||
|
* to the nearest factor of four.
|
||||||
|
*
|
||||||
|
* @param angle The minimum angle in degrees between consecutive segments. The
|
||||||
|
* angle will increase if the the segments hit the minimum edge length.
|
||||||
|
* Default is 10 degrees.
|
||||||
|
*/
|
||||||
|
void Quality::SetMinCircularAngle(double angle) {
|
||||||
|
if (angle <= 0) return;
|
||||||
|
circularAngle_ = angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a length constraint the default number of circular segments for the
|
||||||
|
* CrossSection::Circle(), Manifold::Cylinder(), Manifold::Sphere(), and
|
||||||
|
* Manifold::Revolve() constructors. The number of segments will be rounded up
|
||||||
|
* to the nearest factor of four.
|
||||||
|
*
|
||||||
|
* @param length The minimum length of segments. The length will
|
||||||
|
* increase if the the segments hit the minimum angle. Default is 1.0.
|
||||||
|
*/
|
||||||
|
void Quality::SetMinCircularEdgeLength(double length) {
|
||||||
|
if (length <= 0) return;
|
||||||
|
circularEdgeLength_ = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the default number of circular segments for the
|
||||||
|
* CrossSection::Circle(), Manifold::Cylinder(), Manifold::Sphere(), and
|
||||||
|
* Manifold::Revolve() constructors. Overrides the edge length and angle
|
||||||
|
* constraints and sets the number of segments to exactly this value.
|
||||||
|
*
|
||||||
|
* @param number Number of circular segments. Default is 0, meaning no
|
||||||
|
* constraint is applied.
|
||||||
|
*/
|
||||||
|
void Quality::SetCircularSegments(int number) {
|
||||||
|
if (number < 3 && number != 0) return;
|
||||||
|
circularSegments_ = number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine the result of the SetMinCircularAngle(),
|
||||||
|
* SetMinCircularEdgeLength(), and SetCircularSegments() defaults.
|
||||||
|
*
|
||||||
|
* @param radius For a given radius of circle, determine how many default
|
||||||
|
* segments there will be.
|
||||||
|
*/
|
||||||
|
int Quality::GetCircularSegments(double radius) {
|
||||||
|
if (circularSegments_ > 0) return circularSegments_;
|
||||||
|
int nSegA = 360.0 / circularAngle_;
|
||||||
|
int nSegL = 2.0 * radius * kPi / circularEdgeLength_;
|
||||||
|
int nSeg = fmin(nSegA, nSegL) + 3;
|
||||||
|
nSeg -= nSeg % 4;
|
||||||
|
return std::max(nSeg, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the circular construction parameters to their defaults if
|
||||||
|
* SetMinCircularAngle, SetMinCircularEdgeLength, or SetCircularSegments have
|
||||||
|
* been called.
|
||||||
|
*/
|
||||||
|
void Quality::ResetToDefaults() {
|
||||||
|
circularSegments_ = DEFAULT_SEGMENTS;
|
||||||
|
circularAngle_ = DEFAULT_ANGLE;
|
||||||
|
circularEdgeLength_ = DEFAULT_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct an empty Manifold.
|
* Construct an empty Manifold.
|
||||||
*
|
*
|
||||||
|
|||||||
9
thirdparty/manifold/src/properties.cpp
vendored
9
thirdparty/manifold/src/properties.cpp
vendored
@@ -73,7 +73,13 @@ struct CheckHalfedges {
|
|||||||
|
|
||||||
bool operator()(size_t edge) const {
|
bool operator()(size_t edge) const {
|
||||||
const Halfedge halfedge = halfedges[edge];
|
const Halfedge halfedge = halfedges[edge];
|
||||||
if (halfedge.startVert == -1 || halfedge.endVert == -1) return true;
|
if (halfedge.startVert == -1 && halfedge.endVert == -1 &&
|
||||||
|
halfedge.pairedHalfedge == -1)
|
||||||
|
return true;
|
||||||
|
if (halfedges[NextHalfedge(edge)].startVert == -1 ||
|
||||||
|
halfedges[NextHalfedge(NextHalfedge(edge))].startVert == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (halfedge.pairedHalfedge == -1) return false;
|
if (halfedge.pairedHalfedge == -1) return false;
|
||||||
|
|
||||||
const Halfedge paired = halfedges[halfedge.pairedHalfedge];
|
const Halfedge paired = halfedges[halfedge.pairedHalfedge];
|
||||||
@@ -114,6 +120,7 @@ namespace manifold {
|
|||||||
*/
|
*/
|
||||||
bool Manifold::Impl::IsManifold() const {
|
bool Manifold::Impl::IsManifold() const {
|
||||||
if (halfedge_.size() == 0) return true;
|
if (halfedge_.size() == 0) return true;
|
||||||
|
if (halfedge_.size() % 3 != 0) return false;
|
||||||
return all_of(countAt(0_uz), countAt(halfedge_.size()),
|
return all_of(countAt(0_uz), countAt(halfedge_.size()),
|
||||||
CheckHalfedges({halfedge_}));
|
CheckHalfedges({halfedge_}));
|
||||||
}
|
}
|
||||||
|
|||||||
2
thirdparty/manifold/src/quickhull.cpp
vendored
2
thirdparty/manifold/src/quickhull.cpp
vendored
@@ -18,7 +18,9 @@
|
|||||||
#include "quickhull.h"
|
#include "quickhull.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cstddef>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "impl.h"
|
#include "impl.h"
|
||||||
|
|
||||||
|
|||||||
2
thirdparty/manifold/src/smoothing.cpp
vendored
2
thirdparty/manifold/src/smoothing.cpp
vendored
@@ -12,6 +12,8 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "impl.h"
|
#include "impl.h"
|
||||||
#include "parallel.h"
|
#include "parallel.h"
|
||||||
|
|
||||||
|
|||||||
225
thirdparty/manifold/src/sparse.h
vendored
225
thirdparty/manifold/src/sparse.h
vendored
@@ -1,225 +0,0 @@
|
|||||||
// Copyright 2021 The Manifold Authors.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "./parallel.h"
|
|
||||||
#include "./utils.h"
|
|
||||||
#include "./vec.h"
|
|
||||||
#include "manifold/common.h"
|
|
||||||
#include "manifold/optional_assert.h"
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
template <typename T>
|
|
||||||
inline bool FirstFinite(T v) {
|
|
||||||
return std::isfinite(v[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline bool FirstFinite<double>(double v) {
|
|
||||||
return std::isfinite(v);
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
namespace manifold {
|
|
||||||
|
|
||||||
/** @ingroup Private */
|
|
||||||
class SparseIndices {
|
|
||||||
// sparse indices where {p1: q1, p2: q2, ...} are laid out as
|
|
||||||
// p1 q1 p2 q2 or q1 p1 q2 p2, depending on endianness
|
|
||||||
// such that the indices are sorted by (p << 32) | q
|
|
||||||
public:
|
|
||||||
#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \
|
|
||||||
defined(__BIG_ENDIAN__) || defined(__ARMEB__) || defined(__THUMBEB__) || \
|
|
||||||
defined(__AARCH64EB__) || defined(_MIBSEB) || defined(__MIBSEB) || \
|
|
||||||
defined(__MIBSEB__)
|
|
||||||
static constexpr size_t pOffset = 0;
|
|
||||||
#elif defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || \
|
|
||||||
defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || \
|
|
||||||
defined(__THUMBEL__) || defined(__AARCH64EL__) || defined(_MIPSEL) || \
|
|
||||||
defined(__MIPSEL) || defined(__MIPSEL__) || defined(__EMSCRIPTEN__) || \
|
|
||||||
defined(_WIN32)
|
|
||||||
static constexpr size_t pOffset = 1;
|
|
||||||
#else
|
|
||||||
#error "unknown architecture"
|
|
||||||
#endif
|
|
||||||
static constexpr int64_t EncodePQ(int p, int q) {
|
|
||||||
return (int64_t(p) << 32) | q;
|
|
||||||
}
|
|
||||||
|
|
||||||
SparseIndices() = default;
|
|
||||||
SparseIndices(size_t size) { data_ = Vec<char>(size * sizeof(int64_t)); }
|
|
||||||
|
|
||||||
void Clear() { data_.clear(false); }
|
|
||||||
|
|
||||||
void FromIndices(const std::vector<SparseIndices>& indices) {
|
|
||||||
std::vector<size_t> sizes;
|
|
||||||
size_t total_size = 0;
|
|
||||||
for (const auto& ind : indices) {
|
|
||||||
sizes.push_back(total_size);
|
|
||||||
total_size += ind.data_.size();
|
|
||||||
}
|
|
||||||
data_ = Vec<char>(total_size);
|
|
||||||
for_each_n(ExecutionPolicy::Par, countAt(0), indices.size(), [&](size_t i) {
|
|
||||||
std::copy(indices[i].data_.begin(), indices[i].data_.end(),
|
|
||||||
data_.begin() + sizes[i]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size() const { return data_.size() / sizeof(int64_t); }
|
|
||||||
|
|
||||||
Vec<int> Copy(bool use_q) const {
|
|
||||||
Vec<int> out(size());
|
|
||||||
size_t offset = pOffset;
|
|
||||||
if (use_q) offset = 1 - offset;
|
|
||||||
const int* p = ptr();
|
|
||||||
for_each(autoPolicy(out.size()), countAt(0_uz), countAt(out.size()),
|
|
||||||
[&](size_t i) { out[i] = p[i * 2 + offset]; });
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Sort() {
|
|
||||||
VecView<int64_t> view = AsVec64();
|
|
||||||
stable_sort(view.begin(), view.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Resize(size_t size) { data_.resize(size * sizeof(int64_t), -1); }
|
|
||||||
|
|
||||||
inline int& Get(size_t i, bool use_q) {
|
|
||||||
if (use_q)
|
|
||||||
return ptr()[2 * i + 1 - pOffset];
|
|
||||||
else
|
|
||||||
return ptr()[2 * i + pOffset];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int Get(size_t i, bool use_q) const {
|
|
||||||
if (use_q)
|
|
||||||
return ptr()[2 * i + 1 - pOffset];
|
|
||||||
else
|
|
||||||
return ptr()[2 * i + pOffset];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int64_t GetPQ(size_t i) const {
|
|
||||||
VecView<const int64_t> view = AsVec64();
|
|
||||||
return view[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Set(size_t i, int p, int q) {
|
|
||||||
VecView<int64_t> view = AsVec64();
|
|
||||||
view[i] = EncodePQ(p, q);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void SetPQ(size_t i, int64_t pq) {
|
|
||||||
VecView<int64_t> view = AsVec64();
|
|
||||||
view[i] = pq;
|
|
||||||
}
|
|
||||||
|
|
||||||
VecView<int64_t> AsVec64() {
|
|
||||||
return VecView<int64_t>(reinterpret_cast<int64_t*>(data_.data()),
|
|
||||||
data_.size() / sizeof(int64_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
VecView<const int64_t> AsVec64() const {
|
|
||||||
return VecView<const int64_t>(
|
|
||||||
reinterpret_cast<const int64_t*>(data_.data()),
|
|
||||||
data_.size() / sizeof(int64_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
VecView<int32_t> AsVec32() {
|
|
||||||
return VecView<int32_t>(reinterpret_cast<int32_t*>(data_.data()),
|
|
||||||
data_.size() / sizeof(int32_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
VecView<const int32_t> AsVec32() const {
|
|
||||||
return VecView<const int32_t>(
|
|
||||||
reinterpret_cast<const int32_t*>(data_.data()),
|
|
||||||
data_.size() / sizeof(int32_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Add(int p, int q, bool seq = false) {
|
|
||||||
data_.extend(sizeof(int64_t), seq);
|
|
||||||
Set(size() - 1, p, q);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Unique() {
|
|
||||||
Sort();
|
|
||||||
VecView<int64_t> view = AsVec64();
|
|
||||||
size_t newSize = unique(view.begin(), view.end()) - view.begin();
|
|
||||||
Resize(newSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t RemoveZeros(Vec<int>& S) {
|
|
||||||
DEBUG_ASSERT(S.size() == size(), userErr,
|
|
||||||
"Different number of values than indicies!");
|
|
||||||
|
|
||||||
Vec<size_t> new2Old(S.size());
|
|
||||||
sequence(new2Old.begin(), new2Old.end());
|
|
||||||
|
|
||||||
size_t size = copy_if(countAt(0_uz), countAt(S.size()), new2Old.begin(),
|
|
||||||
[&S](const size_t i) { return S[i] != 0; }) -
|
|
||||||
new2Old.begin();
|
|
||||||
new2Old.resize(size);
|
|
||||||
|
|
||||||
Permute(S, new2Old);
|
|
||||||
Vec<char> tmp(std::move(data_));
|
|
||||||
Resize(size);
|
|
||||||
gather(new2Old.begin(), new2Old.end(),
|
|
||||||
reinterpret_cast<int64_t*>(tmp.data()),
|
|
||||||
reinterpret_cast<int64_t*>(data_.data()));
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
size_t KeepFinite(Vec<T>& v, Vec<int>& x) {
|
|
||||||
DEBUG_ASSERT(x.size() == size(), userErr,
|
|
||||||
"Different number of values than indicies!");
|
|
||||||
|
|
||||||
Vec<int> new2Old(v.size());
|
|
||||||
size_t size = copy_if(countAt(0_uz), countAt(v.size()), new2Old.begin(),
|
|
||||||
[&v](size_t i) { return FirstFinite(v[i]); }) -
|
|
||||||
new2Old.begin();
|
|
||||||
new2Old.resize(size);
|
|
||||||
|
|
||||||
Permute(v, new2Old);
|
|
||||||
Permute(x, new2Old);
|
|
||||||
Vec<char> tmp(std::move(data_));
|
|
||||||
Resize(size);
|
|
||||||
gather(new2Old.begin(), new2Old.end(),
|
|
||||||
reinterpret_cast<int64_t*>(tmp.data()),
|
|
||||||
reinterpret_cast<int64_t*>(data_.data()));
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef MANIFOLD_DEBUG
|
|
||||||
void Dump() const {
|
|
||||||
std::cout << "SparseIndices = " << std::endl;
|
|
||||||
const int* p = ptr();
|
|
||||||
for (size_t i = 0; i < size(); ++i) {
|
|
||||||
std::cout << i << ", p = " << Get(i, false) << ", q = " << Get(i, true)
|
|
||||||
<< std::endl;
|
|
||||||
}
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private:
|
|
||||||
Vec<char> data_;
|
|
||||||
inline int* ptr() { return reinterpret_cast<int32_t*>(data_.data()); }
|
|
||||||
inline const int* ptr() const {
|
|
||||||
return reinterpret_cast<const int32_t*>(data_.data());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace manifold
|
|
||||||
2
thirdparty/manifold/src/subdivision.cpp
vendored
2
thirdparty/manifold/src/subdivision.cpp
vendored
@@ -12,6 +12,8 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "impl.h"
|
#include "impl.h"
|
||||||
#include "parallel.h"
|
#include "parallel.h"
|
||||||
|
|
||||||
|
|||||||
4
thirdparty/manifold/src/vec.h
vendored
4
thirdparty/manifold/src/vec.h
vendored
@@ -228,10 +228,14 @@ class Vec : public VecView<T> {
|
|||||||
// Currently it is set to 64 pages (4kB page).
|
// Currently it is set to 64 pages (4kB page).
|
||||||
constexpr size_t ASYNC_FREE_THRESHOLD = 1 << 18;
|
constexpr size_t ASYNC_FREE_THRESHOLD = 1 << 18;
|
||||||
TracyFreeS(ptr, 3);
|
TracyFreeS(ptr, 3);
|
||||||
|
#if defined(__has_feature)
|
||||||
|
#if !__has_feature(address_sanitizer)
|
||||||
#if (MANIFOLD_PAR == 1)
|
#if (MANIFOLD_PAR == 1)
|
||||||
if (size * sizeof(T) > ASYNC_FREE_THRESHOLD)
|
if (size * sizeof(T) > ASYNC_FREE_THRESHOLD)
|
||||||
gc_arena.enqueue([ptr]() { free(ptr); });
|
gc_arena.enqueue([ptr]() { free(ptr); });
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
free(ptr);
|
free(ptr);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user