[Bf-blender-cvs] [adc3d113f24] soc-2020-soft-body: improved API for less for-all-verts loops

over0219 noreply at git.blender.org
Tue Jun 16 01:30:38 CEST 2020


Commit: adc3d113f248ca036fcb8e530aba31edc24cb5f2
Author: over0219
Date:   Mon Jun 15 18:30:34 2020 -0500
Branches: soc-2020-soft-body
https://developer.blender.org/rBadc3d113f248ca036fcb8e530aba31edc24cb5f2

improved API for less for-all-verts loops

===================================================================

M	intern/softbody/admmpd_api.cpp
M	intern/softbody/admmpd_api.h
M	intern/tetgen/tetgen_api.cpp
M	source/blender/blenkernel/intern/softbody.c

===================================================================

diff --git a/intern/softbody/admmpd_api.cpp b/intern/softbody/admmpd_api.cpp
index 62dc1e7bba5..ade895a1971 100644
--- a/intern/softbody/admmpd_api.cpp
+++ b/intern/softbody/admmpd_api.cpp
@@ -29,6 +29,7 @@
 #include "DNA_meshdata_types.h" // MVert
 #include "BKE_mesh_remesh_voxel.h" // TetGen
 #include "BKE_mesh.h" // BKE_mesh_free
+#include "BKE_softbody.h" // BodyPoint
 #include "MEM_guardedalloc.h" // 
 
 #include <iostream>
@@ -38,55 +39,17 @@ struct ADMMPDInternalData {
   admmpd::Options *options;
   admmpd::Data *data;
 //  admmpd::Lattice *lattice;
+  int in_totverts; // number of input verts
 };
 
-
-void admmpd_alloc(ADMMPDInterfaceData *iface)
-{
-  if (iface==NULL)
-    return;
-
-  if (iface->in_verts != NULL)
-  {
-    MEM_freeN(iface->in_verts);
-    iface->in_verts = NULL;
-  }
-  if (iface->in_vel != NULL)
-  {
-    MEM_freeN(iface->in_vel);
-    iface->in_vel = NULL;
-  }
-  if (iface->in_faces != NULL)
-  {
-    MEM_freeN(iface->in_faces);
-    iface->in_faces = NULL;
-  }
-
-  iface->in_verts = (float *)MEM_mallocN(iface->in_totverts*3*sizeof(float), "admmpd_verts");
-  iface->in_vel = (float *)MEM_mallocN(iface->in_totverts*3*sizeof(float), "admmpd_vel");
-  iface->in_faces = (unsigned int *)MEM_mallocN(iface->in_totfaces*3*sizeof(unsigned int), "admmpd_faces");
-}
-
 void admmpd_dealloc(ADMMPDInterfaceData *iface)
 {
   if (iface==NULL)
     return;
 
-  iface->in_totverts = 0;
-  if (iface->in_verts != NULL)
-    MEM_freeN(iface->in_verts);
-  if (iface->in_vel != NULL)
-    MEM_freeN(iface->in_vel);
-
-  iface->in_totfaces = 0;
-  if (iface->in_faces != NULL)
-    MEM_freeN(iface->in_faces);
-
-  iface->out_totverts = 0;
-  if (iface->out_verts != NULL)
-    MEM_freeN(iface->out_verts);
-  if (iface->out_vel != NULL)
-    MEM_freeN(iface->out_vel);
+  iface->totverts = 0;
+  iface->mesh_totverts = 0;
+  iface->mesh_totfaces = 0;
 
   if (iface->data)
   {
@@ -97,52 +60,32 @@ void admmpd_dealloc(ADMMPDInterfaceData *iface)
     delete iface->data;
   }
 
-  iface->in_verts = NULL;
-  iface->in_vel = NULL;
-  iface->in_faces = NULL;
-  iface->out_verts = NULL;
-  iface->out_vel = NULL;
   iface->data = NULL;
 }
 
