diff options
author | over0219 <over0219@umn.edu> | 2020-06-16 23:51:38 +0300 |
---|---|---|
committer | over0219 <over0219@umn.edu> | 2020-06-16 23:51:38 +0300 |
commit | 38855afd50a6d1a7b7069f5732d08e03e0f585bf (patch) | |
tree | ce4729745817754186c0bfcb5a4e8a91ac0f926b | |
parent | 0beb3002f27642b442f01e991ffcc4db76585cef (diff) |
lattice gen better but some bug on monkey, sometimes. probably a ptr error somewhere
-rw-r--r-- | extern/softbody/CMakeLists.txt | 3 | ||||
-rw-r--r-- | extern/softbody/src/admmpd_lattice.cpp | 121 | ||||
-rw-r--r-- | extern/softbody/src/admmpd_lattice.h | 3 | ||||
-rw-r--r-- | extern/softbody/src/admmpd_solver.cpp | 2 | ||||
-rw-r--r-- | extern/softbody/src/admmpd_solver.h | 1 | ||||
-rw-r--r-- | intern/softbody/admmpd_api.cpp | 13 |
6 files changed, 132 insertions, 11 deletions
diff --git a/extern/softbody/CMakeLists.txt b/extern/softbody/CMakeLists.txt index 63961cbb334..09fdc947dde 100644 --- a/extern/softbody/CMakeLists.txt +++ b/extern/softbody/CMakeLists.txt @@ -24,7 +24,8 @@ set(INC set(INC_SYS ${EIGEN3_INCLUDE_DIRS} - ../../source/blender/blenlib # BLI_task for threading + ../../source/blender/blenlib + ../../source/blender/makesdna # BLI_math_geom requires DNA ) set(SRC diff --git a/extern/softbody/src/admmpd_lattice.cpp b/extern/softbody/src/admmpd_lattice.cpp index 2440c6f4042..84b65260ded 100644 --- a/extern/softbody/src/admmpd_lattice.cpp +++ b/extern/softbody/src/admmpd_lattice.cpp @@ -7,14 +7,55 @@ #include "admmpd_bvh_traverse.h" #include <iostream> #include <unordered_map> +#include <set> #include "BLI_task.h" // threading namespace admmpd { using namespace Eigen; +typedef struct KeepTetThreadData { + AABBTree<double,3> *tree; // of embedded faces + const MatrixXd *pts; // of embedded verts + const MatrixXi *faces; // embedded faces + const std::vector<Vector3d> *tet_x; + const std::vector<Vector4i> *tets; + std::vector<int> *keep_tet; // 0 or 1 +} KeepTetThreadData; + +static void parallel_keep_tet( + void *__restrict userdata, + const int i, + const TaskParallelTLS *__restrict UNUSED(tls)) +{ + KeepTetThreadData *td = (KeepTetThreadData*)userdata; + RowVector4i tet = td->tets->at(i); + Vector3d tet_pts[4] = { + td->tet_x->at(tet[0]), + td->tet_x->at(tet[1]), + td->tet_x->at(tet[2]), + td->tet_x->at(tet[3]) + }; + + // Returns true if the tet intersects the + // surface mesh. Even if it doesn't, we want to keep + // the tet if it's totally enclosed in the mesh. + TetIntersectsMeshTraverse<double> traverser( + tet_pts, td->pts, td->faces); + bool hit = td->tree->traverse(traverser); + if (!hit) + { + if (traverser.output.ray_hit_count % 2 == 1) + hit = true; + } + + if (hit) { td->keep_tet->at(i) = 1; } + else { td->keep_tet->at(i) = 0; } + +} // end parallel test if keep tet bool Lattice::generate( const Eigen::MatrixXd &V, + const Eigen::MatrixXi &F, Eigen::MatrixXd *X, // lattice vertices, n x 3 Eigen::MatrixXi *T) // lattice elements, m x 4 { @@ -100,24 +141,90 @@ bool Lattice::generate( } // end create boxes and vertices - // Copy data into matrices + // We only want to keep tets that are either + // a) intersecting the surface mesh + // b) totally inside the surface mesh + std::set<int> refd_verts; + { + int nf = F.rows(); + std::vector<AlignedBox<double,3> > face_aabb(nf); + for (int i=0; i<nf; ++i) + { + RowVector3i f = F.row(i); + face_aabb[i].setEmpty(); + for (int j=0; j<3; ++j) + face_aabb[i].extend(V.row(f[j]).transpose()); + } + + int nt0 = tets.size(); + std::vector<int> keep_tet(nt0,1); + + AABBTree<double,3> mesh_tree; + mesh_tree.init(face_aabb); + KeepTetThreadData thread_data = { + .tree = &mesh_tree, + .pts = &V, + .faces = &F, + .tet_x = &verts, + .tets = &tets, + .keep_tet = &keep_tet + }; + TaskParallelSettings settings; + BLI_parallel_range_settings_defaults(&settings); + BLI_task_parallel_range(0, nt0, &thread_data, parallel_keep_tet, &settings); + + // Loop over tets and remove as needed. + // Mark referenced vertices to compute a mapping. + int tet_idx = 0; + for (std::vector<Vector4i>::iterator it = tets.begin(); it != tets.end(); ++tet_idx) + { + bool keep = keep_tet[tet_idx]; + if (keep) + { + refd_verts.emplace((*it)[0]); + refd_verts.emplace((*it)[1]); + refd_verts.emplace((*it)[2]); + refd_verts.emplace((*it)[3]); + ++it; + } + else { it = tets.erase(it); } + } + + } // end remove unnecessary tets + + // Copy data into matrices and remove unreferenced { - nv = verts.size(); - X->resize(nv,3); - for(int i=0; i<nv; ++i){ - for(int j=0; j<3; ++j){ - X->operator()(i,j) = verts[i][j]; + // Computing a mapping of vertices from old to new + std::unordered_map<int,int> vtx_old_to_new; + int ntv0 = verts.size(); // original num verts + int ntv1 = refd_verts.size(); // reduced num verts + X->resize(ntv1,3); + int vtx_count = 0; + for (int i=0; i<ntv0; ++i) + { + if (refd_verts.count(i)>0) + { + for(int j=0; j<3; ++j){ + X->operator()(vtx_count,j) = verts[i][j]; + } + vtx_old_to_new[i] = vtx_count; + vtx_count++; } } + + // Copy tets to matrix data and update vertices int nt = tets.size(); T->resize(nt,4); for(int i=0; i<nt; ++i){ for(int j=0; j<4; ++j){ - T->operator()(i,j) = tets[i][j]; + int old_idx = tets[i][j]; + BLI_assert(vtx_old_to_new.count(old_idx)>0); + T->operator()(i,j) = vtx_old_to_new[old_idx]; } } } + // Now compute the baryweighting for embedded vertices return compute_vtx_tet_mapping( &V, &vtx_to_tet, &barys, X, T); diff --git a/extern/softbody/src/admmpd_lattice.h b/extern/softbody/src/admmpd_lattice.h index 0190e8eaf40..41454a1650c 100644 --- a/extern/softbody/src/admmpd_lattice.h +++ b/extern/softbody/src/admmpd_lattice.h @@ -16,7 +16,8 @@ public: // Returns true on success bool generate( - const Eigen::MatrixXd &V, + const Eigen::MatrixXd &V, // embedded verts + const Eigen::MatrixXi &F, // embedded faces Eigen::MatrixXd *x, // lattice vertices, n x 3 Eigen::MatrixXi *tets); // lattice elements, m x 4 diff --git a/extern/softbody/src/admmpd_solver.cpp b/extern/softbody/src/admmpd_solver.cpp index 48f89a5c7ed..027ba921d07 100644 --- a/extern/softbody/src/admmpd_solver.cpp +++ b/extern/softbody/src/admmpd_solver.cpp @@ -13,6 +13,7 @@ #include <iostream> #include "BLI_task.h" // threading +#include "BLI_assert.h" // assert namespace admmpd { using namespace Eigen; @@ -29,6 +30,7 @@ bool Solver::init( const Options *options, Data *data) { + BLI_assert(data != NULL); if (!data || !options) throw std::runtime_error("init: data/options null"); diff --git a/extern/softbody/src/admmpd_solver.h b/extern/softbody/src/admmpd_solver.h index 6a066f5c05f..b10105eba84 100644 --- a/extern/softbody/src/admmpd_solver.h +++ b/extern/softbody/src/admmpd_solver.h @@ -34,6 +34,7 @@ struct Options { {} }; +// TODO template type for float/double struct Data { // Set from input Eigen::MatrixXi tets; // elements t x 4 diff --git a/intern/softbody/admmpd_api.cpp b/intern/softbody/admmpd_api.cpp index 41bde09ee5f..1895b973fef 100644 --- a/intern/softbody/admmpd_api.cpp +++ b/intern/softbody/admmpd_api.cpp @@ -112,7 +112,6 @@ static int admmpd_init_with_lattice( ADMMPDInterfaceData *iface, float *in_verts, unsigned int *in_faces, Eigen::MatrixXd *V, Eigen::MatrixXi *T) { - (void)(in_faces); int nv = iface->mesh_totverts; Eigen::MatrixXd in_V(nv,3); for (int i=0; i<nv; ++i) @@ -123,8 +122,18 @@ static int admmpd_init_with_lattice( } } + int nf = iface->mesh_totfaces; + Eigen::MatrixXi in_F(nf,3); + for (int i=0; i<nf; ++i) + { + for (int j=0; j<3; ++j) + { + in_F(i,j) = in_faces[i*3+j]; + } + } + iface->totverts = 0; - bool success = iface->data->lattice->generate(in_V,V,T); + bool success = iface->data->lattice->generate(in_V,in_F,V,T); if (success) { iface->totverts = V->rows(); |