[Bf-blender-cvs] [e37b91f] strand_nodes: Tentative "stiffness" forces for resisting hair bending.
Lukas Tönne
noreply at git.blender.org
Tue Aug 9 17:26:53 CEST 2016
Commit: e37b91f41376f69cac32f378304a3544772dee9a
Author: Lukas Tönne
Date: Mon Aug 8 11:49:22 2016 +0200
Branches: strand_nodes
https://developer.blender.org/rBe37b91f41376f69cac32f378304a3544772dee9a
Tentative "stiffness" forces for resisting hair bending.
This is not really nice yet, but just serves as a test for internal forces.
===================================================================
M source/blender/physics/intern/strands.cpp
===================================================================
diff --git a/source/blender/physics/intern/strands.cpp b/source/blender/physics/intern/strands.cpp
index e23bfaa..c53749c 100644
--- a/source/blender/physics/intern/strands.cpp
+++ b/source/blender/physics/intern/strands.cpp
@@ -435,87 +435,121 @@ static void strand_solve(BMesh *UNUSED(bm), BMVert *root, float (*orig)[3], int
using Eigen::Vector3f;
using Eigen::Matrix3f;
- BMIter iter;
- BMVert *vert;
- int k;
-
/* compute unconstrained velocities by 1st order differencing */
- VectorX v(3 * numverts);
+ VectorX x(3 * numverts);
+ VectorX x0(3 * numverts);
+ VectorX v0(3 * numverts);
// VectorX L(numverts);
- BM_ITER_STRANDS_ELEM_INDEX(vert, &iter, root, BM_VERTS_OF_STRAND, k) {
- sub_v3_v3v3(&v.coeffRef(3*k), vert->co, orig[k]);
-// L.coeffRef(k) = BM_elem_float_data_named_get(&bm->vdata, vert, CD_PROP_FLT, CD_HAIR_SEGMENT_LENGTH);
+ {
+ BMIter iter;
+ BMVert *vert;
+ int k;
+ BM_ITER_STRANDS_ELEM_INDEX(vert, &iter, root, BM_VERTS_OF_STRAND, k) {
+ copy_v3_v3(&x.coeffRef(3*k), vert->co);
+ copy_v3_v3(&x0.coeffRef(3*k), orig[k]);
+ sub_v3_v3v3(&v0.coeffRef(3*k), vert->co, orig[k]);
+// L.coeffRef(k) = BM_elem_float_data_named_get(&bm->vdata, vert, CD_PROP_FLT, CD_HAIR_SEGMENT_LENGTH);
#ifdef DO_DEBUG
- BKE_sim_debug_data_add_line(orig[k], vert->co, 0,0,1, "hair solve", 3874, BLI_ghashutil_ptrhash(root), k);
+ BKE_sim_debug_data_add_line(orig[k], vert->co, 0,0,1, "hair solve", 3874, BLI_ghashutil_ptrhash(root), k);
#endif
+ }
}
/* "Mass" matrix can be understood as resistance to editing changes.
* XXX For now just using identity, in future more interesting things could be done here.
*/
-// MatrixX M = MatrixX::Identity(3 * numverts, 3 * numverts);
+ MatrixX M = MatrixX::Identity(3 * numverts, 3 * numverts);
/* XXX we actually only need the inverse of M, here just skip a pointless solve step */
MatrixX M_inv = MatrixX::Identity(3 * numverts, 3 * numverts);
/* Constraint matrix */
- int numjoints_root = 3; /* root velocity constraint */
- int numjoints_edges = numverts - 1; /* distance constraints */
- int numjoints = numjoints_edges + numjoints_root;
- MatrixX J = MatrixX::Zero(numjoints, 3 * numverts);
+ int numcons_roots = 3; /* root velocity constraint */
+ int numcons_edges = numverts - 1; /* distance constraints */
+ int numcons = numcons_edges + numcons_roots;
+ MatrixX J = MatrixX::Zero(numcons, 3 * numverts);
/* root velocity constraint */
J.block<3,3>(0, 0) = Matrix3f::Identity();
/* distance constraints */
- BMVert *vertprev = NULL;
- BM_ITER_STRANDS_ELEM_INDEX(vert, &iter, root, BM_VERTS_OF_STRAND, k) {
- if (k > 0) {
-// float target_length = L[k];
-// if (target_length > 0.0f) {
- Vector3 xa(vertprev->co);
- Vector3 xb(vert->co);
-// Vector3f j = (xb - xa) / target_length;
- Vector3f j = (xb - xa);
- j.normalize();
+ for (int i = 0; i < numcons_edges; ++i) {
+// float target_length = L[i+1];
+// if (target_length > 0.0f) {
+ int ka = i * 3;
+ int kb = (i+1) * 3;
+ Vector3f xa(x.block<3,1>(ka, 0));
+ Vector3f xb(x.block<3,1>(kb, 0));
+// Vector3f j = (xb - xa) / target_length;
+ Vector3f j = (xb - xa);
+ j.normalize();
#ifdef DO_DEBUG
- BKE_sim_debug_data_add_vector(vert->co, j.data(), 0,1,0, "hair solve", 3274, BLI_ghashutil_ptrhash(root), k);
+ BKE_sim_debug_data_add_vector(xb.data(), j.data(), 0,1,0, "hair solve", 3274, BLI_ghashutil_ptrhash(root), i);
#endif
-
- int i = k + 2; /* constraint index */
- J.block<1,3>(i, 3*(k-1)) = -j.transpose();
- J.block<1,3>(i, 3*(k) ) = j.transpose();
-// }
- }
-
- vertprev = vert;
+
+ int con = numcons_roots + i;
+ J.block<1,3>(con, ka) = -j.transpose();
+ J.block<1,3>(con, kb) = j.transpose();
+// }
}
/* A = J * M^-1 * J^T */
MatrixX A = J * M_inv * J.transpose();
- /* b = -(J * M^-1 * F_ext + c) = -(J * v0 + c) */
- VectorX c = VectorX::Zero(numjoints);
- c.block<3,1>(0, 0) = root_v;
- VectorX b = -(J * v + c);
+ /* force vector */
+ VectorX F = M * v0;
+ /* bending force: smoothes the hair */
+ float stiffness = 0.1;
+ for (int i = 1; i < numverts - 1; ++i) {
+ int ka = (i-1) * 3;
+ int kb = i * 3;
+ int kc = (i+1) * 3;
+ Vector3f xa(x.block<3,1>(ka, 0));
+ Vector3f xb(x.block<3,1>(kb, 0));
+ Vector3f xc(x.block<3,1>(kc, 0));
+ Vector3f target = xb + (xb - xa).normalized() * (xc - xb).norm();
+ Vector3f f = stiffness * (target - xc);
+ F.block<3,1>(kc, 0) += f;
+ F.block<3,1>(kb, 0) += -f;
+ }
+ /* constant constraint velocities */
+ VectorX c = VectorX::Zero(numcons);
+ c.block<3,1>(0, 0) = -root_v;
+ /* b = -(J * M^-1 * F + c) */
+ VectorX b = -(J * M_inv * F + c);
/* Lagrange multipliers are the solution to A * lambda = b */
VectorX lambda = A.ldlt().solve(b);
+ BLI_assert((A * lambda).isApprox(b, 0.001f));
/* calculate velocity correction by constraint forces */
- VectorX dv = M_inv * J.transpose() * lambda;
- v += dv;
+ VectorX v = M_inv * (J.transpose() * lambda + F);
+
+ /* corrected position update */
+ x = x0 + v;
#ifdef DO_DEBUG
- std::cout << "J = " << std::endl << J << std::endl;
- std::cout << "A = " << std::endl << A << std::endl;
- std::cout << "v = " << std::endl << v << std::endl;
- std::cout << "b = " << std::endl << b << std::endl;
- std::cout << "lambda = " << std::endl << lambda << std::endl;
- BM_ITER_STRANDS_ELEM_INDEX(vert, &iter, root, BM_VERTS_OF_STRAND, k) {
- BKE_sim_debug_data_add_vector(vert->co, &dv.coeff(3*k), 1,0,1, "hair solve", 3833, BLI_ghashutil_ptrhash(root), k);
- BKE_sim_debug_data_add_vector(orig[k], &v.coeff(3*k), 0,1,1, "hair solve", 3811, BLI_ghashutil_ptrhash(root), k);
+ {
+ std::cout << "J = " << std::endl << J << std::endl;
+ std::cout << "A = " << std::endl << A << std::endl;
+ std::cout << "v = " << std::endl << v << std::endl;
+ std::cout << "b = " << std::endl << b << std::endl;
+ std::cout << "lambda = " << std::endl << lambda << std::endl;
+ BMIter iter;
+ BMVert *vert;
+ int k;
+ VectorX dv = v - v0;
+ BM_ITER_STRANDS_ELEM_INDEX(vert, &iter, root, BM_VERTS_OF_STRAND, k) {
+ BKE_sim_debug_data_add_vector(vert->co, &dv.coeff(3*k), 1,0,1, "hair solve", 3833, BLI_ghashutil_ptrhash(root), k);
+ BKE_sim_debug_data_add_vector(orig[k], &v.coeff(3*k), 0,1,1, "hair solve", 3811, BLI_ghashutil_ptrhash(root), k);
+ BKE_sim_debug_data_add_vector(vert->co, &F.coeff(3*k), 1,0,0, "hair solve", 32789, BLI_ghashutil_ptrhash(root), k);
+ }
}
#endif
- BM_ITER_STRANDS_ELEM_INDEX(vert, &iter, root, BM_VERTS_OF_STRAND, k) {
- add_v3_v3v3(vert->co, orig[k], &v.coeff(3*k));
+ {
+ BMIter iter;
+ BMVert *vert;
+ int k;
+ BM_ITER_STRANDS_ELEM_INDEX(vert, &iter, root, BM_VERTS_OF_STRAND, k) {
+ copy_v3_v3(vert->co, &x.coeff(3*k));
+ }
}
}
More information about the Bf-blender-cvs
mailing list