-int admmpd_init(ADMMPDInterfaceData *iface)
+int admmpd_init(ADMMPDInterfaceData *iface, float *in_verts, unsigned int *in_faces)
 {
+
   if (iface==NULL)
     return 0;
-  if (iface->in_verts==NULL || iface->in_vel==NULL || iface->in_faces==NULL)
+  if (in_verts==NULL || in_faces==NULL)
     return 0;
-  if (iface->in_totverts<=0 || iface->in_totfaces<=0)
+  if (iface->mesh_totverts<=0 || iface->mesh_totfaces<=0)
     return 0;
 
   // Generate tets
   TetGenRemeshData tg;
   init_tetgenremeshdata(&tg);
-  tg.in_verts = iface->in_verts;
-  tg.in_totverts = iface->in_totverts;
-  tg.in_faces = iface->in_faces;
-  tg.in_totfaces = iface->in_totfaces;
+  tg.in_verts = in_verts;
+  tg.in_totverts = iface->mesh_totverts;
+  tg.in_faces = in_faces;
+  tg.in_totfaces = iface->mesh_totfaces;
   bool success = tetgen_resmesh(&tg);
   if (!success || tg.out_tottets==0)
     return 0;
 
-  // Resize data
-  iface->out_totverts = tg.out_totverts;
-  if (iface->out_verts != NULL)
-  {
-    MEM_freeN(iface->out_verts);
-    iface->out_verts = NULL;
-  }
-  if (iface->out_vel != NULL)
-  {
-    MEM_freeN(iface->out_vel);
-    iface->out_vel = NULL;
-  }
-  iface->out_verts = (float *)MEM_callocN(
-      iface->out_totverts*3*sizeof(float), "ADMMPD_out_verts");
-  iface->out_vel = (float *)MEM_callocN(
-      iface->out_totverts*3*sizeof(float), "ADMMPD_out_vel");
-
   // Create initializer for ADMMPD
+  iface->totverts = tg.out_totverts;
   int nv = tg.out_totverts;
   int nt = tg.out_tottets;
   Eigen::MatrixXd V(nv,3);
@@ -153,8 +96,6 @@ int admmpd_init(ADMMPDInterfaceData *iface)
     for (int j=0; j<3; ++j)
     {
       V(i,j) = tg.out_verts[i*3+j];
-      iface->out_verts[i*3+j] = tg.out_verts[i*3+j];
-      iface->out_vel[i*3+j] = 0;
     }
   }
   T.setZero();
@@ -191,60 +132,63 @@ int admmpd_init(ADMMPDInterfaceData *iface)
   return int(init_success);
 }
 
-void admmpd_solve(ADMMPDInterfaceData *iface)
+void admmpd_copy_from_bodypoint(ADMMPDInterfaceData *iface, const BodyPoint *pts)
 {
-  if (iface == NULL)
+  if (iface == NULL || pts == NULL)
     return;
 
-  // Whatever is in out_verts and out_vel needs
-  // to be mapped to internal data, as it's used as input
-  // when reading from cached data.
-  int nv = iface->out_totverts;
-  for (int i=0; i<nv; ++i)
+  for (int i=0; i<iface->totverts; ++i)
   {
-    for (int j=0; j<3; ++j)
+    const BodyPoint *pt = &pts[i];
+    for(int j=0; j<3; ++j)
     {
-      iface->data->data->x(i,j) = iface->out_verts[i*3+j];
-      iface->data->data->v(i,j) = iface->out_vel[i*3+j];
+      iface->data->data->x(i,j)=pt->pos[j];
+      iface->data->data->v(i,j)=pt->vec[j];
     }
   }
+}
 
-  try
+void admmpd_copy_to_bodypoint_and_object(ADMMPDInterfaceData *iface, BodyPoint *pts, float (*vertexCos)[3])
+{
+  if (iface == NULL)
+    return;
+
+  for (int i=0; i<iface->totverts; ++i)
   {
-    admmpd::Solver().solve(iface->data->options,iface->data->data);
-    for (int i=0; i<iface->data->data->x.rows(); ++i)
+    if (pts != NULL)
     {
-      for (int j=0; j<3; ++j)
+      BodyPoint *pt = &pts[i];
+      for(int j=0; j<3; ++j)
       {
-        iface->out_verts[i*3+j] = iface->data->data->x(i,j);
-        iface->out_vel[i*3+j] = iface->data->data->v(i,j);
+        pt->pos[j] = iface->data->data->x(i,j);
+        pt->vec[j] = iface->data->data->v(i,j);
       }
     }
-  }
-  catch(const std::exception &e)
-  {
-    printf("**ADMMPD Error on solve: %s\n", e.what());
+
+    // TODO eventually replace with mapping. For now
+    // we assume TetGen, which the first N vertices are
+    // mapped one-to-one.
+    if (vertexCos != NULL && i<iface->mesh_totverts)
+    {
+      vertexCos[i][0] = iface->data->data->x(i,0);
+      vertexCos[i][1] = iface->data->data->x(i,1);
+      vertexCos[i][2] = iface->data->data->x(i,2);
+    }
   }
 }
 
