mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-05-20 03:43:52 +00:00
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 *e3c277b9eeFor 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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user