[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