[Bf-blender-cvs] [bd155f43096] soc-2020-soft-body: tetgen flag default off

mattoverby noreply at git.blender.org
Sat Aug 15 02:20:29 CEST 2020


Commit: bd155f430964952be0b3c67e0f97c4c5e4e48f9f
Author: mattoverby
Date:   Fri Aug 14 19:20:24 2020 -0500
Branches: soc-2020-soft-body
https://developer.blender.org/rBbd155f430964952be0b3c67e0f97c4c5e4e48f9f

tetgen flag default off

===================================================================

M	CMakeLists.txt
M	extern/discregrid/discregrid/include/Discregrid/geometry/mesh_distance.hpp
M	extern/discregrid/discregrid/include/Discregrid/mesh/triangle_mesh.hpp
M	extern/discregrid/discregrid/src/mesh/triangle_mesh.cpp
M	extern/softbody/src/admmpd_collision.cpp
M	extern/softbody/src/admmpd_collision.h
M	intern/softbody/admmpd_api.cpp
M	source/blender/blenkernel/BKE_softbody.h
M	source/blender/editors/object/object_remesh.c
M	source/blender/makesdna/DNA_object_force_types.h

===================================================================

diff --git a/CMakeLists.txt b/CMakeLists.txt
index d59a57ba70b..2ce08e72cd9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -222,7 +222,7 @@ mark_as_advanced(WITH_HEADLESS)
 
 option(WITH_QUADRIFLOW    "Build with quadriflow remesher support" ON)
 
-option(WITH_TETGEN    "Build with tetgen remesher support" ON)
+option(WITH_TETGEN    "Build with tetgen remesher support" OFF)
 
 option(WITH_AUDASPACE    "Build with blenders audio library (only disable if you know what you're doing!)" ON)
 option(WITH_SYSTEM_AUDASPACE "Build with external audaspace library installed on the system (only enable if you know what you're doing!)" OFF)
diff --git a/extern/discregrid/discregrid/include/Discregrid/geometry/mesh_distance.hpp b/extern/discregrid/discregrid/include/Discregrid/geometry/mesh_distance.hpp
index 2272403f23e..910c74cec13 100755
--- a/extern/discregrid/discregrid/include/Discregrid/geometry/mesh_distance.hpp
+++ b/extern/discregrid/discregrid/include/Discregrid/geometry/mesh_distance.hpp
@@ -79,7 +79,16 @@ public:
 	double unsignedDistance(Eigen::Vector3d const& x) const;
 	double unsignedDistanceCached(Eigen::Vector3d const& x) const;
 
-	void set_thread_map(std::vector<std::thread::id> *thread_map_) { thread_map = thread_map_; }
+	// So, the original discregrid uses OpenMP which has
+	// handy functions like omp_get_thread_num(). Switching to non-OpenMP
+	// requires some overhead to get the current thread ID which is what
+	// you see here. So this pointer is passed to both the SDF
+	// generator and this SDF evaluator. The generator fills the thread map
+	// and the evaluator reads from it.
+	// Not ideal and kind of clunky, but a quick workaround for now.
+	void set_thread_map(std::vector<std::thread::id> *thread_map_) {
+		thread_map = thread_map_;
+	}
 
 private:
 
diff --git a/extern/discregrid/discregrid/include/Discregrid/mesh/triangle_mesh.hpp b/extern/discregrid/discregrid/include/Discregrid/mesh/triangle_mesh.hpp
index 66d38b52360..83accb776a8 100755
--- a/extern/discregrid/discregrid/include/Discregrid/mesh/triangle_mesh.hpp
+++ b/extern/discregrid/discregrid/include/Discregrid/mesh/triangle_mesh.hpp
@@ -27,6 +27,8 @@ public:
 
 	TriangleMesh(std::string const& filename);
 
+	bool is_closed() const { return m_is_closed; }
+
 	void exportOBJ(std::string const& filename) const;
 
 	// Halfedge modifiers.
@@ -103,6 +105,7 @@ private:
 	std::vector<std::array<Halfedge, 3>> m_e2e;
 	std::vector<Halfedge> m_v2e;
 	std::vector<Halfedge> m_b2e;
+	bool m_is_closed;
 };
 }
 
diff --git a/extern/discregrid/discregrid/src/mesh/triangle_mesh.cpp b/extern/discregrid/discregrid/src/mesh/triangle_mesh.cpp
index 8a59453be12..186e5ccebd9 100755
--- a/extern/discregrid/discregrid/src/mesh/triangle_mesh.cpp
+++ b/extern/discregrid/discregrid/src/mesh/triangle_mesh.cpp
@@ -72,6 +72,7 @@ TriangleMesh::TriangleMesh(
 	std::vector<std::array<unsigned int, 3>> const& faces)
 	: m_faces(faces), m_e2e(3 * faces.size()), m_vertices(vertices)
 	, m_v2e(vertices.size())
