[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