[Bf-blender-cvs] [0c6fc34eab5] soc-2020-soft-body: updating to use SDF all over

over0219 noreply at git.blender.org
Wed Jul 15 05:09:06 CEST 2020


Commit: 0c6fc34eab5dd002050d897f3bba22e60c777277
Author: over0219
Date:   Tue Jul 14 12:17:06 2020 -0500
Branches: soc-2020-soft-body
https://developer.blender.org/rB0c6fc34eab5dd002050d897f3bba22e60c777277

updating to use SDF all over

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

M	extern/softbody/CMakeLists.txt
M	extern/softbody/src/admmpd_bvh_traverse.cpp
M	extern/softbody/src/admmpd_bvh_traverse.h
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_geom.cpp
A	extern/softbody/src/admmpd_geom.h
D	extern/softbody/src/admmpd_math.cpp
D	extern/softbody/src/admmpd_math.h
M	extern/softbody/src/admmpd_pin.cpp
M	extern/softbody/src/admmpd_pin.h
A	extern/softbody/src/admmpd_sdf.cpp
A	extern/softbody/src/admmpd_sdf.h
M	extern/softbody/src/admmpd_solver.cpp
M	extern/softbody/src/admmpd_tetmesh.cpp
M	extern/softbody/src/admmpd_types.h
M	intern/softbody/admmpd_api.cpp

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

diff --git a/extern/softbody/CMakeLists.txt b/extern/softbody/CMakeLists.txt
index 7f631400ce0..84b2de7fea7 100644
--- a/extern/softbody/CMakeLists.txt
+++ b/extern/softbody/CMakeLists.txt
@@ -28,6 +28,18 @@ set(INC_SYS
 	../../source/blender/makesdna # BLI_math_geom requires DNA
 )
 
