Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorover0219 <over0219@umn.edu>2020-06-16 02:30:34 +0300
committerover0219 <over0219@umn.edu>2020-06-16 02:30:34 +0300
commitadc3d113f248ca036fcb8e530aba31edc24cb5f2 (patch)
treeca23ecd99bf4984cab09ece462020343c5fae683
parent4ff3bb13e35fb190c8510bf4daa7ded0a0c3b777 (diff)
improved API for less for-all-verts loops
-rw-r--r--intern/softbody/admmpd_api.cpp154
-rw-r--r--intern/softbody/admmpd_api.h32
-rw-r--r--intern/tetgen/tetgen_api.cpp6
-rw-r--r--source/blender/blenkernel/intern/softbody.c152
4 files changed, 135 insertions, 209 deletions
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/intern/softbody.c
@@ -856,14 +856,6 @@ static void renew_softbody(Scene *scene, Object *ob, int totpoint, int totspring
sb->bspring = MEM_mallocN(totspring * sizeof(BodySpring), "bodyspring");
}
- if (ob->type == OB_MESH)
- {
- const Mesh *me = ob->data;
- sb->admmpd->in_totfaces = poly_to_tri_count(me->totpoly, me->totloop);
- sb->admmpd->in_totverts = me->totvert;
- admmpd_alloc(sb->admmpd);
- }
-
/* initialize BodyPoint array */
for (i = 0; i < totpoint; i++) {
BodyPoint *bp = &sb->bpoint[i];
@@ -3096,6 +3088,12 @@ static void softbody_to_object(Object *ob, float (*vertexCos)[3], int numVerts,
{
SoftBody *sb = ob->soft;
if (sb) {
+ int sb_totpt = sb->totpoint;
+ if(sb_totpt < numVerts)
+ {
+ printf("\n\n\n\nsoftbody_to_object ERROR: BAD SIZE TOTPOINT\n\n\n\n\n");
+ }
+
BodyPoint *bp = sb->bpoint;
int a;
if (sb->solverflags & SBSO_ESTIMATEIPO) {
@@ -3547,22 +3545,7 @@ static void sbStoreLastFrame(struct Depsgraph *depsgraph, Object *object, float
object_orig->soft->last_frame = framenr;
}
-static void admmpd_resize_softbody(Object *ob, int totpoint)
-{
- if (totpoint<=0)
- return;
-
- SoftBody *sb = ob->soft;
- if (sb->totpoint && sb->bpoint != NULL)
- {
- MEM_freeN(sb->bpoint);
- sb->bpoint = NULL;
- }
- sb->totpoint = totpoint;
- sb->totspring = 0;
- sb->bpoint = MEM_mallocN(totpoint * sizeof(BodyPoint), "bodypoint");
-}
-
+/*
static void admmpd_copy_to_softbody(Object *ob)
{
SoftBody *sb = ob->soft;
@@ -3570,22 +3553,23 @@ static void admmpd_copy_to_softbody(Object *ob)
if (admmpd == NULL)
return;
- if (sb->totpoint != admmpd->out_totverts)
+ if (sb->totpoint != admmpd->totverts)
{
printf("**admm_copy_to_softbody error: DOF missmatch");
return;
}
- for (int i=0; i<admmpd->out_totverts; ++i)
+ for (int i=0; i<admmpd->totverts; ++i)
{
BodyPoint *pt = &sb->bpoint[i];
for (int j=0; j<3; ++j)
{
- pt->pos[j] = admmpd->out_verts[i*3+j];
- pt->vec[j] = admmpd->out_vel[i*3+j];
+ pt->pos[j] = admmpd->verts[i*3+j];
+ pt->vec[j] = admmpd->vel[i*3+j];
}
}
}
+*/
static void init_admmpd_interface(Object *ob, float (*vertexCos)[3])
{
@@ -3595,15 +3579,16 @@ static void init_admmpd_interface(Object *ob, float (*vertexCos)[3])
Mesh *me = ob->data;
SoftBody *sb = ob->soft;
- sb->admmpd = MEM_callocN(sizeof(ADMMPDInterfaceData), "SoftBody_ADMMPD");
+ sb->admmpd = (ADMMPDInterfaceData*)MEM_callocN(sizeof(ADMMPDInterfaceData), "SoftBody_ADMMPD");
// Resize data
- admmpd_dealloc(sb->admmpd);
- sb->admmpd->in_totfaces = poly_to_tri_count(me->totpoly, me->totloop);
- sb->admmpd->in_totverts = me->totvert;
- admmpd_alloc(sb->admmpd);
+ int totfaces = poly_to_tri_count(me->totpoly, me->totloop);
+ unsigned int *in_faces = (unsigned int*)MEM_mallocN(sizeof(unsigned int)*totfaces*3, __func__);
+ float *in_verts = (float*)MEM_mallocN(sizeof(float)*me->totvert*3, __func__);
+ sb->admmpd->mesh_totverts = me->totvert;
+ sb->admmpd->mesh_totfaces = totfaces;
- // Initialize input data
+ // Initialize input vertices
for (int i=0; i<me->totvert; ++i)
{
// Local to global coordinates
@@ -3613,50 +3598,40 @@ static void init_admmpd_interface(Object *ob, float (*vertexCos)[3])
vi[2] = vertexCos[i][2];
mul_m4_v3(ob->obmat, vi);
for (int j=0; j<3; ++j)
- {
- sb->admmpd->in_verts[i*3+j] = vi[j];
- sb->admmpd->in_vel[i*3+j] = 0;
- }
+ in_verts[i*3+j] = vi[j];
}
+
+ // Initialize input faces
MLoopTri *looptri, *lt;
- looptri = lt = MEM_mallocN(sizeof(*looptri)*sb->admmpd->in_totfaces, __func__);
+ looptri = lt = (MLoopTri *)MEM_mallocN(sizeof(*looptri)*totfaces, __func__);
BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, looptri);
- for (int i=0; i<sb->admmpd->in_totfaces; ++i, ++lt)
+ for (int i=0; i<totfaces; ++i, ++lt)
{
- sb->admmpd->in_faces[i*3+0] = me->mloop[lt->tri[0]].v;
- sb->admmpd->in_faces[i*3+1] = me->mloop[lt->tri[1]].v;
- sb->admmpd->in_faces[i*3+2] = me->mloop[lt->tri[2]].v;
+ in_faces[i*3+0] = me->mloop[lt->tri[0]].v;
+ in_faces[i*3+1] = me->mloop[lt->tri[1]].v;
+ in_faces[i*3+2] = me->mloop[lt->tri[2]].v;
}
MEM_freeN(looptri);
looptri = NULL;
- // Initalize solver
- admmpd_init(sb->admmpd);
+ // Initalize solver and free tmp data
+ admmpd_init(sb->admmpd, in_verts, in_faces);
+ MEM_freeN(in_verts);
+ MEM_freeN(in_faces);
// Set up softbody to store defo verts
- int num_defo_verts = sb->admmpd->out_totverts;
- admmpd_resize_softbody(ob,num_defo_verts);
- admmpd_copy_to_softbody(ob);
-}
-
-static void admmpd_update_from_softbody(Object *ob)
-{
- SoftBody *sb = ob->soft;
- ADMMPDInterfaceData *admmpd = sb->admmpd;
- if (sb->totpoint != admmpd->out_totverts)
- {
- printf("**admmpd_update_from_softbody Error: DOF missmatch");
- return;
- }
- BodyPoint *bp = sb->bpoint;
- for (int i=0; i<sb->totpoint; ++i, ++bp)
- {
- for (int j=0; j<3; ++j)
- {
- admmpd->out_verts[i*3+j] = bp->pos[j];
- admmpd->out_vel[i*3+j] = bp->vec[j];
+ if (sb->admmpd->totverts > 0) {
+ if (sb->totpoint && sb->bpoint != NULL)
+ { // Free old data if exists
+ MEM_freeN(sb->bpoint);
+ sb->bpoint = NULL;
}
+ sb->totpoint = sb->admmpd->totverts;
+ sb->totspring = 0;
+ sb->bpoint = MEM_mallocN(sb->totpoint * sizeof(BodyPoint), "bodypoint");
}
+
+ admmpd_copy_to_bodypoint_and_object(sb->admmpd,sb->bpoint,NULL);
}
/* simulates one step. framenr is in frames */
@@ -3678,19 +3653,21 @@ void sbObjectStep_admmpd(
PTCacheID pid;
int framenr = (int)cfra;
int framedelta = framenr - cache->simframe;
- int startframe = 1;
- int endframe = 250;
- float timescale = 1.f;
+ int startframe = -1;
+ int endframe = -1;
+ float timescale = 0.f;
BKE_ptcache_id_from_softbody(&pid, ob, sb);
BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, &timescale);
-
- // Reset simulation
- bool reset_sim =
- sb->admmpd == NULL ||
- sb->admmpd->in_totverts != numVerts;
+ // BKE_ptcache_validate:
+ // sets flag that simulation is valid (|=)
+ // and sets simframe to framenr
+ // Calling BKE_ptcache_id_reset calls
+ // free_softbody_intern
+
// Reset cache
- if (reset_sim)
+ if (sb->admmpd == NULL ||
+ sb->admmpd->mesh_totverts != numVerts)
{
cache->flag |= PTCACHE_OUTDATED;
BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
@@ -3708,10 +3685,6 @@ void sbObjectStep_admmpd(
framenr = endframe;
}
- // Initialize simulation data if needed.
- if (sb->admmpd == NULL)
- init_admmpd_interface(ob,vertexCos);
-
// If it's the first frame we reset the cache and data
if (framenr == startframe) {
BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
@@ -3719,19 +3692,28 @@ void sbObjectStep_admmpd(
BKE_ptcache_validate(cache, framenr);
cache->flag &= ~PTCACHE_REDO_NEEDED;
sb->last_frame = framenr;
+ sbStoreLastFrame(depsgraph, ob, framenr);
return;
}
+ // Initialize simulation data if needed.
+ if (sb->admmpd == NULL)
+ {
+ printf("\n\n\n\n\n**ADMMPD data null!\n\n\n\n\n");
+ return;
+ }
+
// Read from cache
{
bool can_write_cache = DEG_is_active(depsgraph);
bool can_simulate = (framenr == sb->last_frame + 1) &&
!(cache->flag & PTCACHE_BAKED) &&
can_write_cache;
+ // Copies cache into softbody bpoint
int cache_result = BKE_ptcache_read(&pid, (float)framenr + scene->r.subframe, can_simulate);
-
- if (cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED ||
- (!can_simulate && cache_result == PTCACHE_READ_OLD)) {
+ if (cache_result == PTCACHE_READ_EXACT ||
+ cache_result == PTCACHE_READ_INTERPOLATED ||
+ (!can_simulate && cache_result == PTCACHE_READ_OLD)) {
softbody_to_object(ob, vertexCos, numVerts, sb->local);
BKE_ptcache_validate(cache, framenr);
if (cache_result == PTCACHE_READ_INTERPOLATED &&
@@ -3750,6 +3732,7 @@ void sbObjectStep_admmpd(
}
return;
}
+
if (!can_simulate)
return;
} // end read from cache
@@ -3762,10 +3745,9 @@ void sbObjectStep_admmpd(
// Update ADMMPD interface variables from cache
// and perform a solve.
- admmpd_update_from_softbody(ob);
+ admmpd_copy_from_bodypoint(sb->admmpd,sb->bpoint);
admmpd_solve(sb->admmpd);
- admmpd_get_vertices(sb->admmpd,vertexCos,numVerts);
- admmpd_copy_to_softbody(ob);
+ admmpd_copy_to_bodypoint_and_object(sb->admmpd,sb->bpoint,vertexCos);
// Write cache
BKE_ptcache_validate(cache, framenr);