Commit: 0e7628be729d5bb9a2a40a3298c48b5c5e6aaccb
Author: mattoverby
Date: Mon Aug 3 16:35:30 2020 -0500
Branches: soc-2020-soft-body
https://developer.blender.org/rB0e7628be729d5bb9a2a40a3298c48b5c5e6aaccb
trying std thread instead of BLI threads
===================================================================
M extern/CMakeLists.txt
M extern/softbody/CMakeLists.txt
M extern/softbody/src/admmpd_bvh_traverse.cpp
M extern/softbody/src/admmpd_collision.cpp
M extern/softbody/src/admmpd_collision.h
M extern/softbody/src/admmpd_geom.cpp
M extern/softbody/src/admmpd_geom.h
M extern/softbody/src/admmpd_solver.cpp
M extern/softbody/src/admmpd_types.h
M intern/softbody/CMakeLists.txt
===================================================================
diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt
index 78dc955a315..7dd505d8a93 100644
--- a/extern/CMakeLists.txt
+++ b/extern/CMakeLists.txt
@@ -35,6 +35,7 @@ endif()
add_subdirectory(rangetree)
add_subdirectory(wcwidth)
add_subdirectory(softbody)
+add_subdirectory(discregrid)
if(WITH_BULLET)
if(NOT WITH_SYSTEM_BULLET)
diff --git a/extern/softbody/CMakeLists.txt b/extern/softbody/CMakeLists.txt
index 73e3c58b616..446f0b67ede 100644
--- a/extern/softbody/CMakeLists.txt
+++ b/extern/softbody/CMakeLists.txt
@@ -26,18 +26,7 @@ set(INC_SYS
${EIGEN3_INCLUDE_DIRS}
../../source/blender/blenlib
../../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
+ ../discregrid/discregrid/include
)
set(SRC
@@ -62,10 +51,10 @@ set(SRC
src/admmpd_types.h
src/svd/ImplicitQRSVD.h
src/svd/Tools.h
- ${SDFGEN_SRC}
)
set(LIB
+ extern_discregrid
)
blender_add_lib(extern_admmpd "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/extern/softbody/src/admmpd_bvh_traverse.cpp
b/extern/softbody/src/admmpd_bvh_traverse.cpp
index 819048d2ce2..bd60c604a32 100644
--- a/extern/softbody/src/admmpd_bvh_traverse.cpp
+++ b/extern/softbody/src/admmpd_bvh_traverse.cpp
@@ -229,11 +229,11 @@ void NearestTriangleTraverse<T>::traverse(
const AABB &right_aabb, bool &go_right,
bool &go_left_first)
{
- T l_d2 = left_aabb.exteriorDistance(point);
- go_left = l_d2 < output.dist;
- T r_d2 = right_aabb.exteriorDistance(point);
- go_right = r_d2 < output.dist;
- go_left_first = go_left < go_right;
+ T l_d = left_aabb.exteriorDistance(point);
+ go_left = l_d < output.dist;
+ T r_d = right_aabb.exteriorDistance(point);
+ go_right = r_d < output.dist;
+ go_left_first = go_left <= go_right;
}
template <typename T>
diff --git a/extern/softbody/src/admmpd_collision.cpp
b/extern/softbody/src/admmpd_collision.cpp
index ee982cb3f26..c9730e7f038 100644
--- a/extern/softbody/src/admmpd_collision.cpp
+++ b/extern/softbody/src/admmpd_collision.cpp
@@ -8,6 +8,7 @@
#include "BLI_assert.h"
#include "BLI_task.h"
#include "BLI_threads.h"
+#include <thread>
#include <iostream>
#include <sstream>
@@ -33,16 +34,23 @@ void Collision::set_obstacles(
(void)(v0);
if (nv==0 || nf==0)
{
-// obsdata.mesh = admmpd::EmbeddedMesh();
+ // Why even try this? Are you just being mean?
return;
}
+ std::vector<double> v1_dbl(nv*3);
+ Eigen::AlignedBox<double,3> domain;
+
if (obsdata.V.rows() != nv)
obsdata.V.resize(nv,3);
for (int i=0; i<nv; ++i)
{
for (int j=0; j<3; ++j)
+ {
obsdata.V(i,j) = v1[i*3+j];
+ v1_dbl[i*3+j] = v1[i*3+j];
+ }
+ domain.extend(obsdata.V.row(i).transpose());
}
if ((int)obsdata.leaves.size() != nf)
@@ -62,11 +70,28 @@ void Collision::set_obstacles(
obsdata.tree.init(obsdata.leaves);
+ // Generate signed distance field
+ {
+ obsdata.tm =
std::make_unique<Discregrid::TriangleMesh>(v1_dbl.data(), faces, nv, nf);
+ obsdata.md =
std::make_unique<Discregrid::MeshDistance>(*(obsdata.tm.get()));
+ domain.max() += 1e-3 * domain.diagonal().norm() *
Eigen::Vector3d::Ones();
+ domain.min() -= 1e-3 * domain.diagonal().norm() *
Eigen::Vector3d::Ones();
+ std::array<unsigned int, 3> resolution;
+ resolution[0] = 10; resolution[1] = 10; resolution[2] = 10;
+ obsdata.sdf =
std::make_unique<SDFType>(Discregrid::CubicLagrangeDiscreteGrid(domain,
resolution));
+ auto func = Discregrid::DiscreteGrid::ContinuousFunction{};
+ func = [&](Eigen::Vector3d const& xi) {
+ return obsdata.md->signedDistanceCached(xi);
+ };
+ obsdata.sdf->addFunction(func, false);
+ }
+
} // end add obstacle
std::pair<bool,VFCollisionPair>
Collision::detect_against_obs(
- const Eigen::Vector3d &pt,
+ const Eigen::Vector3d &pt_t0,
+ const Eigen::Vector3d &pt_t1,
const ObstacleData *obs) const
{
std::pair<bool,VFCollisionPair> ret =
@@ -75,14 +100,25 @@ Collision::detect_against_obs(
if (!obs->has_obs())
return ret;
- PointInTriangleMeshTraverse<double> pt_in_mesh(pt,&obs->V,&obs->F);
- obs->tree.traverse(pt_in_mesh);
- if (pt_in_mesh.output.num_hits()%2==0)
+ Eigen::Vector3d n;
+ double dist = obs->sdf->interpolate(0, pt_t1, &n);
+ if (dist > 0)
return ret;
- NearestTriangleTraverse<double> nearest_tri(pt,&obs->V,&obs->F);
+ // Performs BVH traversal to find the nearest face
+ // For some reason this is NOT giving me correct results :/
+// Vector3d nearest_pt = pt_t0;
+// unsigned int nearest_face = 0;
+// obs->md->distance(pt_t1, &nearest_pt, &nearest_face);
+// ret.first = true;
+// ret.second.q_idx = nearest_face;
+// ret.second.q_is_obs = true;
+// ret.second.q_pt = nearest_pt;
+// return ret;
+
+ // Guess I'll roll my own
+ NearestTriangleTraverse<double> nearest_tri(pt_t1,&obs->V,&obs->F);
obs->tree.traverse(nearest_tri);
-
ret.first = true;
ret.second.q_idx = nearest_tri.output.prim;
ret.second.q_is_obs = true;
@@ -136,28 +172,36 @@ int EmbeddedMeshCollision::detect(
const Eigen::MatrixXd *x0;
const Eigen::MatrixXd *x1;
std::vector<std::vector<VFCollisionPair> > *per_vertex_pairs;
+ std::vector<std::vector<Eigen::Vector2i> > *per_thread_results;
} DetectThreadData;
//
// Detection function for a single embedded vertex
//
+// auto per_embedded_vertex_detect = [](
+// void *__restrict userdata,
+// const int vi,
+// const TaskParallelTLS *__restrict tls)->void
auto per_embedded_vertex_detect = [](
- void *__restrict userdata,
- const int vi,
- const TaskParallelTLS *__restrict tls)->void
+ DetectThreadData *td,
+ int thread_idx,
+ int vi)->void
{
- (void)(tls);
- DetectThreadData *td = (DetectThreadData*)userdata;
+// (void)(tls);
+// DetectThreadData *td = (DetectThreadData*)userdata;
if (td->embmesh == nullptr)
return;
+ std::vector<Eigen::Vector2i> &pt_res =
td->per_thread_results->at(thread_idx);
std::vector<VFCollisionPair> &vi_pairs =
td->per_vertex_pairs->at(vi);
vi_pairs.clear();
+ Vector3d pt_t0 =
td->embmesh->get_mapped_facet_vertex(*td->x0,vi);
Vector3d pt_t1 =
td->embmesh->get_mapped_facet_vertex(*td->x1,vi);
// Special case, check if we are below the floor
if (pt_t1[2] < td->options->floor)
{
+ pt_res.emplace_back(vi,vi_pairs.size());
vi_pairs.emplace_back();
VFCollisionPair &pair = vi_pairs.back();
pair.p_idx = vi;
@@ -172,11 +216,12 @@ int EmbeddedMeshCollision::detect(
if (td->obsdata->has_obs())
{
std::pair<bool,VFCollisionPair> pt_hit_obs =
-
td->collision->detect_against_obs(pt_t1,td->obsdata);
+
td->collision->detect_against_obs(pt_t0,pt_t1,td->obsdata);
if (pt_hit_obs.first)
{
pt_hit_obs.second.p_idx = vi;
pt_hit_obs.second.p_is_obs = false;
+ pt_res.emplace_back(vi,vi_pairs.size());
vi_pairs.emplace_back(pt_hit_obs.second);
}
}
@@ -188,12 +233,14 @@ int EmbeddedMeshCollision::detect(
td->collision->detect_against_self(vi, pt_t1,
td->x1);
if (pt_hit_self.first)
{
+ pt_res.emplace_back(vi,vi_pairs.size());
vi_pairs.emplace_back(pt_hit_self.second);
}
}
}; // end detect for a single embedded vertex
+ std::vector<std::vector<Eigen::Vector2i> > per_thread_results;
DetectThreadData thread_data = {
.options = options,
.collision = this,
@@ -201,21 +248,63 @@ int EmbeddedMeshCollision::detect(
.obsdata = &obsdata,
.x0 = x0,
.x1 = x1,
- .per_vertex_pairs = &per_vertex_pairs
+ .per_vertex_pairs = &per_vertex_pairs,
+ .per_thread_results = &per_thread_results
};
- TaskParallelSettings thrd_settings;
- BLI_parallel_range_settings_defaults(&thrd_settings);
- BLI_task_parallel_range(0, nev, &thread_data,
per_embedded_vertex_detect, &thrd_settings);
+ // Okay, the thread pooling is a little strange here so let me explain.
+ // Collisions are processed per-vertex. If one vertex is colliding, it's
+ // likely that adjacent vertices (nearby index) are also colliding.
+ // Because of this, it's better to interlace/offset the pooling so that
+ // vertices next to eachother are on different threads to provide
+ // better concurrency. Otherwise a standard slice may end up doing
+ // all of the BVH traversals and the other threads do none!
+ // I haven't actually profiled this, so maybe I'm wrong. But
+ // parallel-for-all functions that do what I need
+ // aren't available in the Blender lib, so I'll have some funsies here.
+ int max_threads = std::max(1, std::min(nev,
admmpd::get_max_threads(options)));
+ const auto & per_thread_function =
[&per_embedded_vertex_detect,&max_threads,&nev]
+ (DetectThreadData *td, int thread_idx)
+ {
+ int slice = std::max((int)std::round((nev+1)/double(max_threads)),1);
+ for (int i=0; i<slice; ++i)
+ {
+ int vi = i*max_threads + thread_idx;
+ if (vi >= nev)
+ break;
+ per_embedded_vertex_detect(td,thread_idx,vi);
+ }
+ };
+
+ // Launch threads
+ std::vector<std::thread> pool;
+ per_thread_results.resize(max_threads, std::vector<Vector2i>());
+ for (int i=0; i<max_threads; ++i)
+ pool.emplace_back(per_thread_function,&thread_data,i);
+
+ // Combine parallel results
vf_pairs.clear();
- for (int i=0; i<nev; ++i)
+ for (int i=0; i<max_threads; ++i)
{
- int pvp = per_vertex_pairs[i].size();
- for (int j=0; j<pvp; ++j)
- vf_pairs.emplace_back(Vector2i(i,j));
+ if (pool[i].joinable())
+ pool[i].join(); // wait for thread to finish
+
+ vf_pairs.insert(vf_pairs.end(),
+ per_thread_results[i].begin(),
per_thread_results[i].end());
}
+// TaskParallelSettings thrd_settings;
+// BLI_parallel_range_settings_defaults(&thrd_settings);
+// BLI_task_parallel_range(0, nev, &thread_data,
per_embedded_vertex_detect, &thrd_settings);
+// vf_pairs.clear();
+// for (int i=0; i<nev; ++i)
+// {
+// int pvp = per_vertex_pairs[i].size();
+// for (int j=0; j<pvp; ++j)
+// vf_pairs.emplace_back(Vector2i(i,j));
+// }
+
return vf_pairs.size();
} // end detect
diff --git a/extern/softbody/src/admmpd_collision.h
b/extern/softbody/src/admmpd_collision.h
index 632b8f8ca2c..c89946f3539 100644
--- a/extern/softbod
@@ Diff output truncated at 10240 characters. @@
_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs