Update eigen to v5.0.1 and libigl to v2.6.0. (#11311)

* Update eigen from v3.3.7 to v5.0.1.

This updates eigen from v3.3.7 released on  December 11, 2018-12-11 to v5.0.1
released on 2025-11-11. There have be a large number of bug-fixes,
optimizations, and improvements between these releases. See the details at;

https://gitlab.com/libeigen/eigen/-/releases

It retains the previous custom minimal `CMakeLists.txt`, and adds a
README-OrcaSlicer.md that explains what version and parts of the upstream
eigen release have been included, and where the full release can be found.

* Update libigl from v2.0.0 (or older) to v2.6.0.

This updates libigl from what was probably v2.0.0 released on 2018-10-16 to
v2.6.0 released on 2025-05-15. It's possible the old version was even older
than that but there is no version indicators in the code and I ran out of
patience identifying missing changes and only went back as far as v2.0.0.

There have been a large number of bug-fixes, optimizations, and improvements
between these versions. See the following for details;

https://github.com/libigl/libigl/releases

I retained the minimal custom `CMakeLists.txt`, added `README.md` from the
libigl distribution which identifies the version, and added a
README-OrcaSlicer.md that details the version and parts that have been
included.

* Update libslic3r for libigl v2.6.0 changes.

This updates libslic3r for all changes moving to eigen v5.0.1 and libigl
v2.6.0. Despite the large number of updates to both dependencies, no changes
were required for the eigen update, and only one change was required for the
libigl update.

For libigl, `igl::Hit` was changed to a template taking the Scalar type to
use. Previously it was hard-coded to `float`, so to minimize possible impact
I've updated all places it is used from `igl::Hit` to `igl::Hit<float>`.

* Add compiler option `-DNOMINMAX` for libigl with MSVC.

MSVC by default defines `min(()` and `max()` macros that break
`std::numeric_limits<>::max()`. The upstream cmake that we don't include
adds `-DNOMINMAX` for the libigl module when compiling with MSVC, so we need
to add the same thing here.

* Fix src/libslic3r/TriangleMeshDeal.cpp for the unmodified upstream libigl.

This fixes `TriangleMeshDeal.cpp` to work with the unmodified upstream
libigl v2.6.0. loop.{h,cpp} implementation.

This file and feature was added in PR "BBS Port: Mesh Subdivision" (#12150)
which included changes to `loop.{h,cpp}` in the old version of libigl. This PR
avoids modifying the included dependencies, and uses the updated upstream
versions of those files without any modifications, which requires fixing
TriangleMeshDeal.cpp to work with them.

In particular, the modifications made to `loop.{h,cpp}` included changing the
return type from void to bool, adding additional validation checking of the
input meshes, and returning false if they failed validation. These added
checks looked unnecessary and would only have caught problems if the input
mesh was very corrupt.

To make `TriangleMeshDeal.cpp` work without this built-in checking
functionality, I removed checking/handling of any `false` return value.

There was also a hell of a lot of redundant copying and casting back and forth
between float and double, so I cleaned that up. The input and output meshs use
floats for the vertexes, and there would be no accuracy benefits from casting
to and from doubles for the simple weighted average operations done by
igl::loop(). So this just uses `Eigen:Map` to use the original input mesh
vertex data directly without requiring any copy or casting.

* Move eigen from included `deps_src` to externaly fetched `deps`.

This copys what PrusaSlicer did and moved it from an included dependency under
`deps_src` to an externaly fetched dependency under `deps`. This requires
updating some `CMakeList.txt` configs and removing the old and obsolete
`cmake/modules/FindEigen3.cmake`. The details of when this was done in
PrusaSlicer and the followup fixes are at;

* 21116995d7
* https://github.com/prusa3d/PrusaSlicer/issues/13608
* https://github.com/prusa3d/PrusaSlicer/pull/13609
* e3c277b9ee

For some reason I don't fully understand this also required fixing
`src/slic3r/GUI/GUI_App.cpp` by adding `#include <boost/nowide/cstdio.hpp>` to
fix an `error: ‘remove’ is not a member of ‘boost::nowide'`. The main thing I
don't understand is how it worked before. Note that this include is in the
PrusaSlicer version of this file, but it also significantly deviates from what
is currently in OrcaSlicer in many other ways.

* Whups... I missed adding the deps/Eigen/Eigen.cmake file...

* Tidy some whitespace indenting in CMakeLists.txt.

* Ugh... tabs indenting needing fixes.

* Change the include order of deps/Eigen.

It turns out that although Boost includes some references to Eigen, Eigen also
includes some references to Boost for supporting some of it's additional
numeric types.

I don't think it matters much since we are not using these features, but I
think technically its more correct to say Eigen depends on Boost than the
other way around, so I've re-ordered them.

* Add source for Eigen 5.0.1 download to flatpak yml config.

* Add explicit `DEPENDS dep_Boost to deps/Eigen.

I missed this before. This ensures we don't rely on include orders to make
sure Boost is installed before we configure Eigen.

* Add `DEPENDS dep_Boost dep_GMP dep_MPFR` to deps/Eigen.

It turns out Eigen can also use GMP and MPFR for multi-precision and
multi-precision-rounded numeric types if they are available.

Again, I don't think we are using these so it doesn't really matter, but it is
technically correct and ensures they are there if we ever do need them.

* Fix deps DEPENDENCY ordering for GMP, MPFR, Eigen, and CGAL.

I think this is finally correct. Apparently CGAL also optionally depends on
Eigen, so the correct dependency order from lowest to highest is GMP, MPFR, Eigen, and CGAL.

---------

Co-authored-by: Donovan Baarda <dbaarda@google.com>
Co-authored-by: Noisyfox <timemanager.rick@gmail.com>
This commit is contained in:
Donovan Baarda
2026-05-12 17:09:13 +10:00
committed by GitHub
parent 797ee70b0b
commit dc5897d7b5
1573 changed files with 63323 additions and 161343 deletions

View File

@@ -1,6 +1,6 @@
// This file is part of libigl, a simple c++ geometry processing library.
//
// Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
// Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public License
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
@@ -11,6 +11,7 @@
#include "CGAL_includes.hpp"
#include "RemeshSelfIntersectionsParam.h"
#include "../../unique.h"
#include "../../default_num_threads.h"
#include <Eigen/Dense>
#include <list>
@@ -18,8 +19,9 @@
#include <vector>
#include <thread>
#include <mutex>
#include <cstdio>
//#define IGL_SELFINTERSECTMESH_DEBUG
//#define IGL_SELFINTERSECTMESH_TIMING
#ifndef IGL_FIRST_HIT_EXCEPTION
#define IGL_FIRST_HIT_EXCEPTION 10
#endif
@@ -32,11 +34,12 @@ namespace igl
{
namespace cgal
{
// Kernel is a CGAL kernel like:
// CGAL::Exact_predicates_inexact_constructions_kernel
// or
// CGAL::Exact_predicates_exact_constructions_kernel
/// Class for computing the self-intersections of a mesh
///
/// @tparam Kernel is a CGAL kernel like:
/// CGAL::Exact_predicates_inexact_constructions_kernel
/// or
/// CGAL::Exact_predicates_exact_constructions_kernel
template <
typename Kernel,
typename DerivedV,
@@ -48,7 +51,7 @@ namespace igl
typename DerivedIM>
class SelfIntersectMesh
{
typedef
typedef
SelfIntersectMesh<
Kernel,
DerivedV,
@@ -61,24 +64,24 @@ namespace igl
public:
// 3D Primitives
typedef CGAL::Point_3<Kernel> Point_3;
typedef CGAL::Segment_3<Kernel> Segment_3;
typedef CGAL::Triangle_3<Kernel> Triangle_3;
typedef CGAL::Segment_3<Kernel> Segment_3;
typedef CGAL::Triangle_3<Kernel> Triangle_3;
typedef CGAL::Plane_3<Kernel> Plane_3;
typedef CGAL::Tetrahedron_3<Kernel> Tetrahedron_3;
typedef CGAL::Tetrahedron_3<Kernel> Tetrahedron_3;
// 2D Primitives
typedef CGAL::Point_2<Kernel> Point_2;
typedef CGAL::Segment_2<Kernel> Segment_2;
typedef CGAL::Triangle_2<Kernel> Triangle_2;
typedef CGAL::Segment_2<Kernel> Segment_2;
typedef CGAL::Triangle_2<Kernel> Triangle_2;
// 2D Constrained Delaunay Triangulation types
typedef CGAL::Exact_intersections_tag Itag;
// Axis-align boxes for all-pairs self-intersection detection
typedef std::vector<Triangle_3> Triangles;
typedef typename Triangles::iterator TrianglesIterator;
typedef typename Triangles::const_iterator TrianglesConstIterator;
typedef
CGAL::Box_intersection_d::Box_with_handle_d<double,3,TrianglesIterator>
typedef
CGAL::Box_intersection_d::Box_with_handle_d<double,3,TrianglesIterator>
Box;
// Input mesh
const Eigen::MatrixBase<DerivedV> & V;
const Eigen::MatrixBase<DerivedF> & F;
@@ -107,10 +110,20 @@ namespace igl
public:
RemeshSelfIntersectionsParam params;
public:
// Constructs (VV,FF) a new mesh with self-intersections of (V,F)
// subdivided
//
// See also: remesh_self_intersections.h
/// Constructs (VV,FF) a new mesh with self-intersections of (V,F)
/// subdivided
///
/// @param[in] V #V by 3 list of vertex positions
/// @param[in] F #F by 3 list of triangle indices into V
/// @param[in] params parameters
/// @param[out] VV #VV by 3 list of vertex positions
/// @param[out] FF #FF by 3 list of triangle indices into VV
/// @param[out] IF #IF by 2 list of edge indices into VV
/// @param[out] J #F list of indices into FF of birth parents
/// @param[out] IM #VV list of indices into V of birth parents
///
///
/// \see remesh_self_intersections.h
inline SelfIntersectMesh(
const Eigen::MatrixBase<DerivedV> & V,
const Eigen::MatrixBase<DerivedF> & F,
@@ -121,47 +134,43 @@ namespace igl
Eigen::PlainObjectBase<DerivedJ> & J,
Eigen::PlainObjectBase<DerivedIM> & IM);
private:
// Helper function to mark a face as offensive
//
// Inputs:
// f index of face in F
/// Helper function to mark a face as offensive
///
/// @param[in] f index of face in F
inline void mark_offensive(const Index f);
// Helper function to count intersections between faces
//
// Input:
// fa index of face A in F
// fb index of face B in F
/// Helper function to count intersections between faces
///
/// @param[in] fa index of face A in F
/// @param[in] fb index of face B in F
inline void count_intersection( const Index fa, const Index fb);
// Helper function for box_intersect. Intersect two triangles A and B,
// append the intersection object (point,segment,triangle) to a running
// list for A and B
//
// Inputs:
// A triangle in 3D
// B triangle in 3D
// fa index of A in F (and key into offending)
// fb index of B in F (and key into offending)
// Returns true only if A intersects B
//
/// Helper function for box_intersect. Intersect two triangles A and B,
/// append the intersection object (point,segment,triangle) to a running
/// list for A and B
///
/// @param[in] A triangle in 3D
/// @param[in] B triangle in 3D
/// @param[in] fa index of A in F (and key into offending)
/// @param[in] fb index of B in F (and key into offending)
/// @return true only if A intersects B
///
inline bool intersect(
const Triangle_3 & A,
const Triangle_3 & B,
const Triangle_3 & A,
const Triangle_3 & B,
const Index fa,
const Index fb);
// Helper function for box_intersect. In the case where A and B have
// already been identified to share a vertex, then we only want to
// add possible segment intersections. Assumes truly duplicate
// triangles are not given as input
//
// Inputs:
// A triangle in 3D
// B triangle in 3D
// fa index of A in F (and key into offending)
// fb index of B in F (and key into offending)
// va index of shared vertex in A (and key into offending)
// vb index of shared vertex in B (and key into offending)
// Returns true if intersection (besides shared point)
//
/// Helper function for box_intersect. In the case where A and B have
/// already been identified to share a vertex, then we only want to
/// add possible segment intersections. Assumes truly duplicate
/// triangles are not given as input
///
/// @param[in] A triangle in 3D
/// @param[in] B triangle in 3D
/// @param[in] fa index of A in F (and key into offending)
/// @param[in] fb index of B in F (and key into offending)
/// @param[in] va index of shared vertex in A (and key into offending)
/// @param[in] vb index of shared vertex in B (and key into offending)
/// @return true if intersection (besides shared point)
///
inline bool single_shared_vertex(
const Triangle_3 & A,
const Triangle_3 & B,
@@ -169,40 +178,59 @@ namespace igl
const Index fb,
const Index va,
const Index vb);
// Helper handling one direction
//// Helper handling one direction
///
/// @param[in] A triangle in 3D
/// @param[in] B triangle in 3D
/// @param[in] fa index of A in F (and key into offending)
/// @param[in] fb index of B in F (and key into offending)
/// @param[in] va index of shared vertex in A (and key into offending)
/// @return true if intersection (besides shared point)
inline bool single_shared_vertex(
const Triangle_3 & A,
const Triangle_3 & B,
const Index fa,
const Index fb,
const Index va);
// Helper function for box_intersect. In the case where A and B have
// already been identified to share two vertices, then we only want
// to add a possible coplanar (Triangle) intersection. Assumes truly
// degenerate facets are not givin as input.
/// Helper function for box_intersect. In the case where A and B have
/// already been identified to share two vertices, then we only want
/// to add a possible coplanar (Triangle) intersection. Assumes truly
/// degenerate facets are not givin as input.
///
/// @param[in] A triangle in 3D
/// @param[in] B triangle in 3D
/// @param[in] fa index of A in F (and key into offending)
/// @param[in] fb index of B in F (and key into offending)
/// @param[in] shared list of pairs of indices of shared vertices
/// @return true if intersection (besides shared point)
inline bool double_shared_vertex(
const Triangle_3 & A,
const Triangle_3 & B,
const Index fa,
const Index fb,
const std::vector<std::pair<Index,Index> > shared);
public:
// Callback function called during box self intersections test. Means
// boxes a and b intersect. This method then checks if the triangles
// in each box intersect and if so, then processes the intersections
//
// Inputs:
// a box containing a triangle
// b box containing a triangle
/// Callback function called during box self intersections test. Means
/// boxes a and b intersect. This method then checks if the triangles
/// in each box intersect and if so, then processes the intersections
///
/// @param[in] a box containing a triangle
/// @param[in] b box containing a triangle
inline void box_intersect(const Box& a, const Box& b);
/// Process all of the intersecting boxes
inline void process_intersecting_boxes();
public:
// Getters:
//const IndexList& get_lIF() const{ return lIF;}
/// Static function that captures a SelfIntersectMesh instance to pass
/// to cgal.
/// @param[in] SIM pointer to SelfIntersectMesh instance
/// @param[in] a box containing a triangle
/// @param[in] b box containing a triangle
static inline void box_intersect_static(
SelfIntersectMesh * SIM,
const Box &a,
SelfIntersectMesh * SIM,
const Box &a,
const Box &b);
private:
std::mutex m_offending_lock;
@@ -216,7 +244,6 @@ namespace igl
#include "mesh_to_cgal_triangle_list.h"
#include "remesh_intersections.h"
#include "../../REDRUM.h"
#include "../../get_seconds.h"
#include "../../C_STR.h"
@@ -225,7 +252,6 @@ namespace igl
#include <algorithm>
#include <exception>
#include <cassert>
#include <iostream>
// References:
// http://minregret.googlecode.com/svn/trunk/skyline/src/extern/CGAL-3.3.1/examples/Polyhedron/polyhedron_self_intersection.cpp
@@ -245,7 +271,7 @@ namespace igl
// using boost:
// boost::function<void(const Box &a,const Box &b)> cb
// = boost::bind(&::box_intersect, this, _1,_2);
//
//
template <
typename Kernel,
typename DerivedV,
@@ -264,8 +290,8 @@ inline void igl::copyleft::cgal::SelfIntersectMesh<
DerivedIF,
DerivedJ,
DerivedIM>::box_intersect_static(
Self * SIM,
const typename Self::Box &a,
Self * SIM,
const typename Self::Box &a,
const typename Self::Box &b)
{
SIM->box_intersect(a,b);
@@ -308,7 +334,7 @@ inline igl::copyleft::cgal::SelfIntersectMesh<
using namespace std;
using namespace Eigen;
#ifdef IGL_SELFINTERSECTMESH_DEBUG
#ifdef IGL_SELFINTERSECTMESH_TIMING
const auto & tictoc = []() -> double
{
static double t_start = igl::get_seconds();
@@ -317,24 +343,24 @@ inline igl::copyleft::cgal::SelfIntersectMesh<
return diff;
};
const auto log_time = [&](const std::string& label) -> void{
std::cout << "SelfIntersectMesh." << label << ": "
<< tictoc() << std::endl;
std::printf("%50s: %0.5lf\n",
C_STR("SelfIntersectMesh." << label),tictoc());
};
tictoc();
#endif
// Compute and process self intersections
mesh_to_cgal_triangle_list(V,F,T);
#ifdef IGL_SELFINTERSECTMESH_DEBUG
#ifdef IGL_SELFINTERSECTMESH_TIMING
log_time("convert_to_triangle_list");
#endif
// http://www.cgal.org/Manual/latest/doc_html/cgal_manual/Box_intersection_d/Chapter_main.html#Section_63.5
// http://www.cgal.org/Manual/latest/doc_html/cgal_manual/Box_intersection_d/Chapter_main.html#Section_63.5
// Create the corresponding vector of bounding boxes
std::vector<Box> boxes;
boxes.reserve(T.size());
for (
TrianglesIterator tit = T.begin();
tit != T.end();
for (
TrianglesIterator tit = T.begin();
tit != T.end();
++tit)
{
if (!tit->is_degenerate())
@@ -343,18 +369,18 @@ inline igl::copyleft::cgal::SelfIntersectMesh<
}
}
// Leapfrog callback
std::function<void(const Box &a,const Box &b)> cb =
std::bind(&box_intersect_static, this,
std::function<void(const Box &a,const Box &b)> cb =
std::bind(&box_intersect_static, this,
// Explicitly use std namespace to avoid confusion with boost (who puts
// _1 etc. in global namespace)
std::placeholders::_1,
std::placeholders::_2);
#ifdef IGL_SELFINTERSECTMESH_DEBUG
#ifdef IGL_SELFINTERSECTMESH_TIMING
log_time("box_and_bind");
#endif
// Run the self intersection algorithm with all defaults
CGAL::box_self_intersection_d(boxes.begin(), boxes.end(),cb);
#ifdef IGL_SELFINTERSECTMESH_DEBUG
// Run the self intersection algorithm with given cutoff size
CGAL::box_self_intersection_d(boxes.begin(), boxes.end(),cb,std::ptrdiff_t(params.cutoff));
#ifdef IGL_SELFINTERSECTMESH_TIMING
log_time("box_intersection_d");
#endif
try{
@@ -368,7 +394,7 @@ inline igl::copyleft::cgal::SelfIntersectMesh<
}
// Otherwise just fall through
}
#ifdef IGL_SELFINTERSECTMESH_DEBUG
#ifdef IGL_SELFINTERSECTMESH_TIMING
log_time("resolve_intersection");
#endif
@@ -383,13 +409,13 @@ inline igl::copyleft::cgal::SelfIntersectMesh<
)
{
IF(i,0) = (*ifit);
ifit++;
ifit++;
IF(i,1) = (*ifit);
ifit++;
i++;
}
}
#ifdef IGL_SELFINTERSECTMESH_DEBUG
#ifdef IGL_SELFINTERSECTMESH_TIMING
log_time("store_intersecting_face_pairs");
#endif
@@ -399,9 +425,10 @@ inline igl::copyleft::cgal::SelfIntersectMesh<
}
remesh_intersections(
V,F,T,offending,params.stitch_all,VV,FF,J,IM);
V,F,T,offending,
params.stitch_all,params.slow_and_more_precise_rounding,VV,FF,J,IM);
#ifdef IGL_SELFINTERSECTMESH_DEBUG
#ifdef IGL_SELFINTERSECTMESH_TIMING
log_time("remesh_intersection");
#endif
}
@@ -486,8 +513,8 @@ inline bool igl::copyleft::cgal::SelfIntersectMesh<
DerivedIF,
DerivedJ,
DerivedIM>::intersect(
const Triangle_3 & A,
const Triangle_3 & B,
const Triangle_3 & A,
const Triangle_3 & B,
const Index fa,
const Index fb)
{
@@ -501,6 +528,8 @@ inline bool igl::copyleft::cgal::SelfIntersectMesh<
{
// Construct intersection
CGAL::Object result = CGAL::intersection(A,B);
// Could avoid this mutex if `offending` was per-thread and passed as input
// reference.
std::lock_guard<std::mutex> guard(m_offending_lock);
offending[fa].push_back({fb, result});
offending[fb].push_back({fa, result});
@@ -600,8 +629,8 @@ inline bool igl::copyleft::cgal::SelfIntersectMesh<
return true;
}else
{
cerr<<REDRUM("Segment ∩ triangle neither point nor segment?")<<endl;
assert(false);
// Should never happen.
assert(false && "Segment ∩ triangle neither point nor segment?");
}
}
@@ -710,13 +739,13 @@ inline bool igl::copyleft::cgal::SelfIntersectMesh<
if(CGAL::object_cast<Segment_3 >(&result))
{
// not coplanar
assert(false &&
assert(false &&
"Co-planar non-degenerate triangles should intersect over triangle");
return false;
} else if(CGAL::object_cast<Point_3 >(&result))
{
// this "shouldn't" happen but does for inexact
assert(false &&
assert(false &&
"Co-planar non-degenerate triangles should intersect over triangle");
return false;
} else
@@ -740,7 +769,7 @@ inline bool igl::copyleft::cgal::SelfIntersectMesh<
// Expression : is_finite(d)
// File : /opt/local/include/CGAL/GMP/Gmpq_type.h
// Line : 132
// Explanation:
// Explanation:
// But only if NDEBUG is not defined, otherwise there's an uncaught
// "Floating point exception: 8" SIGFPE
return false;
@@ -767,7 +796,7 @@ inline void igl::copyleft::cgal::SelfIntersectMesh<
DerivedIF,
DerivedJ,
DerivedIM>::box_intersect(
const Box& a,
const Box& a,
const Box& b)
{
candidate_triangle_pairs.push_back({a.handle(), b.handle()});
@@ -792,30 +821,25 @@ inline void igl::copyleft::cgal::SelfIntersectMesh<
DerivedJ,
DerivedIM>::process_intersecting_boxes()
{
std::vector<std::mutex> triangle_locks(T.size());
std::vector<std::mutex> vertex_locks(V.rows());
std::mutex index_lock;
std::mutex exception_mutex;
bool exception_fired = false;
int exception = -1;
auto process_chunk =
[&](
const size_t first,
const size_t last) -> void
// Eventually switching to igl::parallel_for would be good, but currently
// igl::parallel_for does not provide a way to catch exceptions fired on a
// spawned thread _outside_ of its loop-chunk which is the mechanism used here
// to bail out early when `first_only=true` to avoid
// O(#candidate_triangle_pairs) behavior.
auto process_chunk = [&]( const size_t first, const size_t last) -> void
{
try
{
assert(last >= first);
for (size_t i=first; i<last; i++)
for (size_t i=first; i<last; i++)
{
if(exception_fired) return;
Index fa=T.size(), fb=T.size();
{
// Before knowing which triangles are involved, we need to lock
// everything to prevent race condition in updating reference
// counters.
std::lock_guard<std::mutex> guard(index_lock);
const auto& tri_pair = candidate_triangle_pairs[i];
fa = tri_pair.first - T.begin();
fb = tri_pair.second - T.begin();
@@ -823,22 +847,6 @@ inline void igl::copyleft::cgal::SelfIntersectMesh<
assert(fa < T.size());
assert(fb < T.size());
// Lock triangles
std::lock_guard<std::mutex> guard_A(triangle_locks[fa]);
std::lock_guard<std::mutex> guard_B(triangle_locks[fb]);
// Lock vertices
std::list<std::lock_guard<std::mutex> > guard_vertices;
{
std::vector<typename DerivedF::Scalar> unique_vertices;
std::vector<size_t> tmp1, tmp2;
igl::unique({F(fa,0), F(fa,1), F(fa,2), F(fb,0), F(fb,1), F(fb,2)},
unique_vertices, tmp1, tmp2);
std::for_each(unique_vertices.begin(), unique_vertices.end(),
[&](const typename DerivedF::Scalar& vi) {
guard_vertices.emplace_back(vertex_locks[vi]);
});
}
if(exception_fired) return;
const Triangle_3& A = T[fa];
@@ -867,7 +875,7 @@ inline void igl::copyleft::cgal::SelfIntersectMesh<
}
}
}
const Index total_shared_vertices =
const Index total_shared_vertices =
comb_shared_vertices + geo_shared_vertices;
if(exception_fired) return;
@@ -915,25 +923,18 @@ inline void igl::copyleft::cgal::SelfIntersectMesh<
exception = e;
}
};
size_t num_threads=0;
const size_t hardware_limit = std::thread::hardware_concurrency();
if (const char* igl_num_threads = std::getenv("LIBIGL_NUM_THREADS")) {
num_threads = atoi(igl_num_threads);
}
if (num_threads == 0 || num_threads > hardware_limit) {
num_threads = hardware_limit;
}
const size_t num_threads = default_num_threads();
assert(num_threads > 0);
const size_t num_pairs = candidate_triangle_pairs.size();
const size_t chunk_size = num_pairs / num_threads;
std::vector<std::thread> threads;
for (size_t i=0; i<num_threads-1; i++)
for (size_t i=0; i<num_threads-1; i++)
{
threads.emplace_back(process_chunk, i*chunk_size, (i+1)*chunk_size);
}
// Do some work in the master thread.
process_chunk((num_threads-1)*chunk_size, num_pairs);
for (auto& t : threads)
for (auto& t : threads)
{
if (t.joinable()) t.join();
}
@@ -941,4 +942,4 @@ inline void igl::copyleft::cgal::SelfIntersectMesh<
//process_chunk(0, candidate_triangle_pairs.size());
}
#endif
#endif