[Bf-blender-cvs] [db5a2452d45] soc-2020-soft-body: revising mesh types

over0219 noreply at git.blender.org
Wed Jul 22 04:23:48 CEST 2020


Commit: db5a2452d45f6cd870dfb55e0c4e13ecea0e0b00
Author: over0219
Date:   Tue Jul 21 15:54:48 2020 -0500
Branches: soc-2020-soft-body
https://developer.blender.org/rBdb5a2452d45f6cd870dfb55e0c4e13ecea0e0b00

revising mesh types

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

M	extern/softbody/CMakeLists.txt
M	extern/softbody/src/admmpd_bvh.cpp
M	extern/softbody/src/admmpd_collision.cpp
M	extern/softbody/src/admmpd_collision.h
M	extern/softbody/src/admmpd_embeddedmesh.cpp
M	extern/softbody/src/admmpd_embeddedmesh.h
A	extern/softbody/src/admmpd_mesh.cpp
A	extern/softbody/src/admmpd_mesh.h
D	extern/softbody/src/admmpd_pin.cpp
D	extern/softbody/src/admmpd_pin.h
M	extern/softbody/src/admmpd_solver.cpp
M	extern/softbody/src/admmpd_solver.h
D	extern/softbody/src/admmpd_tetmesh.cpp
D	extern/softbody/src/admmpd_tetmesh.h
M	extern/softbody/src/admmpd_types.h
M	intern/softbody/admmpd_api.cpp
M	intern/tetgen/tetgen_api.cpp
M	source/blender/blenkernel/intern/softbody.c

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

diff --git a/extern/softbody/CMakeLists.txt b/extern/softbody/CMakeLists.txt
index 78e4525322b..c300bedeb39 100644
--- a/extern/softbody/CMakeLists.txt
+++ b/extern/softbody/CMakeLists.txt
@@ -47,22 +47,22 @@ set(SRC
 	src/admmpd_bvh_traverse.cpp
 	src/admmpd_collision.h
 	src/admmpd_collision.cpp
-	src/admmpd_embeddedmesh.h
-	src/admmpd_embeddedmesh.cpp
+#	src/admmpd_embeddedmesh.h
+#	src/admmpd_embeddedmesh.cpp
 	src/admmpd_energy.h
 	src/admmpd_energy.cpp
 	src/admmpd_geom.h
 	src/admmpd_geom.cpp
 	src/admmpd_linsolve.h
 	src/admmpd_linsolve.cpp
-	src/admmpd_pin.h
-	src/admmpd_pin.cpp
+#	src/admmpd_pin.h
+#	src/admmpd_pin.cpp
 	src/admmpd_sdf.h
 	src/admmpd_sdf.cpp
 	src/admmpd_solver.h
 	src/admmpd_solver.cpp
-	src/admmpd_tetmesh.h
-	src/admmpd_tetmesh.cpp
+	src/admmpd_mesh.h
+	src/admmpd_mesh.cpp
 	src/admmpd_types.h
 	${SDFGEN_SRC}
 )
diff --git a/extern/softbody/src/admmpd_bvh.cpp b/extern/softbody/src/admmpd_bvh.cpp
index afa16874062..190d086aa3c 100644
--- a/extern/softbody/src/admmpd_bvh.cpp
+++ b/extern/softbody/src/admmpd_bvh.cpp
@@ -285,8 +285,8 @@ typename Octree<T,DIM>::Node* Octree<T,DIM>::create_children(
                 node->prims.emplace_back(p_idx);
         }
         // Create children only if prims intersect