-void admmpd_get_vertices(ADMMPDInterfaceData *iface, float (*vertexCos)[3], int numVerts)
+void admmpd_solve(ADMMPDInterfaceData *iface)
 {
+  
   if (iface == NULL)
     return;
 
-  if (numVerts != iface->in_totverts || numVerts > iface->out_totverts)
+  try
   {
-    printf("**ADMMPD TODO: PROPER VERTEX MAPPINGS\n");
-    return;
+    admmpd::Solver().solve(iface->data->options,iface->data->data);
   }
-  // TODO double check this, but I believe the first n verts
-  // created by tetgen are the same as the input. I hope. We'll find out I guess.
-  // If not, this function will be a placeholder for the mapping that
-  // will have to occur.
-  for (int i=0; i<numVerts; ++i)
+  catch(const std::exception &e)
   {
-    vertexCos[i][0] = iface->out_verts[i*3+0];
-    vertexCos[i][1] = iface->out_verts[i*3+1];
-    vertexCos[i][2] = iface->out_verts[i*3+2];
+    printf("**ADMMPD Error on solve: %s\n", e.what());
   }
 }
\ No newline at end of file
diff --git a/intern/softbody/admmpd_api.h b/intern/softbody/admmpd_api.h
index f90f75a0405..36cbe684e9e 100644
--- a/intern/softbody/admmpd_api.h
+++ b/intern/softbody/admmpd_api.h
@@ -29,40 +29,40 @@ extern "C" {
 #endif
 
 typedef struct ADMMPDInterfaceData {
-    float *in_verts;
-    float *in_vel;
-    unsigned int *in_faces;
-    int in_totfaces;
-    int in_totverts;
-    // Num output verts might be different than num input verts.
+    // totverts is usually different than mesh_totverts.
     // This is due to the lattice/tetmesh that is generated
     // in init. You can use them as input if reading from cache,
     // as they will be copied to internal solver data before admmpd_solve.
-    float *out_verts;
-    float *out_vel;
-    int out_totverts;
+    int totverts; // number of deformable verts (output)
+    int mesh_totverts; // number of surface mesh vertices (input)
+    int mesh_totfaces; // number of surface mesh faces (input)
     // Solver data used internally
     struct ADMMPDInternalData *data;
 } ADMMPDInterfaceData;
 
-// Allocates ADMMPDInterfaceData, using in_totfaces and in_totverts.
-// Does not allocate solver data, which is created on admmpd_init
-void admmpd_alloc(ADMMPDInterfaceData*);
+// SoftBody bodypoint (contains pos,vec)
+typedef struct BodyPoint BodyPoint;
 
 // Clears all solver data and ADMMPDInterfaceData
 void admmpd_dealloc(ADMMPDInterfaceData*);
 
 // Initializes solver and allocates internal data
-int admmpd_init(ADMMPDInterfaceData*);
+int admmpd_init(ADMMPDInterfaceData*, float *in_verts, unsigned int *in_faces);
+
+// Copies BodyPoint data (from SoftBody)
+// to internal vertex position and velocity
+void admmpd_copy_from_bodypoint(ADMMPDInterfaceData*, const BodyPoint *pts);
+
+// Copies internal vertex position and velocity data
+// to BodyPoints (from SoftBody) AND surface mesh vertices.
+// If pts or vertexCos is null, its skipped
+void admmpd_copy_to_bodypoint_and_object(ADMMPDInterfaceData*, BodyPoint *pts, float (*vertexCos)[3]);
 
 // Copies out_verts and out_verts to internal data
 // Performs solve over the time step
 // Copies internal data to out_verts and out_vel
 void admmpd_solve(ADMMPDInterfaceData*);
 
-// Copies ADMMPDInterfaceData::out_ to vertexCos
-void admmpd_get_vertices(ADMMPDInterfaceData*, float (*vertexCos)[3], int numVerts); 
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/intern/tetgen/tetgen_api.cpp b/intern/tetgen/tetgen_api.cpp
index 50b8201caac..33115411d82 100644
--- a/intern/tetgen/tetgen_api.cpp
+++ b/intern/tetgen/tetgen_api.cpp
@@ -101,14 +101,14 @@ static void make_tetgenio(
 bool tetgen_resmesh(TetGenRemeshData *tg)
 {
 //	float maxvol = compute_maxvol(tg->in_verts, tg->in_faces, tg->in_totfaces);
-//    float quality = 1.4;
+    float quality = 1.4;
 
 	// Set up the switches
 	std::stringstream switches;
 //	switches << "Q"; // quiet
 //    switches << "a" << maxvol;
-//	if (quality>0)
-//        switches << "q" << quality;
+	if (quality>0)
+        switches << "q" << quality;
 
 
     tetgenio in;
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 026acd06b04..29e37c67a9c 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/in

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list