+set(SDFGEN_SRC
+	src/sdfgen/array1.h
+	src/sdfgen/array2.h
+	src/sdfgen/array3.h
+	src/sdfgen/hashgrid.h
+	src/sdfgen/hashtable.h
+	src/sdfgen/makelevelset3.cpp
+	src/sdfgen/makelevelset3.h
+	src/sdfgen/util.h
+	src/sdfgen/vec.h
+)
+
 set(SRC
 	src/admmpd_bvh.h
 	src/admmpd_bvh.cpp
@@ -39,17 +51,20 @@ set(SRC
 	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_math.h
-	src/admmpd_math.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_types.h
+	${SDFGEN_SRC}
 )
 
 set(LIB
diff --git a/extern/softbody/src/admmpd_bvh_traverse.cpp b/extern/softbody/src/admmpd_bvh_traverse.cpp
index 0695aeef2b5..7def5340085 100644
--- a/extern/softbody/src/admmpd_bvh_traverse.cpp
+++ b/extern/softbody/src/admmpd_bvh_traverse.cpp
@@ -5,13 +5,86 @@
 #define ADMMPD_BVH_H_ 1
 
 #include "admmpd_bvh_traverse.h"
-#include "admmpd_math.h"
+#include "admmpd_geom.h"
 #include "BLI_assert.h"
 #include "BLI_math_geom.h"
 
 namespace admmpd {
 using namespace Eigen;
 
+template <typename T>
+RayClosestHit<T>::RayClosestHit(
+		const VecType &orig_,
+		const VecType &dir_,
+		const MatrixXType *prim_verts_,
+		const Eigen::MatrixXi *tri_inds_,
+		T eps_,
+		T t_min_,
+		T t_max_) :
+	o(orig_),
+	d(dir_),
+	prim_verts(prim_verts_),
+	tri_inds(tri_inds_),
+	eps(eps_),
+	t_min(t_min_)
+{
+	output.t_max = t_max_;
+	BLI_assert(prim_verts != NULL);
+	BLI_assert(tri_inds != NULL);
+	BLI_assert(prim_verts->cols()==3);
+	BLI_assert(tri_inds->cols()==3);
+}
+
+template <typename T>
+void RayClosestHit<T>::traverse(
+	const AABB &left_aabb, bool &go_left,
+	const AABB &right_aabb, bool &go_right,
+	bool &go_left_first)
+{
+	go_left = geom::ray_aabb<T>(o,d,left_aabb,t_min,output.t_max) ||
+		(eps > 0 ? left_aabb.exteriorDistance(o) < eps : false);
+	go_right = geom::ray_aabb<T>(o,d,right_aabb,t_min,output.t_max) ||
+		(eps > 0 ? right_aabb.exteriorDistance(o) < eps : false);
+}
+
+template <typename T>
+bool RayClosestHit<T>::stop_traversing(const AABB &aabb, int prim)
+{
+	BLI_assert(prim > 0);
+	BLI_assert(prim < tri_inds->rows());
+	if (!geom::ray_aabb<T>(o,d,aabb,t_min,output.t_max))
+		return true;
+	RowVector3i p = tri_inds->row(prim);
+	VecType v[3] = {
+		prim_verts->row(p[0]),
+		prim_verts->row(p[1]),
+		prim_verts->row(p[2])
+	};
+	T t_max = output.t_max;
+	VecType bary;
+	bool hit = geom::ray_triangle<T>(o,d,v[0],v[1],v[2],t_min,t_max,&bary);
+	if (hit)
+	{
+		output.prim = prim;
+		output.t_max = t_max;
+		output.barys = bary;
+		return false;
+	}
+	if (eps > 0)
+	{
+		VecType o_on_tri = geom::point_on_triangle<T>(o,v[0],v[1],v[2]);
+		T dist = (o-o_on_tri).norm();
+		if (dist < eps)
+		{
+			output.prim = prim;
+			output.t_max = dist;
+			output.barys = geom::point_triangle_barys<T>(o_on_tri,v[0],v[1],v[2]);
+		}
+	}
+	return false;
+}
+
+
 template <typename T>
 void PointInTetMeshTraverse<T>::traverse(
 	const AABB &left_aabb, bool &go_left,
@@ -43,7 +116,7 @@ bool PointInTetMeshTraverse<T>::stop_traversing(
 		prim_verts->row(t[3])
 	};
 
-	bool hit = point_in_tet(
+	bool hit = geom::point_in_tet(
 		point.template cast<double>(),
 		v[0].template cast<double>(),
 		v[1].template cast<double>(),
@@ -285,6 +358,8 @@ bool TetIntersectsMeshTraverse<T>::stop_traversing(
 } // end point in mesh stop traversing
 
 // Compile template types
+template class admmpd::RayClosestHit<double>;
+template class admmpd::RayClosestHit<float>;
 template class admmpd::PointInTetMeshTraverse<double>;
 template class admmpd::PointInTetMeshTraverse<float>;
 template class admmpd::PointInTriangleMeshTraverse<double>;
diff --git a/extern/softbody/src/admmpd_bvh_traverse.h b/extern/softbody/src/admmpd_bvh_traverse.h
index 774eb6a6b10..29eebd0163d 100644
--- a/extern/softbody/src/admmpd_bvh_traverse.h
+++ b/extern/softbody/src/admmpd_bvh_traverse.h
@@ -9,6 +9,7 @@
 
 namespace admmpd {
 
+
 // Traverse class for traversing the structures.
 template <typename T, int DIM>
 class Traverser
@@ -31,6 +32,51 @@ public:
 	virtual bool stop_traversing(const AABB &aabb, int prim) = 0;
 };
 
+// Closest hit BVH traversal.
+template <typename T>
+class RayClosestHit : public Traverser<T,3>
+{
+protected:
+	using typename Traverser<T,3>::AABB;
+	typedef Eigen::Matrix<T,3,1> VecType;
+	typedef Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> MatrixXType;
+
+	VecType o, d;
+	const MatrixXType *prim_verts;
+	const Eigen::MatrixXi *tri_inds;
+	T eps;
+	T t_min;
+
+public:
+	struct Output {
+		int prim; // -1 if no intersections
+		T t_max;
+		VecType barys;
+		Output() :
+			prim(-1),
+			t_max(std::numeric_limits<T>::max()),
+			barys(VecType::Zero())
+			{}
+	} output;
+
+	RayClosestHit(
+			const VecType &orig_, // ray origin
+			const VecType &dir_,  // normalized ray direction
+			const MatrixXType *prim_verts_,
+			const Eigen::MatrixXi *tri_inds_,
+			T eps_, // if dist(0,tri) < eps, is a hit. eps<=0 skips this test
+			T t_min_=0,
+			T t_max_=std::numeric_limits<T>::max());
+
+	void traverse(
+		const AABB &left_aabb, bool &go_left,
+		const AABB &right_aabb, bool &go_right,
+		bool &go_left_first);
+
+	// Searches for closest hit, so always returns false
+	bool stop_traversing(const AABB &aabb, int prim);
+};
+
 // Point in tet mesh traversal
 template <typename T>
 class PointInTetMeshTraverse : public Traverser<T,3>
diff --git a/extern/softbody/src/admmpd_collision.cpp b/extern/softbody/src/admmpd_collision.cpp
index 4d2444e6a52..892a599264d 100644
--- a/extern/softbody/src/admmpd_collision.cpp
+++ b/extern/softbody/src/admmpd_collision.cpp
@@ -3,7 +3,7 @@
 
 #include "admmpd_collision.h"
 #include "admmpd_bvh_traverse.h"
-#include "admmpd_math.h"
+#include "admmpd_geom.h"
 
 #include "BLI_assert.h"
 #include "BLI_task.h"
@@ -51,6 +51,7 @@ void Collision::set_obstacles(
 		obsdata.aabbs.resize(nf);
 	}
 
+	Vector3d v_eta = Vector3d::Ones()*settings.collision_eps;
 	for (int i=0; i<nf; ++i)
 	{
 		obsdata.aabbs[i].setEmpty();
@@ -61,156 +62,93 @@ void Collision::set_obstacles(
 			obsdata.aabbs[i].extend(obsdata.V0.row(fj).transpose());
 			obsdata.aabbs[i].extend(obsdata.V1.row(fj).transpose());
 		}
+		obsdata.aabbs[i].extend(obsdata.aabbs[i].min()-v_eta);
+		obsdata.aabbs[i].extend(obsdata.aabbs[i].max()+v_eta);
 	}
 
 	obsdata.tree.init(obsdata.aabbs);
 
 } // end add obstacle
 
-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,
-	std::vector<VFCollisionPair> *pairs)
+std::pair<bool,VFCollisionPair>
+Collision::detect_point_against_mesh(
+        int pt_idx,
+        bool pt_is_obs,
+        const Eigen::Vector3d &pt_t0,
+        const Eigen::Vector3d &pt_t1,
+        bool mesh_is_obs,
+        const Eigen::MatrixXd *mesh_x,
+        const Eigen::MatrixXi *mesh_tris,
+        const AABBTree<double,3> *mesh_tree) const
 {
+	std::pair<bool,VFCollisionPair> ret = 
+		std::make_pair(false, VFCollisionPair());
+
 	// Any faces to detect against?
 	if (mesh_tris->rows()==0)
-		return;
-
-	// TODO
-	// This won't work for overlapping obstacles.
-	// We would instead need something like a signed distance field
-	// or continuous collision detection.
-
-	PointInTriangleMeshTraverse<double> pt_in_mesh(
-		pt, mesh_x, mesh_tris);
-	mesh_tree->traverse(pt_in_mesh);
-	if (pt_in_mesh.output.num_hits() % 2 != 1)
-		return;
-
-	// If we are inside an obstacle, we
-	// have to project to the nearest surface.
-
-	// TODO
-	// Consider replacing this with BLI codes:
-	// BLI_bvhtree_find_nearest in BLI_kdopbvh.h
-	// But since it doesn't have a point-in-mesh
-	// detection, we may as use our own BVH/traverser
-	// for now.
-
-	NearestTriangleTraverse<double> find_nearest_tri(
-		pt, mesh_x, mesh_tris);
-	mesh_tree->traverse(find_nearest_tri);
-	if (find_nearest_tri.output.prim < 0) // error
-		return;
+		return ret;	
 
-	// Create collision pair
-	pairs->emplace_back();
-	VFCollisionPair &pair = pairs->back();
+/*
+	VFCollisionPair &pair = ret.second;
+	pair.p_idx = pt_idx;
+	pair.p_is_obs = false;
+	pair.q_idx = 0;
+	pair.q_is_obs = 1;
+	double max_z = mesh_x->col(2).maxCoeff();
+	pair.pt_on_q = Vector3d(pt_t1[0],pt_t1[1],max_z);
+*/
+	return ret;
+/*
+	// Use a ray that is pos at t0 to t1
+	// with t_max being the displacment. If not moving,
+	// set the "eps" variable used by traversal which
+	// does point-triangle distance, and considers it a hit
+	// if the distance is less than the eps.
+	Vector3d dx = (pt_t1-pt_t0);
+	double t_max = dx.norm();
+	double eps = -1; // used as point-triangle distance query
+	//if (t_max < settings.collision_eps)
+	if (false)
+	{
+		dx = Vector3d(0,0,1);
+		t_max = settings.collision_eps;
+		eps = settings.collision_eps;
+	}
+	dx.normalize();
+
+	// Traverse the BVH
+	RayClosestHit<double> ray_hit_mesh(
+		pt_t0, dx,
+		mesh_x, mesh_tris,
+		eps, 0, t_max);
+	mesh_tree->traverse(ray_hit_mesh);
+
+//	if (pt_idx==0)
+//	{
+//		std::cout << "\n\nV0 (z): " << pt_t0[2] << std::endl;
+//		std::cout << "dir: " << dx.transpose() << std::endl;
+//		std::cout << ray_hit_mesh.output.prim << std::endl;
+//		if(ray_hit_mesh.output.prim >= 0)
+//			throw std::runtime_error("YAY HIT");
+//	}
+
+	if (ray_hit_mesh.output.prim < 0)
+		return ret;
+
+	ret.first = true;
+	VFCollisionPair &pair = ret.second;
 	pair.p_idx = pt_idx;
 	pair.p_is_obs = pt_is_obs;
-	pair.q_idx = find_nearest_tri.output.prim;
+	pair.q_idx = ray_hit_mesh.output.prim;
 	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 < mesh_tris->rows());
-//	RowVector3i tri_inds = mesh_tris->row(pair.q_idx);
-/

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list