-        int np = node->prims.size();
-        for (int i=0; i<nchild && np>0; ++i)
+        bool has_prims = node->prims.size()>0;
+        for (int i=0; i<nchild && has_prims; ++i)
         {
 
             T step = node->halfwidth * 0.5;
diff --git a/extern/softbody/src/admmpd_collision.cpp b/extern/softbody/src/admmpd_collision.cpp
index 648e5f59be2..0c07ef441d0 100644
--- a/extern/softbody/src/admmpd_collision.cpp
+++ b/extern/softbody/src/admmpd_collision.cpp
@@ -90,6 +90,8 @@ Collision::detect_against_obs(
 	return ret;
 }
 
+#if 0
+
 int EmbeddedMeshCollision::detect(
 	const Eigen::MatrixXd *x0,
 	const Eigen::MatrixXd *x1)
@@ -544,6 +546,8 @@ void EmbeddedMeshCollision::linearize(
 
 } // end jacobian
 
+#endif
+
 } // namespace admmpd
 
 /*
diff --git a/extern/softbody/src/admmpd_collision.h b/extern/softbody/src/admmpd_collision.h
index 4d917ccfc72..a5189e7c22b 100644
--- a/extern/softbody/src/admmpd_collision.h
+++ b/extern/softbody/src/admmpd_collision.h
@@ -110,6 +110,8 @@ public:
         const Eigen::MatrixXd *x) const = 0;
 };
 
+#if 0
+
 // Collision detection against multiple meshes
 class EmbeddedMeshCollision : public Collision {
 public:
@@ -162,6 +164,8 @@ protected:
         const Eigen::MatrixXd *x) const;
 };
 
+#endif
+
 } // namespace admmpd
 
 #endif // ADMMPD_COLLISION_H_
diff --git a/extern/softbody/src/admmpd_embeddedmesh.cpp b/extern/softbody/src/admmpd_embeddedmesh.cpp
index e939114faeb..86f6d00086b 100644
--- a/extern/softbody/src/admmpd_embeddedmesh.cpp
+++ b/extern/softbody/src/admmpd_embeddedmesh.cpp
@@ -1,5 +1,6 @@
 // Copyright Matt Overby 2020.
 // Distributed under the MIT License.
+#if 0
 
 #include "admmpd_embeddedmesh.h"
 #include "admmpd_geom.h"
@@ -379,4 +380,6 @@ Eigen::Vector3d EmbeddedMesh::get_mapped_vertex(
 		x_data->row(tet[3]) * b[3]);
 }
 
-} // namespace admmpd
\ No newline at end of file
+} // namespace admmpd
+
+#endif
\ No newline at end of file
diff --git a/extern/softbody/src/admmpd_embeddedmesh.h b/extern/softbody/src/admmpd_embeddedmesh.h
index 0ee8cacf43e..6a4fd80bf28 100644
--- a/extern/softbody/src/admmpd_embeddedmesh.h
+++ b/extern/softbody/src/admmpd_embeddedmesh.h
@@ -1,5 +1,6 @@
 // Copyright Matt Overby 2020.
 // Distributed under the MIT License.
+#if 0
 
 #ifndef ADMMPD_EMBEDDEDMESH_H_
 #define ADMMPD_EMBEDDEDMESH_H_
@@ -51,3 +52,4 @@ protected:
 } // namespace admmpd
 
 #endif // ADMMPD_EMBEDDEDMESH_H_
+#endif
\ No newline at end of file
diff --git a/extern/softbody/src/admmpd_mesh.cpp b/extern/softbody/src/admmpd_mesh.cpp
new file mode 100644
index 00000000000..c4225fa6dc1
--- /dev/null
+++ b/extern/softbody/src/admmpd_mesh.cpp
@@ -0,0 +1,143 @@
+// Copyright Matt Overby 2020.
+// Distributed under the MIT License.
+
+#include "admmpd_mesh.h"
+#include "admmpd_geom.h"
+#include <unordered_map>
+#include <set>
+#include <iostream>
+#include "BLI_assert.h"
+
+namespace admmpd {
+using namespace Eigen;
+
+bool TetMesh::create(
+	const float *verts, // size nv*3
+	int nv,
+	const unsigned int *faces, // size nf*3 (surface faces)
+	int nf,
+	const unsigned int *tets, // size nt*4
+	int nt) // must be > 0
+{
+	if (nv<=0 || verts == nullptr)
+		return false;
+	if (nf<=0 || faces == nullptr)
+		return false;
+	if (nt<=0 || tets == nullptr)
+		return false;
+
+	V0.resize(nv,3);
+	for (int i=0; i<nv; ++i)
+	{
+		V0(i,0) = verts[i*3+0];
+		V0(i,1) = verts[i*3+1];
+		V0(i,2) = verts[i*3+2];
+	}
+
+	F.resize(nf,3);
+	for (int i=0; i<nf; ++i)
+	{
+		F(i,0) = faces[i*3+0];
+		F(i,1) = faces[i*3+1];
+		F(i,2) = faces[i*3+2];
+	}
+
+	T.resize(nt,4);
+	for (int i=0; i<nt; ++i)
+	{
+		T(i,0) = tets[i*4+0];
+		T(i,1) = tets[i*4+1];
+		T(i,2) = tets[i*4+2];
+		T(i,3) = tets[i*4+3];
+	}
+
+	return true;
+
+} // end TetMesh create
+
+void TetMesh::compute_masses(
+	Eigen::Ref<const Eigen::MatrixXd> x,
+	double density_kgm3,
+	Eigen::VectorXd &m) const
+{
+	density_kgm3 = std::abs(density_kgm3);
+
+	// Source: https://github.com/mattoverby/mclscene/blob/master/include/MCL/TetMesh.hpp
+	// Computes volume-weighted masses for each vertex
+	// density_kgm3 is the unit-volume density
+	int nx = x.rows();
+	m.resize(nx);
+	m.setZero();
+	int n_tets = T.rows();
+	for (int t=0; t<n_tets; ++t)
+	{
+		RowVector4i tet = T.row(t);
+		for (int i=0; i<4; ++i)
+		{
+			if (tet[i] < 0 || tet[i] >= nx)
+				throw std::runtime_error("TetMesh::compute_masses Error: Bad vertex index\n");
+		}
+		RowVector3d tet_v0 = x.row(tet[0]);
+		Matrix3d edges;
+		edges.col(0) = x.row(tet[1]) - tet_v0;
+		edges.col(1) = x.row(tet[2]) - tet_v0;
+		edges.col(2) = x.row(tet[3]) - tet_v0;
+		double vol = edges.determinant()/6.0;
+		if (vol <= 0)
+			throw std::runtime_error("TetMesh::compute_masses Error: Inverted or flattened tet\n");
+
+		double tet_mass = density_kgm3 * vol;
+		m[tet[0]] += tet_mass / 4.0;
+		m[tet[1]] += tet_mass / 4.0;
+		m[tet[2]] += tet_mass / 4.0;
+		m[tet[3]] += tet_mass / 4.0;
+	}
+
+	// Verify masses
+	for (int i=0; i<nx; ++i)
+	{
+		if (m[i] <= 0.0)
+		{
+			printf("**TetMesh::compute_masses Error: unreferenced vertex\n");
+			m[i]=1;
+		}
+	}
+
+} // end compute masses
+
+void TetMesh::set_pin(
+	int idx,
+	const Eigen::Vector3d &p,
+	const Eigen::Vector3d &k)
+{
+	if (k.maxCoeff() <= 0)
+		return;
+
+	pin_k[idx] = k;
+	pin_pos[idx] = p;
+}
+
+void TetMesh::linearize_pins(
+	std::vector<Eigen::Triplet<double> > &trips,
+	std::vector<double> &q) const
+{
+	int np = pin_k.size();
+	trips.reserve((int)trips.size() + np*3);
+	q.reserve((int)q.size() + np*3);
+
+	std::unordered_map<int,Eigen::Vector3d>::const_iterator it_k = pin_k.begin();
+	for (; it_k != pin_k.end(); ++it_k)
+	{
+		int idx = it_k->first;
+		const Vector3d &qi = pin_pos.at(idx);
+		const Vector3d &ki = it_k->second;
+		for (int i=0; i<3; ++i)
+		{
+			int p_idx = q.size();
+			q.emplace_back(qi[i]*ki[i]);
+			trips.emplace_back(p_idx, idx*3+i, ki[i]);
+		}
+	}
+}
+
+} // namespace admmpd
diff --git a/extern/softbody/src/admmpd_mesh.h b/extern/softbody/src/admmpd_mesh.h
new file mode 100644
index 00000000000..92e84568924
--- /dev/null
+++ b/extern/softbody/src/admmpd_mesh.h
@@ -0,0 +1,204 @@
+// Copyright Matt Overby 2020.
+// Distributed under the MIT License.
+
+#ifndef ADMMPD_TETMESH_H_
+#define ADMMPD_TETMESH_H_
+
+#include "admmpd_types.h"
+#include <unordered_map>
+
+namespace admmpd {
+
+class Mesh {
+public:
+
+    virtual bool create(
+        const float *verts, // size nv*3
+        int nv,
+        const unsigned int *faces, // size nf*3
+        int nf,
+        const unsigned int *tets, // null or size nt*4
+        int nt) = 0; // If embedded mesh, set to zero
+
+    // ====================
+    //  Accessors
+    // ====================
+    virtual Eigen::Ref<const Eigen::MatrixXi> prims() const = 0;
+    virtual Eigen::Ref<const Eigen::MatrixXd> rest_prim_verts() const = 0;
+    virtual Eigen::Ref<const Eigen::MatrixXi> facets() const = 0;
+    virtual Eigen::Ref<const Eigen::MatrixXd> rest_facet_verts() const = 0;
+
+    // Maps primitive vertex to facet vertex. For standard tet meshes
+    // it's just one-to-one, but embedded meshes use bary weighting.
+    virtual Eigen::Vector3d get_mapped_facet_vertex(
+        Eigen::Ref<const Eigen::MatrixXd> prim_verts,
+        int facet_vertex_idx) = 0;
+
+    // ====================
+    //  Utility
+    // ====================
+
+    virtual void compute_masses(
+        Eigen::Ref<const Eigen::MatrixXd> x,
+        double density_kgm3,
+        Eigen::VectorXd &m) const = 0;
+
+    // ====================
+    //  Pins
+    // ====================
+
+    virtual int num_pins() const = 0;
+
+    // Pins a vertex at a location with stiffness k
+    virtual void set_pin(
+        int idx,
+        const Eigen::Vector3d &p,
+        const Eigen::Vector3d &k) = 0;
+
+    virtual void clear_pins() = 0;
+
+    // Px=q with stiffnesses baked in
+    virtual void linearize_pins(
+        std::vector<Eigen::Triplet<double> > &trips,
+        std::vector<double> &q) const = 0;
+
+}; // class Mesh
+
+
+class EmbeddedMesh : public Mesh {
+protected:
+    Eigen::MatrixXd lat_V0, emb_V0;
+    Eigen::MatrixXi lat_T, emb_F;
+
+public:
+
+    bool create(
+        const float *verts, // size nv*3
+        int nv,
+        const unsigned int *faces, // size nf*3
+        int nf,
+        const unsigned int *tets, // ignored
+        int nt){} // ignored
+
+    Eigen::Ref<const Eigen::MatrixXi> prims() const { return lat_T; }
+    Eigen::Ref<const Eigen::MatrixXd> rest_prim_verts() const { return lat_V0; }
+
+    // Facets are the embedded faces of the tet mesh
+    Eigen::Ref<const Eigen::MatrixXi> facets() const { return emb_F; }
+    Eigen::Ref<const Eigen::MatrixXd> rest_facet_verts() const { return emb_V0; }
+
+    Eigen::Vector3d get_mapped_facet_vertex(
+        Eigen::Ref<const Eigen::MatrixXd> prim_verts,
+        int facet_vertex_idx){}
+
+    void compute_masses(
+        Eigen::Ref<const Eigen::MatrixXd> x,
+        double density_kgm3,
+        Eige

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list