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);

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to