[Bf-blender-cvs] [9e2042ca033] soc-2020-soft-body: several bugfixes but I think I'm going to need to change the way I handle constrained solve

over0219 noreply at git.blender.org
Wed Jun 24 06:03:59 CEST 2020


Commit: 9e2042ca033a2ff8134abd719e60292ce65e720c
Author: over0219
Date:   Tue Jun 23 23:03:53 2020 -0500
Branches: soc-2020-soft-body
https://developer.blender.org/rB9e2042ca033a2ff8134abd719e60292ce65e720c

several bugfixes but I think I'm going to need to change the way I handle constrained solve

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

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_embeddedmesh.h
M	extern/softbody/src/admmpd_math.h
M	extern/softbody/src/admmpd_solver.cpp
M	extern/softbody/src/admmpd_solver.h
A	extern/softbody/src/admmpd_tetmesh.cpp
A	extern/softbody/src/admmpd_tetmesh.h
M	extern/softbody/src/admmpd_types.h
M	intern/softbody/admmpd_api.cpp
M	source/blender/blenkernel/intern/softbody.c

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

diff --git a/extern/softbody/CMakeLists.txt b/extern/softbody/CMakeLists.txt
index 4d6ff3328b8..3e006f74ae3 100644
--- a/extern/softbody/CMakeLists.txt
+++ b/extern/softbody/CMakeLists.txt
@@ -43,6 +43,8 @@ set(SRC
   src/admmpd_math.cpp
   src/admmpd_solver.h
   src/admmpd_solver.cpp
+  src/admmpd_tetmesh.h
+  src/admmpd_tetmesh.cpp
   src/admmpd_types.h
 )
 
diff --git a/extern/softbody/src/admmpd_collision.cpp b/extern/softbody/src/admmpd_collision.cpp
index 98c5653e7f7..be6bd0a21b7 100644
--- a/extern/softbody/src/admmpd_collision.cpp
+++ b/extern/softbody/src/admmpd_collision.cpp
@@ -10,6 +10,7 @@
 #include "BLI_threads.h"
 
 #include <iostream>
