[Bf-blender-cvs] [e0a76a48eb8] soc-2020-soft-body: improved lattice gen

over0219 noreply at git.blender.org
Wed Jul 1 05:42:18 CEST 2020


Commit: e0a76a48eb80f85026c503206ddc3a82d7af0ddb
Author: over0219
Date:   Tue Jun 30 22:42:14 2020 -0500
Branches: soc-2020-soft-body
https://developer.blender.org/rBe0a76a48eb80f85026c503206ddc3a82d7af0ddb

improved lattice gen

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

M	extern/softbody/CMakeLists.txt
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_linsolve.cpp
M	extern/softbody/src/admmpd_solver.cpp
M	extern/softbody/src/admmpd_types.h

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

diff --git a/extern/softbody/CMakeLists.txt b/extern/softbody/CMakeLists.txt
index b8f036feebb..cadd9ef51ee 100644
--- a/extern/softbody/CMakeLists.txt
+++ b/extern/softbody/CMakeLists.txt
@@ -19,35 +19,35 @@
 # ***** END GPL LICENSE BLOCK *****
 
 set(INC
-  src
+	src
 )
 
 set(INC_SYS
-  ${EIGEN3_INCLUDE_DIRS}
-  ../../source/blender/blenlib
-  ../../source/blender/makesdna # BLI_math_geom requires DNA
+	${EIGEN3_INCLUDE_DIRS}
+	../../source/blender/blenlib
+	../../source/blender/makesdna # BLI_math_geom requires DNA
 )
 
 set(SRC
-  src/admmpd_bvh.h
-  src/admmpd_bvh.cpp
-  src/admmpd_bvh_traverse.h
-  src/admmpd_bvh_traverse.cpp
-  src/admmpd_collision.h
-  src/admmpd_collision.cpp
-  src/admmpd_embeddedmesh.h
-  src/admmpd_embeddedmesh.cpp
-  src/admmpd_energy.h
-  src/admmpd_energy.cpp
-  src/admmpd_linsolve.h
-  src/admmpd_linsolve.cpp
-  src/admmpd_math.h
-  src/admmpd_math.cpp
-  src/admmpd_solver.h
-  src/admmpd_solver.cpp
-  src/admmpd_tetmesh.h
-  src/admmpd_tetmesh.cpp
-  src/admmpd_types.h
+	src/admmpd_bvh.h
+	src/admmpd_bvh.cpp
+	src/admmpd_bvh_traverse.h
+	src/admmpd_bvh_traverse.cpp
+	src/admmpd_collision.h
+	src/admmpd_collision.cpp
+	src/admmpd_embeddedmesh.h
+	src/admmpd_embeddedmesh.cpp
+	src/admmpd_energy.h
+	src/admmpd_energy.cpp
+	src/admmpd_linsolve.h
+	src/admmpd_linsolve.cpp
+	src/admmpd_math.h
+	src/admmpd_math.cpp
+	src/admmpd_solver.h
+	src/admmpd_solver.cpp
+	src/admmpd_tetmesh.h
+	src/admmpd_tetmesh.cpp
+	src/admmpd_types.h
 )
 
 set(LIB
diff --git a/extern/softbody/src/admmpd_collision.cpp b/extern/softbody/src/admmpd_collision.cpp
index b7e835a9185..289af9fc68b 100644
--- a/extern/softbody/src/admmpd_collision.cpp
+++ b/extern/softbody/src/admmpd_collision.cpp
@@ -78,18 +78,6 @@ void Collision::detect_discrete_vf(
 	double floor_z,
 	std::vector<VFCollisionPair> *pairs)
 {
-	// Special case, check if we are below the floor
-	if (pt[2] < floor_z)
-	{
-		pairs->emplace_back();
-		VFCollisionPair &pair = pairs->back();
-		pair.p_idx = pt_idx;
-		pair.p_is_obs = pt_is_obs;
-		pair.q_idx = -1;
-		pair.q_is_obs = 1;
-		pair.pt_on_q = Vector3d(pt[0],pt[1],floor_z);
-	}
-
 	// Any faces to detect against?
 	if (mesh_tris->rows()==0)
 		return;
@@ -191,6 +179,19 @@ static void parallel_detect(
 			bary[2] * td->x1->row(tet[2]) +
 			bary[3] * td->x1->row(tet[3]);
 
+
+		// Special case, check if we are below the floor
+		if (pt[2] < td->floor_z)
+		{
+			tl_pairs.emplace_back();
+			VFCollisionPair &pair = tl_pairs.back();
+			pair.p_idx = i;
+			pair.p_is_obs = false;
+			pair.q_idx = -1;
+			pair.q_is_obs = 1;
+			pair.pt_on_q = Vector3d(pt[0],pt[1],td->floor_z);
+		}
+
 		Collision::detect_discrete_vf(
 			pt, i, false,
 			&td->obsdata->tree,
@@ -200,6 +201,15 @@ static void parallel_detect(
 			td->floor_z,
 			&tl_pairs );
 
+	//	Collision::detect_discrete_vf(
+	//		pt, i, false,
+	//		&td->obsdata->tree,
+	//		&td->obsdata->V1,
+	//		&td->obsdata->F,
+	//		true,
+	//		td->floor_z,
+	//		&tl_pairs );
+
 	} // end detect with embedded meshes
 
 } // end parallel detect
diff --git a/extern/softbody/src/admmpd_collision.h b/extern/softbody/src/admmpd_collision.h
index 2ab7d343c05..95623510969 100644
--- a/extern/softbody/src/admmpd_collision.h
+++ b/extern/softbody/src/admmpd_collision.h
@@ -12,11 +12,9 @@ namespace admmpd {
 struct VFCollisionPair {
     int p_idx; // point
     int p_is_obs; // 0 or 1
-    int q_idx; // face
+    int q_idx; // face, or -1 if floor
     int q_is_obs; // 0 or 1
     Eigen::Vector3d pt_on_q; // point of collision on q
-//    int floor; // 0 or 1, special case
-//    Eigen::Vector3d barys;
     Eigen::Vector3d q_n; // face normal
     VFCollisionPair();
 };
diff --git a/extern/softbody/src/admmpd_embeddedmesh.cpp b/extern/softbody/src/admmpd_embeddedmesh.cpp
index 22ac59fef0c..0c2cdcac938 100644
--- a/extern/softbody/src/admmpd_embeddedmesh.cpp
+++ b/extern/softbody/src/admmpd_embeddedmesh.cpp
@@ -6,6 +6,7 @@
 #include "admmpd_bvh.h"
 #include "admmpd_bvh_traverse.h"
 #include <iostream>
+#include <fstream>
 #include <unordered_map>
 #include <set>
 #include "BLI_task.h" // threading
@@ -63,6 +64,153 @@ static void parallel_keep_tet(
 
 } // end parallel test if keep tet
 
+// Gen lattice with subdivision
+struct LatticeData {
+	const Eigen::MatrixXd *V;
+	std::vector<Vector3d> verts;
+	std::vector<Vector4i> tets;
+};
+
+static inline void merge_close_vertices(LatticeData *data, double eps=1e-12)
+{
+	int nv = data->verts.size();
+	std::vector<Vector3d> new_v(nv); // new verts
+	std::vector<int> idx(nv,0); // index mapping
+	std::vector<int> visited(nv,0);
+	int count = 0;
+	for (int i=0; i<nv; ++i)
+	{
+		if(!visited[i])
+		{
+			visited[i] = 1;
+			new_v[count] = data->verts[i];
+			idx[i] = count;
+			Vector3d vi = data->verts[i];
+			for (int j = i+1; j<nv; ++j)
+			{
+				if((data->verts[j]-vi).norm() < eps)
+				{
+					visited[j] = 1;
+					idx[j] = count;
+				}
+			}
+			count++;
+		}
+	}
+	new_v.resize(count);
+	data->verts = new_v;
+	int nt = data->tets.size();
+	for (int i=0; i<nt; ++i)
+	{
+		for (int j=0; j<4; ++j)
+		{
+			data->tets[i][j] = idx[data->tets[i][j]];
+		}
+	}
+}
+
+static inline void subdivide_cube(
+	LatticeData *data,
+	const std::vector<Vector3d> &cv,
+	const std::vector<int> &pts_in_box,
+	int level)
+{
+	BLI_assert((int)cv.size()==8);
+	auto add_tets_from_box = [&]()
+	{
+		Vector3d max = cv[5];
+		Vector3d min = cv[3];
+		std::vector<Vector3d> v = {
+			// Top plane, clockwise looking down
+			max,
+			Vector3d(min[0], max[1], max[2]),
+			Vector3d(min[0], max[1], min[2]),
+			Vector3d(max[0], max[1], min[2]),
+			// Bottom plane, clockwise looking down
+			Vector3d(max[0], min[1], max[2]),
+			Vector3d(min[0], min[1], max[2]),
+			min,
+			Vector3d(max[0], min[1], min[2])
+		};
+		// Add vertices and get indices of the box
+		std::vector<int> b;
+		for(int i=0; i<8; ++i)
+		{
+			b.emplace_back(data->verts.size());
+			data->verts.emplace_back(v[i]);
+		}
+		// From the box, create five new tets
+		std::vector<Vector4i> new_tets = {
+			Vector4i( b[0], b[5], b[7], b[4] ),
+			Vector4i( b[5], b[7], b[2], b[0] ),
+			Vector4i( b[5], b[0], b[2], b[1] ),
+			Vector4i( b[7], b[2], b[0], b[3] ),
+			Vector4i( b[5], b[2], b[7], b[6] )
+		};
+		for(int i=0; i<5; ++i)
+			data->tets.emplace_back(new_tets[i]);
+	};
+
+	// Add this cube because we're at bottom
+	if (level==0)
+	{
+		add_tets_from_box();
+		return;
+	}
+
+	// Only subdivide if we contain vertices
+	// Otherwise just return.
+	AlignedBox<double,3> aabb;
+	aabb.extend(cv[3]); aabb.extend(cv[5]);
+	aabb.extend(aabb.min()-Vector3d::Ones()*1e-8);
+	aabb.extend(aabb.max()+Vector3d::Ones()*1e-8);
+	std::vector<int> new_pts_in_box;
+	int nv = pts_in_box.size();
+	for (int i=0; i<nv; ++i)
+	{
+		int idx = pts_in_box[i];
+		if (aabb.contains(data->V->row(idx).transpose()))
+			new_pts_in_box.emplace_back(idx);
+	}
+	if (new_pts_in_box.size()==0)
+	{
+		add_tets_from_box();
+		return;
+	}
+
+	// cv are the cube vertices, listed clockwise
+	// with the bottom plane first, then top plane
+	Vector3d vfront = 0.25*(cv[0]+cv[1]+cv[5]+cv[4]); // front (+z)
+	Vector3d vback = 0.25*(cv[3]+cv[2]+cv[6]+cv[7]); // back (-z)
+	Vector3d vleft = 0.25*(cv[0]+cv[3]+cv[7]+cv[4]); // left (-x)
+	Vector3d vright = 0.25*(cv[1]+cv[2]+cv[6]+cv[5]); // right (+x)
+	Vector3d vtop = 0.25*(cv[4]+cv[5]+cv[6]+cv[7]); // top (+y)
+	Vector3d vbot = 0.25*(cv[0]+cv[1]+cv[2]+cv[3]); // bot (-y)
+	Vector3d vcent = 0.125*(cv[0]+cv[1]+cv[2]+cv[3]+cv[4]+cv[5]+cv[6]+cv[7]); // center
+	Vector3d v01 = 0.5*(cv[0]+cv[1]);
+	Vector3d v03 = 0.5*(cv[0]+cv[3]);
+	Vector3d v04 = 0.5*(cv[0]+cv[4]);
+	Vector3d v12 = 0.5*(cv[1]+cv[2]);
+	Vector3d v15 = 0.5*(cv[1]+cv[5]);
+	Vector3d v23 = 0.5*(cv[2]+cv[3]);
+	Vector3d v26 = 0.5*(cv[2]+cv[6]);
+	Vector3d v37 = 0.5*(cv[3]+cv[7]);
+	Vector3d v45 = 0.5*(cv[4]+cv[5]);
+	Vector3d v56 = 0.5*(cv[5]+cv[6]);
+	Vector3d v67 = 0.5*(cv[6]+cv[7]);
+	Vector3d v47 = 0.5*(cv[4]+cv[7]);
+	subdivide_cube(data, { cv[0], v01, vbot, v03, v04, vfront, vcent, vleft }, new_pts_in_box, level-1);
+	subdivide_cube(data, { v01, cv[1], v12, vbot, vfront, v15, vright, vcent }, new_pts_in_box, level-1);
+	subdivide_cube(data, { vbot, v12, cv[2], v23, vcent, vright, v26, vback }, new_pts_in_box, level-1);
+	subdivide_cube(data, { v03, vbot, v23, cv[3], vleft, vcent, vback, v37 }, new_pts_in_box, level-1);
+	subdivide_cube(data, { v04, vfront, vcent, vleft, cv[4], v45, vtop, v47 }, new_pts_in_box, level-1);
+	subdivide_cube(data, { vfront, v15, vright, vcent, v45, cv[5], v56, vtop }, new_pts_in_box, level-1);
+	subdivide_cube(data, { vcent, vright, v26, vback, vtop, v56, cv[6], v67 }, new_pts_in_box, level-1);
+	subdivide_cube(data, { vleft, vcent, vback, v37, v47, vtop, v67, cv[7] }, new_pts_in_box, level-1);
+}
+
+
+
 bool EmbeddedMesh::generate(
 	const Eigen::MatrixXd &V, // embedded verts
 	const Eigen::MatrixXi &F, // embedded faces
@@ -70,99 +218,38 @@ bool EmbeddedMesh::generate(
 	Eigen::MatrixXd *x_tets, // lattice vertices, n x 3
 	bool trim_lattice)
 {
-	// How big the grid cells are as a fraction
-	// of the total mesh.
-	static const double GRID_FRAC = 0.15;
-
-	if (emb_mesh==NULL)
-		return false;
-	if (x_tets==NULL)
-		return false;
-
 	emb_mesh->faces = F;
 	emb_mesh->x_rest = V;
 
 	AlignedBox<double,3> aabb;
-	int nv = V.rows();
-	for(int i=0; i<nv; ++i)
-		aabb.extend(V.row(i).transpose());
-	
-	aabb.extend(aabb.min()-Vector3d::Ones()*1e-6);
-	aabb.extend(aabb.max()+Vector3d::Ones()*1e-6);
-	Vector3d mesh_boxmin = aabb.min();
-	Vector3d sizes = aabb.sizes();
-	double grid_dx = sizes.maxCoeff() * GRID_FRAC;
-
-	// Generate vertices and tets
-	std::vector<Vector3d> verts;
-	std::vector<Vector4i> tets;
+	int nev = V.rows();
+	std::vector<int> pts_in_box;
+	for (int i=0; i<nev; ++i)
 	{
-		std::unordered_map<std::string, int> vertex_map; // [i,j,k]->index
-
-		auto grid_hash = [&](const Vector3d &x)
-		{
-			Vector3i ll = Vector3i( // nearest gridcell
-				std::round((x[0]-mesh_boxmin[0])/grid_dx),
-				std::round((x[1]-mesh_boxmin[1])/grid_dx),
-				std::round((x[2]-mesh_boxmin[2])/grid_dx));
-			return std::to_string(ll[0])+' '+std::to_string(ll[1])+' '+std::to_string(ll[2]);
-		};
-
-		auto add_box = [&](int i_, int j_,

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list