[Bf-blender-cvs] [9ba5c8b90aa] soc-2020-soft-body: first commit. interfaced to very basic admmpd solver, but requires restart to begin sim as caching not working for velocity. lattice is simply a packed 5-tet cube around mesh.
over0219
noreply at git.blender.org
Wed Jun 3 06:26:45 CEST 2020
Commit: 9ba5c8b90aa6245c569f7e66b0cd472beb59b5a5
Author: over0219
Date: Tue Jun 2 19:53:14 2020 -0500
Branches: soc-2020-soft-body
https://developer.blender.org/rB9ba5c8b90aa6245c569f7e66b0cd472beb59b5a5
first commit. interfaced to very basic admmpd solver, but requires restart to begin sim as caching not working for velocity. lattice is simply a packed 5-tet cube around mesh.
===================================================================
M extern/CMakeLists.txt
A extern/softbody/CMakeLists.txt
A extern/softbody/README.md
A extern/softbody/src/admmpd_energy.cpp
A extern/softbody/src/admmpd_energy.h
A extern/softbody/src/admmpd_lattice.cpp
A extern/softbody/src/admmpd_lattice.h
A extern/softbody/src/admmpd_math.cpp
A extern/softbody/src/admmpd_math.h
A extern/softbody/src/admmpd_solver.cpp
A extern/softbody/src/admmpd_solver.h
M intern/CMakeLists.txt
A intern/softbody/CMakeLists.txt
A intern/softbody/admmpd_api.cpp
A intern/softbody/admmpd_api.h
M release/datafiles/locale
M release/scripts/addons
M source/blender/blenkernel/CMakeLists.txt
M source/blender/blenkernel/intern/softbody.c
M source/blender/makesdna/DNA_object_force_types.h
M source/blender/modifiers/intern/MOD_softbody.c
M source/tools
===================================================================
diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt
index 235c2fa931a..7d4023cf52a 100644
--- a/extern/CMakeLists.txt
+++ b/extern/CMakeLists.txt
@@ -34,6 +34,7 @@ endif()
add_subdirectory(rangetree)
add_subdirectory(wcwidth)
+add_subdirectory(softbody)
if(WITH_BULLET)
if(NOT WITH_SYSTEM_BULLET)
diff --git a/extern/softbody/CMakeLists.txt b/extern/softbody/CMakeLists.txt
new file mode 100644
index 00000000000..08a36882f28
--- /dev/null
+++ b/extern/softbody/CMakeLists.txt
@@ -0,0 +1,43 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ src
+)
+
+set(INC_SYS
+ ${EIGEN3_INCLUDE_DIRS}
+)
+
+set(SRC
+ src/admmpd_math.h
+ src/admmpd_math.cpp
+ src/admmpd_energy.h
+ src/admmpd_energy.cpp
+ src/admmpd_lattice.h
+ src/admmpd_lattice.cpp
+ src/admmpd_solver.h
+ src/admmpd_solver.cpp
+)
+
+set(LIB
+)
+
+blender_add_lib(extern_admmpd "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/extern/softbody/README.md b/extern/softbody/README.md
new file mode 100644
index 00000000000..78144e7b666
--- /dev/null
+++ b/extern/softbody/README.md
@@ -0,0 +1,3 @@
+# SoftBody #
+
+
diff --git a/extern/softbody/src/admmpd_energy.cpp b/extern/softbody/src/admmpd_energy.cpp
new file mode 100644
index 00000000000..978fd565aa4
--- /dev/null
+++ b/extern/softbody/src/admmpd_energy.cpp
@@ -0,0 +1,112 @@
+
+
+
+#include "admmpd_energy.h"
+
+namespace admmpd {
+using namespace Eigen;
+
+Lame::Lame() : m_model(0)
+{
+ set_from_youngs_poisson(10000000,0.299);
+}
+
+void Lame::set_from_youngs_poisson(double youngs, double poisson)
+{
+ m_mu = youngs/(2.0*(1.0+poisson));
+ m_lambda = youngs*poisson/((1.0+poisson)*(1.0-2.0*poisson));
+ m_bulk_mod = m_lambda + (2.0/3.0)*m_mu;
+}
+
+void EnergyTerm::signed_svd(
+ const Eigen::Matrix<double,3,3>& A,
+ Eigen::Matrix<double,3,3> &U,
+ Eigen::Matrix<double,3,1> &S,
+ Eigen::Matrix<double,3,3> &V)
+{
+ JacobiSVD<Matrix3d> svd(A, ComputeFullU | ComputeFullV);
+ S = svd.singularValues();
+ U = svd.matrixU();
+ V = svd.matrixV();
+ Matrix3d J = Matrix3d::Identity();
+ J(2,2) = -1.0;
+ if( U.determinant() < 0.0 )
+ {
+ U = U * J;
+ S[2] = -S[2];
+ }
+ if( V.determinant() < 0.0 )
+ {
+ Matrix3d Vt = V.transpose();
+ Vt = J * Vt;
+ V = Vt.transpose();
+ S[2] = -S[2];
+ }
+}
+
+void EnergyTerm::update(
+ int index,
+ const Lame &lame,
+ double rest_volume,
+ double weight,
+ const Eigen::MatrixXd *x,
+ const Eigen::MatrixXd *Dx,
+ Eigen::MatrixXd *z,
+ Eigen::MatrixXd *u)
+{
+ Matrix3d Dix = Dx->block<3,3>(index,0);
+ Matrix3d ui = u->block<3,3>(index,0);
+ Matrix3d zi = Dix + ui;
+
+ Matrix3d U, V;
+ Vector3d S;
+ signed_svd(zi, U, S, V);
+ S = Vector3d::Ones();
+
+ Matrix3d p = U * S.asDiagonal() * V.transpose();
+ double k = lame.m_bulk_mod;
+ double kv = k * rest_volume;
+ double w2 = weight*weight;
+ zi = (kv*p + w2*zi) / (w2 + kv);
+ ui += (Dix - zi);
+
+ u->block<3,3>(index,0) = ui;
+ z->block<3,3>(index,0) = zi;
+
+} // end EnergyTerm::update
+
+int EnergyTerm::init_tet(
+ int index,
+ const Lame &lame,
+ const Eigen::Matrix<int,1,4> &prim,
+ const Eigen::MatrixXd *x,
+ double &volume,
+ double &weight,
+ std::vector< Eigen::Triplet<double> > &triplets )
+{
+ Matrix<double,3,3> edges;
+ edges.col(0) = x->row(prim[1]) - x->row(prim[0]);
+ edges.col(1) = x->row(prim[2]) - x->row(prim[0]);
+ edges.col(2) = x->row(prim[3]) - x->row(prim[0]);
+ Matrix<double,3,3> edges_inv = edges.inverse();
+ volume = edges.determinant() / 6.0f;
+ if( volume < 0 )
+ throw std::runtime_error("**Solver::energy_init: Inverted initial tet");
+ double k = lame.m_bulk_mod;
+ weight = std::sqrt(k*volume);
+ Matrix<double,4,3> S = Matrix<double,4,3>::Zero();
+ S(0,0) = -1; S(0,1) = -1; S(0,2) = -1;
+ S(1,0) = 1; S(2,1) = 1; S(3,2) = 1;
+ Eigen::Matrix<double,4,3> D = S * edges_inv;
+ Eigen::Matrix<double,3,4> Dt = D.transpose();
+ int rows[3] = { index+0, index+1, index+2 };
+ int cols[4] = { prim[0], prim[1], prim[2], prim[3] };
+ for( int r=0; r<3; ++r ){
+ for( int c=0; c<4; ++c ){
+ triplets.emplace_back(rows[r], cols[c], Dt(r,c));
+ }
+ }
+ return 3;
+}
+
+} // end namespace mcl
diff --git a/extern/softbody/src/admmpd_energy.h b/extern/softbody/src/admmpd_energy.h
new file mode 100644
index 00000000000..4245c9cff9c
--- /dev/null
+++ b/extern/softbody/src/admmpd_energy.h
@@ -0,0 +1,61 @@
+
+
+
+#ifndef _ADMMPD_ENERGY_H
+#define _ADMMPD_ENERGY_H 1
+
+#include <Eigen/Sparse>
+#include <Eigen/Geometry>
+#include <vector>
+
+namespace admmpd {
+
+class Lame {
+public:
+ int m_model;
+ double m_mu;
+ double m_lambda;
+ double m_bulk_mod;
+ void set_from_youngs_poisson(double youngs, double poisson);
+ Lame();
+};
+
+class EnergyTerm {
+public:
+
+ void signed_svd(
+ const Eigen::Matrix<double,3,3> &A,
+ Eigen::Matrix<double,3,3> &U,
+ Eigen::Matrix<double,3,1> &S,
+ Eigen::Matrix<double,3,3> &V);
+
+ // Updates the z and u variables for an element energy.
+ void update(
+ int index,
+ const Lame &lame,
+ double rest_volume,
+ double weight,
+ const Eigen::MatrixXd *x,
+ const Eigen::MatrixXd *Dx,
+ Eigen::MatrixXd *z,
+ Eigen::MatrixXd *u);
+
+ // Initializes tet energy, returns num rows for D
+ int init_tet(
+ int index,
+ const Lame &lame,
+ const Eigen::RowVector4i &prim,
+ const Eigen::MatrixXd *x,
+ double &volume,
+ double &weight,
+ std::vector< Eigen::Triplet<double> > &triplets);
+
+};
+
+} // end namespace admmpd
+
+#endif // _ADMMPD_ENERGY_H
+
+
+
+
diff --git a/extern/softbody/src/admmpd_lattice.cpp b/extern/softbody/src/admmpd_lattice.cpp
new file mode 100644
index 00000000000..4323f8fce33
--- /dev/null
+++ b/extern/softbody/src/admmpd_lattice.cpp
@@ -0,0 +1,229 @@
+
+
+
+#include "admmpd_lattice.h"
+#include "admmpd_math.h"
+
+//#include "vdb.h"
+
+namespace admmpd {
+using namespace Eigen;
+
+// We store our deformable data in column major to make
+// matrix-vector mults and solves faster, but we want
+// to map raw data as row major.
+inline void map_to_x3d(const std::vector<Vector3d> &x_vec, Eigen::MatrixXd *x)
+{
+ int nx = x_vec.size();
+ if (nx==0)
+ {
+ *x = MatrixXd();
+ return;
+ }
+
+ x->resize(nx,3);
+ for (int i=0; i<nx; ++i)
+ {
+ x->operator()(i,0) = x_vec[i][0];
+ x->operator()(i,1) = x_vec[i][1];
+ x->operator()(i,2) = x_vec[i][2];
+ }
+}
+
+inline void map_to_x4i(const std::vector<Vector4i> &x_vec, Eigen::MatrixXi *x)
+{
+ int nx = x_vec.size();
+ if (nx==0)
+ {
+ *x = MatrixXi();
+ return;
+ }
+
+ x->resize(nx,4);
+ for (int i=0; i<nx; ++i)
+ {
+ x->operator()(i,0) = x_vec[i][0];
+ x->operator()(i,1) = x_vec[i][1];
+ x->operator()(i,2) = x_vec[i][2];
+ x->operator()(i,3) = x_vec[i][3];
+ }
+}
+
+bool Lattice::generate(
+ const Eigen::MatrixXd &V,
+ Eigen::MatrixXd *x, // lattice vertices, n x 3
+ Eigen::MatrixXi *tets) // lattice elements, m x 4
+{
+ // All vertices enclosed in 5 tets!
+ // Will generate actual lattice in the future.
+ AlignedBox<double,3> box;
+ vtx = V;
+ int nv = vtx.rows();
+ for (int i=0; i<nv; ++i)
+ {
+ Vector3d v = vtx.row(i);
+ box.extend(v);
+ }
+ box.extend(box.min() - Vector3d::Ones() * 1e-12);
+ box.extend(box.max() + Vector3d::Ones() * 1e-12);
+
+ std::vector<Vector3d> x_vec;
+ std::vector<Vector4i> t_vec;
+ create_packed_tets(box.min(),box.max(),x_vec,t_vec);
+
+ // Copy vector data to output
+ map_to_x3d(x_vec, x);
+ map_to_x4i(t_vec, tets);
+ return compute_vtx_tet_mapping(&vtx, &vtx_to_tet, &barys, x, tets);
+
+} // end gen lattice
+
+//
+// Original source (BSD-2):
+// github.com/mattoverby/mclscene/blob/master/include/MCL/EmbeddedMesh.hpp
+//
+void Lattice::create_packed_tets(
+ const Eigen::Vector3d &min,
+ const Eigen::Vector3d &max,
+ std::vector<Vector3d> &verts,
+ std::vector<Vector4i> &tets )
+{
+
+ // Top plane, clockwise looking down
+ Vector3d a = max;
+ Vector3d b( min[0], max[1], max[2] );
+ Vector3d c( min[0], max[1], min[2] );
+ Vector3d d( max[0], max[1], min[2] );
+
+ // Bottom plan, clockwise looking down
+ Vector3d e( max[0], min[1], max[2] );
+ Vector3d f( min[0], min[1], max[2] );
+ Vector3d g( min[0], min[1], min[2] );
+ Vector3d h( max[0], min[1], min[2] );
+
+ // Add the verts
+ int nv = verts.size();
+ verts.emplace_back( a ); // 0
+ verts.emplace_back( b ); // 1
+ verts.emplace_back( c ); // 2
+ verts.emplace_back( d ); // 3
+ verts.emplace_back( e ); // 4
+ verts.emplace_back( f ); // 5
+ verts.emplace_back( g ); // 6
+ verts.emplace_back( h ); // 7
+
+ // Pack 5 tets into the cube
+ Vector4i t0( 0, 5, 7, 4 );
+ Vector4i t1( 5, 7, 2, 0 );
+ Vector4i t2( 5, 0, 2, 1 );
+ Vector4i t3( 7, 2, 0, 3 );
+ Vector4i t4( 5, 2, 7, 6 );
+ Vector4i offset(nv,nv,nv,nv);
+
+ // Add the tets
+ tets.emplace_back( t0+offset );
+ tets.emplace_back( t1+offset );
+ tets.emplace_back( t2+offset );
+ tets.emplace_back( t3+offset );
+ tets.emplace_back( t4+offset );
+
+//vdb_point(a[0],a[1],a[2]);
+//vdb_point(b[0],b[1],b[2]);
+//vdb_point(c[0],c[1],c[2]);
+//vdb_point(d[0],d[1],d[2]);
+//vdb_point(e[0],e[1],e[2]);
+//vdb_point(f[0],f[1],f[2]);
+//vdb_point(g[0],g[1],g[2]);
+//vdb_point(h[0],h[1],h[2]);
+//vdb_line(float x0, float y0, float z0,
+// float x1, float y1, float z1);
+
+} // end create packed tets
+
+bool Lattice::compute_vtx_tet_mapping(
+ const Eigen::MatrixXd *vtx_, // embedded vertices, p x 3
+ Eigen::VectorXi *vtx_to_tet_, // what tet vtx is embedded in, p x 1
+ Eigen::MatrixXd *barys_, // barycoords of the embedding, p x 4
+ const Eigen::MatrixXd *x_
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list