[Bf-blender-cvs] [7561037f6ea] soc-2020-soft-body: fixed bug in ldlt
mattoverby
noreply at git.blender.org
Tue Aug 11 23:24:55 CEST 2020
Commit: 7561037f6ea78e3c4b1c792a94f9b7e577b625aa
Author: mattoverby
Date: Tue Aug 11 16:24:51 2020 -0500
Branches: soc-2020-soft-body
https://developer.blender.org/rB7561037f6ea78e3c4b1c792a94f9b7e577b625aa
fixed bug in ldlt
===================================================================
M extern/softbody/src/admmpd_linsolve.cpp
M extern/softbody/src/admmpd_mesh.cpp
M intern/softbody/admmpd_api.cpp
M source/blender/blenkernel/intern/softbody.c
===================================================================
diff --git a/extern/softbody/src/admmpd_linsolve.cpp b/extern/softbody/src/admmpd_linsolve.cpp
index bda806b2e2a..87e10cc357b 100644
--- a/extern/softbody/src/admmpd_linsolve.cpp
+++ b/extern/softbody/src/admmpd_linsolve.cpp
@@ -29,8 +29,9 @@ void LDLT::init_solve(
{
(void)(collision);
int nx = data->x.rows();
- if (nx==0)
- throw_err("init_solve","no vertices");
+ if (nx==0) { throw_err("init_solve","no vertices"); }
+ if (!mesh) { throw_err("init_solve","no mesh"); }
+ if (!options) { throw_err("init_solve","no options"); }
// Get the P matrix
std::set<int> pin_inds;
@@ -47,7 +48,7 @@ void LDLT::init_solve(
// Compute P
data->ls.last_pk = pk;
- int np = q_coeffs.size();
+ int np = q_coeffs.size()/3;
SparseMatrix<double> P;
MatrixXd q;
if (data->ls.Ptq.rows() != nx)
@@ -74,17 +75,19 @@ void LDLT::init_solve(
data->ls.Ptq = pk * P.transpose() * q;
}
+ if (!data->ls.ldlt_A_PtP)
+ data->ls.ldlt_A_PtP = std::make_unique<Cholesky>();
+
+std::cout << "factoring" << std::endl;
+
// Compute A + P'P and factorize:
// 1) A not computed
// 2) P has changed
// 3) factorization not set
- if ( !data->ls.ldlt_A_PtP ||
+ if ( data->ls.ldlt_A_PtP->info() != Eigen::Success ||
data->ls.A_PtP.nonZeros()==0 ||
new_P)
{
- if (!data->ls.ldlt_A_PtP)
- data->ls.ldlt_A_PtP = std::make_unique<Cholesky>();
-
data->ls.A_PtP = SparseMatrix<double>(data->A) + pk * P.transpose()*P;
data->ls.ldlt_A_PtP->compute(data->ls.A_PtP);
if(data->ls.ldlt_A_PtP->info() != Eigen::Success)
diff --git a/extern/softbody/src/admmpd_mesh.cpp b/extern/softbody/src/admmpd_mesh.cpp
index e4f945c266d..52d8e2d0cda 100644
--- a/extern/softbody/src/admmpd_mesh.cpp
+++ b/extern/softbody/src/admmpd_mesh.cpp
@@ -408,25 +408,32 @@ bool EmbeddedMesh::linearize_pins(
const Vector3d &qi = emb_pin_pos.at(emb_idx);
const double &ki = it_k->second;
+ if (ki <= 0.0)
+ continue;
+
int tet_idx = emb_v_to_tet[emb_idx];
RowVector4d bary = emb_barys.row(emb_idx);
RowVector4i tet = lat_T.row(tet_idx);
+ int p_idx = q.size()/3;
for (int i=0; i<3; ++i)
{
- int p_idx = q.size();
q.emplace_back(qi[i]*ki);
- if (replicate)
- {
- for (int j=0; j<4; ++j)
- trips.emplace_back(p_idx, tet[j]*3+i, bary[j]*ki);
- }
- else if (i==0)
+ }
+
+ if (replicate)
+ {
+ for (int i=0; i<3; ++i)
{
for (int j=0; j<4; ++j)
- trips.emplace_back(p_idx/3, tet[j], bary[j]*ki);
+ trips.emplace_back(p_idx*3+i, tet[j]*3+i, bary[j]*ki);
}
}
+ else
+ {
+ for (int j=0; j<4; ++j)
+ trips.emplace_back(p_idx, tet[j], bary[j]*ki);
+ }
}
bool has_P_updated = P_updated;
@@ -576,6 +583,10 @@ bool TetMesh::linearize_pins(
pin_inds.emplace(idx);
const Vector3d &qi = pin_pos.at(idx);
const double &ki = it_k->second;
+
+ if (ki <= 0.0)
+ continue;
+
for (int i=0; i<3; ++i)
{
int p_idx = q.size();
@@ -699,18 +710,18 @@ bool TriangleMesh::linearize_pins(
pin_inds.emplace(idx);
const Vector3d &qi = pin_pos.at(idx);
const double &ki = it_k->second;
+ int p_idx = q.size()/3;
for (int i=0; i<3; ++i)
- {
- int p_idx = q.size();
q.emplace_back(qi[i]*ki);
- if (replicate)
- {
- trips.emplace_back(p_idx, idx*3+i, ki);
- }
- else if (i==0)
- {
- trips.emplace_back(p_idx/3, idx, ki);
- }
+
+ if (replicate)
+ {
+ for (int i=0; i<3; ++i)
+ trips.emplace_back(p_idx*3+i, idx*3+i, ki);
+ }
+ else
+ {
+ trips.emplace_back(p_idx, idx, ki);
}
}
diff --git a/intern/softbody/admmpd_api.cpp b/intern/softbody/admmpd_api.cpp
index 7bfb8453f36..d4cae9b18fd 100644
--- a/intern/softbody/admmpd_api.cpp
+++ b/intern/softbody/admmpd_api.cpp
@@ -310,27 +310,20 @@ int admmpd_mesh_needs_update(ADMMPDInterfaceData *iface, Object *ob)
if (!iface) { return 0; }
if (!ob) { return 0; }
if (!ob->soft) { return 0; }
+ if (!ob->data) { return 0; }
if (!iface->idata) { return 1; }
if (!iface->idata->mesh) { return 1; }
+ Mesh *mesh = (Mesh*)ob->data;
+ if (!mesh) { return 0; }
+
// Mode or topology change?
int mode = ob->soft->admmpd_init_mode;
int mesh_type = iface->idata->mesh->type();
if (mode != mesh_type) { return 1; }
-
- switch (mode)
- {
- default:
- case MESHTYPE_EMBEDDED:
- case MESHTYPE_TET: {
- int nv = iface->idata->mesh->rest_prim_verts()->rows();
- if (nv != ob->soft->totpoint) { return 1; }
- } break;
- case MESHTYPE_TRIANGLE: {
- int nv = iface->idata->mesh->rest_facet_verts()->rows();
- if (nv != ob->soft->totpoint) { return 1; }
- } break;
- }
+ if (!iface->idata->mesh->rest_facet_verts()) { return 1; }
+ int nx = iface->idata->mesh->rest_facet_verts()->rows();
+ if (nx != mesh->totvert) { return 1; }
return 0;
}
@@ -508,15 +501,9 @@ void admmpd_copy_to_object(ADMMPDInterfaceData *iface, Object *ob, float (*verte
if (ob && ob->soft)
{
- int np = std::min(ob->soft->totpoint, nx);
SoftBody *sb = ob->soft;
- if (!sb->bpoint || nx != np)
+ if (!sb->bpoint)
{
- // If we have a bpoint but it's the wrong size
- if (ob->soft->bpoint && nx != np)
- MEM_freeN(sb->bpoint);
-
- // Create bpoint if we don't have one
if (!ob->soft->bpoint)
sb->bpoint = (BodyPoint*)MEM_callocN(nx*sizeof(BodyPoint), "ADMMPD_bpoint");
@@ -525,7 +512,8 @@ void admmpd_copy_to_object(ADMMPDInterfaceData *iface, Object *ob, float (*verte
}
// Copy internal data to BodyPoint
- for (int i=0; i<nx; ++i)
+ int np = std::min(ob->soft->totpoint, nx);
+ for (int i=0; i<np; ++i)
{
BodyPoint *pt = &ob->soft->bpoint[i];
for(int j=0; j<3; ++j)
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index affd940f368..75fbea9c958 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -3647,13 +3647,22 @@ static void sbObjectStep_admmpd(
float (*vertexCos)[3],
int numVerts)
{
+ if (!ob)
+ return;
+
if (ob->type != OB_MESH) {
CLOG_ERROR(&LOG, "ADMM-PD only works with mesh object types");
return;
}
Mesh *me = ob->data;
+ if (!me)
+ return;
+
SoftBody *sb = ob->soft;
+ if (!sb)
+ return;
+
if (!sb->admmpd) {
CLOG_ERROR(&LOG, "No ADMM-PD data");
return;
@@ -3698,13 +3707,6 @@ static void sbObjectStep_admmpd(
return;
}
else {
- // When a paramter is changed the SoftBody object
- // is deleted and a new one is created (CoW). Calling
- // copy to object (with NULL vertexCos) makes sure
- // the BodyPoint data has been properly allocated,
- // but skips updating vertexCos.
- admmpd_copy_to_object(sb->admmpd,ob,NULL);
-
// Do we need to initialize the ADMM-PD mesh?
// a) Has never been initialized.
// b) The mesh topology has changed.
@@ -3719,8 +3721,9 @@ static void sbObjectStep_admmpd(
// Do we need to initialize the ADMM-PD solver?
// a) Has never been initialized
// b) Some settings require re-initialization
+ // c) The mesh has changed
int init_solver = 0;
- if (admmpd_solver_needs_update(sb->admmpd, scene, ob)) {
+ if (init_mesh || admmpd_solver_needs_update(sb->admmpd, scene, ob)) {
init_solver = admmpd_update_solver(sb->admmpd, scene, ob, vertexCos);
if (!init_solver) {
CLOG_ERROR(&LOG, "%s", sb->admmpd->last_error);
More information about the Bf-blender-cvs
mailing list