[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