+#include <sstream>
 
 namespace admmpd {
 using namespace Eigen;
@@ -23,7 +24,7 @@ VFCollisionPair::VFCollisionPair() :
 	q_n(0,0,0)
 	{}
 
-void EmbeddedMeshCollision::set_obstacles(
+void Collision::set_obstacles(
 	const float *v0,
 	const float *v1,
 	int nv,
@@ -67,53 +68,32 @@ void EmbeddedMeshCollision::set_obstacles(
 
 } // end add obstacle
 
-typedef struct DetectThreadData {
-	const EmbeddedMeshData *mesh;
-	const EmbeddedMeshCollision::ObstacleData *obsdata;
-	const Eigen::MatrixXd *x0;
-	const Eigen::MatrixXd *x1;
-	double floor_z;
-	std::vector<std::vector<VFCollisionPair> > *pt_vf_pairs; // per thread pairs
-} DetectThreadData;
-
-static void parallel_detect_obstacles(
-	void *__restrict userdata,
-	const int i,
-	const TaskParallelTLS *__restrict tls)
+void Collision::detect_discrete_vf(
+	const Eigen::Vector3d &pt,
+	int pt_idx,
+	bool pt_is_obs,
+	const AABBTree<double,3> *mesh_tree,
+	const Eigen::MatrixXd *mesh_x,
+	const Eigen::MatrixXi *mesh_tris,
+	bool mesh_is_obs,
+	double floor_z,
+	std::vector<VFCollisionPair> *pairs)
 {
-	DetectThreadData *td = (DetectThreadData*)userdata;
-
-	// Comments say "don't use this" but how else am I supposed
-	// to get the thread ID? It appears to return the right thing...
-	int thread_idx = BLI_task_parallel_thread_id(tls);
-	std::vector<VFCollisionPair> &tl_pairs = td->pt_vf_pairs->at(thread_idx);
-
-	int tet_idx = td->mesh->vtx_to_tet[i];
-	RowVector4i tet = td->mesh->tets.row(tet_idx);
-	Vector4d bary = td->mesh->barys.row(i);
-
-	// First, get the surface vertex
-	Vector3d pt = 
-		bary[0] * td->x1->row(tet[0]) +
-		bary[1] * td->x1->row(tet[1]) +
-		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)
+	if (pt[2] < floor_z)
 	{
-		tl_pairs.emplace_back();
-		VFCollisionPair &pair = tl_pairs.back();
-		pair.p_idx = i;
-		pair.p_is_obs = 0;
+		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],td->floor_z);
+		pair.pt_on_q = Vector3d(pt[0],pt[1],floor_z);
 		pair.q_n = Vector3d(0,0,1);
 	}
 
-	// Any obstacles?
-	if (td->obsdata->F.rows()==0)
+	// Any faces to detect against?
+	if (mesh_tris->rows()==0)
 		return;
 
 	// TODO
@@ -122,8 +102,8 @@ static void parallel_detect_obstacles(
 	// or continuous collision detection.
 
 	PointInTriangleMeshTraverse<double> pt_in_mesh(
-		pt, &td->obsdata->V1, &td->obsdata->F);
-	td->obsdata->tree.traverse(pt_in_mesh);
+		pt, mesh_x, mesh_tris);
+	mesh_tree->traverse(pt_in_mesh);
 	if (pt_in_mesh.output.num_hits() % 2 != 1)
 		return;
 
@@ -138,40 +118,93 @@ static void parallel_detect_obstacles(
 	// for now.
 
 	NearestTriangleTraverse<double> find_nearest_tri(
-		pt, &td->obsdata->V1, &td->obsdata->F);
-	td->obsdata->tree.traverse(find_nearest_tri);
+		pt, mesh_x, mesh_tris);
+	mesh_tree->traverse(find_nearest_tri);
 	if (find_nearest_tri.output.prim < 0) // error
 		return;
 
 	// Create collision pair
-	tl_pairs.emplace_back();
-	VFCollisionPair &pair = tl_pairs.back();
-	pair.p_idx = i;
-	pair.p_is_obs = 0;
+	pairs->emplace_back();
+	VFCollisionPair &pair = pairs->back();
+	pair.p_idx = pt_idx;
+	pair.p_is_obs = pt_is_obs;
 	pair.q_idx = find_nearest_tri.output.prim;
-	pair.q_is_obs = 1;
+	pair.q_is_obs = mesh_is_obs;
 	pair.pt_on_q = find_nearest_tri.output.pt_on_tri;
 
 	// Compute face normal
 	BLI_assert(pair.q_idx >= 0);
-	BLI_assert(pair.q_idx < td->obsdata->F.rows());
-	RowVector3i tri_inds = td->obsdata->F.row(pair.q_idx);
+	BLI_assert(pair.q_idx < mesh_tris->rows());
+	RowVector3i tri_inds = mesh_tris->row(pair.q_idx);
+	BLI_assert(tri_inds[0]>=0 && tri_inds[0]<mesh_x->rows());
+	BLI_assert(tri_inds[1]>=0 && tri_inds[1]<mesh_x->rows());
+	BLI_assert(tri_inds[2]>=0 && tri_inds[2]<mesh_x->rows());
 	Vector3d tri[3] = {
-		td->obsdata->V1.row(tri_inds[0]),
-		td->obsdata->V1.row(tri_inds[1]),
-		td->obsdata->V1.row(tri_inds[2])
+		mesh_x->row(tri_inds[0]),
+		mesh_x->row(tri_inds[1]),
+		mesh_x->row(tri_inds[2])
 	};
 	pair.q_n = ((tri[1]-tri[0]).cross(tri[2]-tri[0])).normalized();
 
-} // end parallel detect against obstacles
+//	std::stringstream ss;
+//	ss << "\nhit:" <<
+//		"\n\t normal: " << pair.q_n.transpose() <<
+//		"\n\t pt: " << pt.transpose() <<
+//		"\n\t pt_on_tri: " << pair.pt_on_q.transpose() <<
+//		std::endl;
+//	printf("%s",ss.str().c_str());
+
+} // end detect_discrete_vf
+
+typedef struct DetectThreadData {
+	const TetMeshData *tetmesh;
+	const EmbeddedMeshData *embmesh;
+	const Collision::ObstacleData *obsdata;
+	const Eigen::MatrixXd *x0;
+	const Eigen::MatrixXd *x1;
+	double floor_z;
+	std::vector<std::vector<VFCollisionPair> > *pt_vf_pairs; // per thread pairs
+} DetectThreadData;
 
 static void parallel_detect(
 	void *__restrict userdata,
 	const int i,
 	const TaskParallelTLS *__restrict tls)
 {
-	parallel_detect_obstacles(userdata,i,tls);
-	//parallel_detect_self(userdata,i,tls);	
+	DetectThreadData *td = (DetectThreadData*)userdata;
+
+	// Comments say "don't use this" but how else am I supposed
+	// to get the thread ID? It appears to return the right thing...
+	int thread_idx = BLI_task_parallel_thread_id(tls);
+	std::vector<VFCollisionPair> &tl_pairs = td->pt_vf_pairs->at(thread_idx);
+
+	if (td->tetmesh != nullptr)
+	{
+
+	} // end detect with tet meshes
+	
+	if (td->embmesh != nullptr)
+	{
+		int tet_idx = td->embmesh->vtx_to_tet[i];
+		RowVector4i tet = td->embmesh->tets.row(tet_idx);
+		Vector4d bary = td->embmesh->barys.row(i);
+		Vector3d pt = 
+			bary[0] * td->x1->row(tet[0]) +
+			bary[1] * td->x1->row(tet[1]) +
+			bary[2] * td->x1->row(tet[2]) +
+			bary[3] * td->x1->row(tet[3]);
+
+		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
 
 int EmbeddedMeshCollision::detect(
@@ -187,25 +220,114 @@ int EmbeddedMeshCollision::detect(
 	std::vector<std::vector<VFCollisionPair> > pt_vf_pairs
 		(max_threads, std::vector<VFCollisionPair>());
 
+	DetectThreadData thread_data = {
+		.tetmesh = nullptr,
+		.embmesh = mesh,
+		.obsdata = &obsdata,
+		.x0 = x0,
+		.x1 = x1,
+		.floor_z = floor_z,
+		.pt_vf_pairs = &pt_vf_pairs
+	};
+
+	int nev = mesh->x_rest.rows();
+
+	TaskParallelSettings settings;
+	BLI_parallel_range_settings_defaults(&settings);
+	BLI_task_parallel_range(0, nev, &thread_data, parallel_detect, &settings);
+
+	// Combine thread-local results
+	vf_pairs.clear();
+	for (int i=0; i<max_threads; ++i)
+	{
+		const std::vector<VFCollisionPair> &tl_pairs = pt_vf_pairs[i];
+		vf_pairs.insert(vf_pairs.end(), tl_pairs.begin(), tl_pairs.end());
+	}
 
+	return vf_pairs.size();
+} // end detect
 
+static Vector3d vx0(0,0,0);
 
+void EmbeddedMeshCollision::jacobian(
+	const Eigen::MatrixXd *x,
+	std::vector<Eigen::Triplet<double> > *trips_x,
+	std::vector<Eigen::Triplet<double> > *trips_y,
+	std::vector<Eigen::Triplet<double> > *trips_z,
+	std::vector<double> *l)
+{
+	BLI_assert(x != NULL);
+	BLI_assert(x->cols() == 3);
 
+	int np = vf_pairs.size();
+	if (np==0)
+		return;
 
-floor_z = -2;
+	l->reserve((int)l->size() + np);
+	trips_x->reserve((int)trips_x->size() + np*4);
+	trips_y->reserve((int)trips_y->size() + np*4);
+	trips_z->reserve((int)trips_z->size() + np*4);
 
+	for (int i=0; i<np; ++i)
+	{
+		VFCollisionPair &pair = vf_pairs[i];
+		int emb_p_idx = pair.p_idx;
 
+		// TODO: obstacle point intersecting mesh
+		if (pair.p_is_obs)
+		{
+			continue;
+		}
 
+		// Obstacle collision
+		if (pair.q_is_obs)
+		{
+			RowVector4d bary = mesh->barys.row(emb_p_idx);
+			int tet_idx = mesh->vtx_to_tet[emb_p_idx];
+			RowVector4i tet = mesh->tets.row(tet_idx);
 
+			// Basically a pin constraint
+			for (int j=0; j<3; ++j)
+			{
+				int c_idx = l->size();
+				for (int k=0; k<4; ++k)
+				{
+					if (j==0)
+						trips_x->emplace_back(c_idx, tet[k], bary[k]*pair.q_n[0]);
+					if (j==1)
+						trips_y->emplace_back(c_idx, tet[k], bary[k]*pair.q_n[1]);
+					if (j==2)
+						trips_z->emplace_back(c_idx, tet[k], bary[k]*pair.q_n[2]);
+				}
+				l->emplace_back(pair.pt_on_q[j]*pair.q_n[j]);
+			}
 
+			continue;
+		}
 
+		// Self collisions
+	
+	} // end loop pairs
 
+} // end jacobian
 
+/*
+int TetMeshCollision::detect(
+	const Eigen::MatrixXd *x0,
+	const Eigen::MatrixXd *x1)
+{
+	if (mesh==NULL)
+		return 0;
 
+	update_bvh(x0,x1);
 
+	int max_threads = std::max(1,BLI_system_thread_count());
+	std::vector<std::vector<VFCollisionPair> > pt_vf_pairs
+		(max_threads, std::vector<VFCollisionPair>());
 
 	DetectThreadData thread_data = {
-		.mesh = mesh,
+		.tetmesh = mesh,
+		.embmesh = nullptr,
 		.obsdata = &obsdata,
 		.x0 = x0,
 		.x1 = x1,
@@ -213,10 +335,10 @@ floor_z = -2;
 		.pt_vf_pairs = &pt_vf_pairs
 	};
 
-	int nev = mesh->x_rest.rows();
+	int nv = x1->rows();
 	TaskParallelSettings settings;
 	BLI_parallel_range_settings_defaults(&settings);
-	BLI_task_parallel_range(0, nev, &thread_data, parallel_detect, &settings);
+	BLI_task_parallel_range(0, nv, &thread_data, parallel_detect, &settings);
 
 	// Combine thread-local results
 	vf_pairs.clear();
@@ -227,9 +349,9 @@ floor_z = -2;
 	}
 
 	return vf_pairs.size();
-} // end detect
+}
 
-void EmbeddedMeshCollision::jacobian(
+void TetMeshCollision::jacobian(
 	const Eigen::MatrixXd *x,
 	std::vector<Eigen::Triplet<double> > *trips_x,
 	std::vector<Eigen::Triplet<double> > *trips_y,
@@ 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list