+	, m_is_closed(false)
 {
 	construct();
 }
@@ -79,7 +80,7 @@ TriangleMesh::TriangleMesh(
 TriangleMesh::TriangleMesh(double const* vertices,
 	unsigned int const* faces,
 	std::size_t nv, std::size_t nf)
-	: m_faces(nf), m_vertices(nv), m_e2e(3 * nf), m_v2e(nv)
+	: m_faces(nf), m_vertices(nv), m_e2e(3 * nf), m_v2e(nv), m_is_closed(false)
 {
 	std::copy(vertices, vertices + 3 * nv, m_vertices[0].data());
 	std::copy(faces, faces + 3 * nf, m_faces[0].data());
@@ -90,6 +91,8 @@ TriangleMesh::TriangleMesh(double const* vertices,
 
 TriangleMesh::TriangleMesh(std::string const& path)
 {
+	m_is_closed = false;
+
 	std::ifstream in(path, std::ios::in);
 	if (!in) 
 	{ 
@@ -200,7 +203,11 @@ TriangleMesh::construct()
 
 	if (!m_b2e.empty())
 	{
-		std::cout << std::endl << "WARNING: Mesh not closed!" << std::endl;
+		m_is_closed = false;
+	}
+	else
+	{
+		m_is_closed = true;
 	}
 }
 
diff --git a/extern/softbody/src/admmpd_collision.cpp b/extern/softbody/src/admmpd_collision.cpp
index cf5a0fa68d6..f6dc94dcbdd 100644
--- a/extern/softbody/src/admmpd_collision.cpp
+++ b/extern/softbody/src/admmpd_collision.cpp
@@ -26,18 +26,27 @@ VFCollisionPair::VFCollisionPair() :
 	q_bary(0,0,0)
 	{}
 
-void Collision::set_obstacles(
+void Collision::ObstacleData::clear() {
+	V = MatrixXd();
+	F = MatrixXi();
+	sdf = Discregrid::CubicLagrangeDiscreteGrid();
+}
+
+
+bool Collision::set_obstacles(
 	const float *v0,
 	const float *v1,
 	int nv,
 	const unsigned int *faces,
-	int nf)
+	int nf,
+	std::string *err)
 {
 	(void)(v0);
 	if (nv==0 || nf==0)
 	{
-		// Why do this? Are you just being mean?
-		return;
+		if (err) { *err = "Collision obstacle has no verts or faces"; }
+		obsdata.clear();
+		return false;
 	}
 
 	std::vector<double> v1_dbl(nv*3);
@@ -63,9 +72,16 @@ void Collision::set_obstacles(
 			obsdata.F(i,j) = faces[i*3+j];
 	}
 
+	// Is the mesh closed?
+	Discregrid::TriangleMesh tm(v1_dbl.data(), faces, nv, nf);
+	if (!tm.is_closed()) {
+		if (err) { *err = "Collision obstacle not a closed mesh"; }
+		obsdata.clear();
+		return false;
+	}
+
 	// Generate signed distance field
 	{
-		Discregrid::TriangleMesh tm(v1_dbl.data(), faces, nv, nf);
 		Discregrid::MeshDistance md(tm);
 		domain.max() += 1e-3 * domain.diagonal().norm() * Eigen::Vector3d::Ones();
 		domain.min() -= 1e-3 * domain.diagonal().norm() * Eigen::Vector3d::Ones();
@@ -81,6 +97,14 @@ void Collision::set_obstacles(
 		obsdata.sdf.addFunction(func, &thread_map, false);
 	}
 
+	if (obsdata.sdf.nCells()==0) {
+		if (err) { *err = "SDF gen failed for collision obstacle"; }
+		obsdata.clear();
+		return false;
+	}
+
+	return true;
+
 } // end add obstacle
 
 std::pair<bool,VFCollisionPair>
diff --git a/extern/softbody/src/admmpd_collision.h b/extern/softbody/src/admmpd_collision.h
index 819d7620a7c..25d9feb295b 100644
--- a/extern/softbody/src/admmpd_collision.h
+++ b/extern/softbody/src/admmpd_collision.h
@@ -24,6 +24,7 @@ class Collision {
 public:
     struct ObstacleData {
         bool has_obs() const { return F.rows()>0; }
+        void clear();
         Eigen::MatrixXd V;
         Eigen::MatrixXi F;
         SDFType sdf;
@@ -56,15 +57,15 @@ public:
         std::vector<std::set<int> > &g) = 0;
 
     // Set the soup of obstacles for this time step.
-    // I don't really like having to switch up interface style, but we'll
-    // do so here to avoid copies that would happen in admmpd_api.
-    // We should actually just pash in a mesh class?
-    virtual void set_obstacles(
+    // Returns true on success (SDF generation).
+    // If err not nullptr, it's set with what caused the error.
+    virtual bool set_obstacles(
         const float *v0,
         const float *v1,
         int nv,
         const unsigned int *faces,
-        int nf);
+        int nf,
+        std::string *err=nullptr);
 
     // Linearizes active collision pairs about x
     // for the constraint Cx=d
diff --git a/intern/softbody/admmpd_api.cpp b/intern/softbody/admmpd_api.cpp
index f7bc5eefcd5..2139355400f 100644
--- a/intern/softbody/admmpd_api.cpp
+++ b/intern/softbody/admmpd_api.cpp
@@ -26,12 +26,13 @@
 #include "admmpd_solver.h"
 #include "admmpd_mesh.h"
 #include "admmpd_collision.h"
-
-#include "tetgen_api.h"
+#ifdef WITH_TETGEN
+  #include "tetgen_api.h"
+  #include "BKE_mesh_remesh_voxel.h" // TetGen
+#endif
 #include "DNA_mesh_types.h" // Mesh
 #include "DNA_meshdata_types.h" // MVert
 #include "DNA_object_force_types.h" // Enums
-#include "BKE_mesh_remesh_voxel.h" // TetGen
 #include "BKE_mesh.h" // BKE_mesh_free
 #include "BKE_softbody.h" // BodyPoint
 #include "BKE_deform.h" // BKE_defvert_find_index
@@ -41,8 +42,6 @@
 #include <memory>
 #include <algorithm>
 
-#define ADMMPD_API_DEBUG
-
 // Collision obstacles are cached until
 // solve(...) is called. If we are substepping,
 // the obstacle is interpolated from start to end.
@@ -176,6 +175,7 @@ void admmpd_dealloc(ADMMPDInterfaceData *iface)
 
 static inline int admmpd_init_with_tetgen(ADMMPDInterfaceData *iface, Object *ob, float (*vertexCos)[3])
 {
+#ifdef WITH_TETGEN
   std::vector<float> v;
   std::vector<unsigned int> f;
   vecs_from_object(ob,vertexCos,v,f);
@@ -196,7 +196,6 @@ static inline int admmpd_init_with_tetgen(ADMMPDInterfaceData *iface, Object *ob
   // Double check assumption, the first
   // mesh_totverts vertices remain the same
   // for input and output mesh.
-  #ifdef ADMMPD_API_DEBUG
     for (int i=0; i<tg.in_totverts; ++i)
     {
       for (int j=0; j<3; ++j)
@@ -209,7 +208,6 @@ static inline int admmpd_init_with_tetgen(ADMMPDInterfaceData *iface, Object *ob
         }
       }
     }
-  #endif
 
   iface->idata->mesh = std::make_shared<admmpd::TetMesh>();
   success = iface->idata->mesh->create(
@@ -231,6 +229,12 @@ static inline int admmpd_init_with_tetgen(ADMMPDInterfaceData *iface, Object *ob
   MEM_freeN(tg.out_verts);
 
   return 1;
+#else
+  (void)(ob);
+  (void)(vertexCos);
+  strcpy_error(iface, "TetGen not available");
+  return 0;
+#endif
 }
 
 static inline int admmpd_init_with_lattice(ADMMPDInterfaceData *iface, Object *ob, float (*vertexCos)[3])
@@ -690,13 +694,19 @@ int admmpd_solve(ADMMPDInterfaceData *iface, Object *ob, float (*vertexCos)[3])
     iface->idata->options->substeps>1 &&
     (iface->idata->obs.x0-iface->idata->obs.x1).lpNorm<Eigen::Infinity>()>1e-6;
 
+  bool had_set_obstacle_error = false;
   if (has_obstacles && iface->idata->obs.needs_sdf_recompute && !lerp_obstacles) {
-    iface->idata->collision->set_obstacles(
-      iface->idata->obs.x0.data(),
-      iface->idata->obs.x1.data(),
-      iface->idata->obs.x0.size()/3,
-      iface->idata->obs.F.data(),
-      iface->idata->obs.F.size()/3);
+    std::string set_obs_error = "";
+    if (!iface->idata->collision->set_obstacles(
+        iface->idata->obs.x0.data(),
+        iface->idata->obs.x1.data(),
+        iface->idata->obs.x0.size()/3,
+        iface->idata->obs.F.data(),
+        iface->idata->obs.F.size()/3,
+        &set_obs_error)) {
+      strcpy_error(iface, set_obs_error.c_str());
+      had_set_obstacle_error = true;
+    }
   }
 
   try
@@ -704,16 +714,23 @@ int admmpd_solve(ADMMPDInterfaceData *iface, Object *ob, float (*vertexCos)[3])
     Eigen::VectorXf obs_x1; // used if su

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list