Mesh Deform Modifier: compress static binding weights better, threshold

is still set very low so in many cases it could be even smaller, but being
a bit conservative here to try to avoid breaking rigs.

This is not forward-compatible, i.e. loading new files in older blender
versions will loose the binding.
This commit is contained in:
Brecht Van Lommel 2010-04-23 11:19:06 +00:00
parent d43bef938f
commit 08775e8f14
5 changed files with 150 additions and 33 deletions

@ -321,5 +321,8 @@ struct LinkNode *modifiers_calcDataMasks(struct Scene *scene,
int required_mode);
struct ModifierData *modifiers_getVirtualModifierList(struct Object *ob);
/* here for do_versions */
void modifier_mdef_compact_influences(struct ModifierData *md);
#endif

@ -3852,24 +3852,35 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
else if (md->type==eModifierType_MeshDeform) {
MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
mmd->bindweights= newdataadr(fd, mmd->bindweights);
mmd->bindcos= newdataadr(fd, mmd->bindcos);
mmd->bindinfluences= newdataadr(fd, mmd->bindinfluences);
mmd->bindoffsets= newdataadr(fd, mmd->bindoffsets);
mmd->bindcagecos= newdataadr(fd, mmd->bindcagecos);
mmd->dyngrid= newdataadr(fd, mmd->dyngrid);
mmd->dyninfluences= newdataadr(fd, mmd->dyninfluences);
mmd->dynverts= newdataadr(fd, mmd->dynverts);
mmd->bindweights= newdataadr(fd, mmd->bindweights);
mmd->bindcos= newdataadr(fd, mmd->bindcos);
if(fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
int a;
if(mmd->bindoffsets)
for(a=0; a<mmd->totvert+1; a++)
SWITCH_INT(mmd->bindoffsets[a])
if(mmd->bindcagecos)
for(a=0; a<mmd->totcagevert*3; a++)
SWITCH_INT(mmd->bindcagecos[a])
if(mmd->dynverts)
for(a=0; a<mmd->totvert; a++)
SWITCH_INT(mmd->dynverts[a])
if(mmd->bindweights)
for(a=0; a<mmd->totcagevert*mmd->totvert; a++)
SWITCH_INT(mmd->bindweights[a])
if(mmd->bindcos)
for(a=0; a<mmd->totcagevert*3; a++)
SWITCH_INT(mmd->bindcos[a])
if(mmd->dynverts)
for(a=0; a<mmd->totvert; a++)
SWITCH_INT(mmd->dynverts[a])
}
}
}
@ -5169,7 +5180,7 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
/*comma expressions, (e.g. expr1, expr2, expr3) evalutate each expression,
from left to right. the right-most expression sets the result of the comma
expression as a whole*/
for(cl= sconsole->history.first; cl && (clnext=cl->next), cl; cl= clnext) {
for(cl= sconsole->history.first; cl && (clnext=cl->next); cl= clnext) {
cl->line= newdataadr(fd, cl->line);
if (!cl->line) {
BLI_remlink(&sconsole->history, cl);
@ -6451,6 +6462,30 @@ static void do_version_mtex_factor_2_50(MTex **mtex_array, short idtype)
}
}
static void do_version_mdef_250(FileData *fd, Library *lib, Main *main)
{
Object *ob;
ModifierData *md;
MeshDeformModifierData *mmd;
for(ob= main->object.first; ob; ob=ob->id.next) {
for(md=ob->modifiers.first; md; md=md->next) {
if(md->type == eModifierType_MeshDeform) {
mmd= (MeshDeformModifierData*)md;
if(mmd->bindcos) {
/* make bindcos NULL in order to trick older versions
into thinking that the mesh was not bound yet */
mmd->bindcagecos= mmd->bindcos;
mmd->bindcos= NULL;
modifier_mdef_compact_influences(md);
}
}
}
}
}
static void do_version_constraints_radians_degrees_250(ListBase *lb)
{
bConstraint *con;
@ -10780,7 +10815,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
/* put 2.50 compatibility code here until next subversion bump */
{
do_version_mdef_250(fd, lib, main);
}
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
@ -12219,16 +12254,17 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
printf(" absolute lib: %s\n", mainptr->curlib->filename);
printf(" relative lib: %s\n", mainptr->curlib->name);
printf(" enter a new path:\n");
scanf("%s", newlib_path);
strcpy(mainptr->curlib->name, newlib_path);
strcpy(mainptr->curlib->filename, newlib_path);
cleanup_path(G.sce, mainptr->curlib->filename);
fd= blo_openblenderfile(mainptr->curlib->filename, basefd->reports);
if(scanf("%s", newlib_path) > 0) {
strcpy(mainptr->curlib->name, newlib_path);
strcpy(mainptr->curlib->filename, newlib_path);
cleanup_path(G.sce, mainptr->curlib->filename);
fd= blo_openblenderfile(mainptr->curlib->filename, basefd->reports);
if(fd) {
printf("found: '%s', party on macuno!\n", mainptr->curlib->filename);
if(fd) {
printf("found: '%s', party on macuno!\n", mainptr->curlib->filename);
}
}
}
}

@ -44,6 +44,7 @@
#include "BLI_memarena.h"
#include "BKE_DerivedMesh.h"
#include "BKE_modifier.h"
#include "BKE_utildefines.h"
#ifdef RIGID_DEFORM
@ -1991,19 +1992,22 @@ void mesh_deform_bind(Scene *scene, DerivedMesh *dm, MeshDeformModifierData *mmd
#endif
/* assign bind variables */
mmd->bindcos= (float*)mdb.cagecos;
mmd->bindcagecos= (float*)mdb.cagecos;
mmd->totvert= mdb.totvert;
mmd->totcagevert= mdb.totcagevert;
copy_m4_m4(mmd->bindmat, mmd->object->obmat);
/* transform bindcos to world space */
/* transform bindcagecos to world space */
for(a=0; a<mdb.totcagevert; a++)
mul_m4_v3(mmd->object->obmat, mmd->bindcos+a*3);
mul_m4_v3(mmd->object->obmat, mmd->bindcagecos+a*3);
/* free */
mdb.cagedm->release(mdb.cagedm);
MEM_freeN(mdb.vertexcos);
/* compact weights */
modifier_mdef_compact_influences((ModifierData*)mmd);
end_progress_bar();
waitcursor(0);
}

@ -516,9 +516,13 @@ typedef struct MeshDeformModifierData {
short gridsize, flag, mode, pad;
/* variables filled in when bound */
float *bindweights, *bindcos; /* computed binding weights */
/* result of static binding */
MDefInfluence *bindinfluences; /* influences */
int *bindoffsets; /* offsets into influences array */
float *bindcagecos; /* coordinates that cage was bound with */
int totvert, totcagevert; /* total vertices in mesh and cage */
/* result of dynamic binding */
MDefCell *dyngrid; /* grid with dynamic binding cell points */
MDefInfluence *dyninfluences; /* dynamic binding vertex influences */
int *dynverts, *pad2; /* is this vertex bound or not? */
@ -528,6 +532,10 @@ typedef struct MeshDeformModifierData {
float dyncellwidth; /* width of dynamic bind cell */
float bindmat[4][4]; /* matrix of cage at binding time */
/* deprecated storage */
float *bindweights; /* deprecated inefficient storage */
float *bindcos; /* deprecated storage of cage coords */
/* runtime */
void (*bindfunc)(struct Scene *scene, struct DerivedMesh *dm,
struct MeshDeformModifierData *mmd,

@ -58,8 +58,9 @@ static void freeData(ModifierData *md)
{
MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
if(mmd->bindweights) MEM_freeN(mmd->bindweights);
if(mmd->bindcos) MEM_freeN(mmd->bindcos);
if(mmd->bindinfluences) MEM_freeN(mmd->bindinfluences);
if(mmd->bindoffsets) MEM_freeN(mmd->bindoffsets);
if(mmd->bindcagecos) MEM_freeN(mmd->bindcagecos);
if(mmd->dyngrid) MEM_freeN(mmd->dyngrid);
if(mmd->dyninfluences) MEM_freeN(mmd->dyninfluences);
if(mmd->dynverts) MEM_freeN(mmd->dynverts);
@ -170,7 +171,7 @@ static float meshdeform_dynamic_bind(MeshDeformModifierData *mmd, float (*dco)[3
}
static void meshdeformModifier_do(
ModifierData *md, Object *ob, DerivedMesh *dm,
ModifierData *md, Object *ob, DerivedMesh *dm,
float (*vertexCos)[3], int numVerts)
{
MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
@ -180,11 +181,13 @@ static void meshdeformModifier_do(
MDeformVert *dvert = NULL;
MDeformWeight *dw;
MVert *cagemvert;
MDefInfluence *influences;
int *offsets;
float imat[4][4], cagemat[4][4], iobmat[4][4], icagemat[3][3], cmat[4][4];
float weight, totweight, fac, co[3], *weights, (*dco)[3], (*bindcos)[3];
float weight, totweight, fac, co[3], (*dco)[3], (*bindcagecos)[3];
int a, b, totvert, totcagevert, defgrp_index;
if(!mmd->object || (!mmd->bindcos && !mmd->bindfunc))
if(!mmd->object || (!mmd->bindcagecos && !mmd->bindfunc))
return;
/* get cage derivedmesh */
@ -216,7 +219,7 @@ static void meshdeformModifier_do(
copy_m3_m4(icagemat, iobmat);
/* bind weights if needed */
if(!mmd->bindcos) {
if(!mmd->bindcagecos) {
static int recursive = 0;
/* progress bar redraw can make this recursive .. */
@ -231,15 +234,16 @@ static void meshdeformModifier_do(
totvert= numVerts;
totcagevert= cagedm->getNumVerts(cagedm);
if(mmd->totvert!=totvert || mmd->totcagevert!=totcagevert || !mmd->bindcos) {
if(mmd->totvert!=totvert || mmd->totcagevert!=totcagevert || !mmd->bindcagecos) {
cagedm->release(cagedm);
return;
}
/* setup deformation data */
cagemvert= cagedm->getVertArray(cagedm);
weights= mmd->bindweights;
bindcos= (float(*)[3])mmd->bindcos;
influences= mmd->bindinfluences;
offsets= mmd->bindoffsets;
bindcagecos= (float(*)[3])mmd->bindcagecos;
dco= MEM_callocN(sizeof(*dco)*totcagevert, "MDefDco");
for(a=0; a<totcagevert; a++) {
@ -249,7 +253,7 @@ static void meshdeformModifier_do(
if(G.rt != 527) {
mul_m4_v3(mmd->bindmat, co);
/* compute difference with world space bind coord */
sub_v3_v3v3(dco[a], co, bindcos[a]);
sub_v3_v3v3(dco[a], co, bindcagecos[a]);
}
else
copy_v3_v3(dco[a], co);
@ -296,9 +300,9 @@ static void meshdeformModifier_do(
totweight= 0.0f;
co[0]= co[1]= co[2]= 0.0f;
for(a=0; a<totcagevert; a++) {
weight= weights[a + b*totcagevert];
madd_v3_v3fl(co, dco[a], weight);
for(a=offsets[b]; a<offsets[b+1]; a++) {
weight= influences[a].weight;
madd_v3_v3fl(co, dco[influences[a].vertex], weight);
totweight += weight;
}
}
@ -352,6 +356,68 @@ static void deformVertsEM(
dm->release(dm);
}
#define MESHDEFORM_MIN_INFLUENCE 0.00001
void modifier_mdef_compact_influences(ModifierData *md)
{
MeshDeformModifierData *mmd= (MeshDeformModifierData*)md;
float weight, *weights, totweight;
int totinfluence, totvert, totcagevert, a, b;
weights= mmd->bindweights;
if(!weights)
return;
totvert= mmd->totvert;
totcagevert= mmd->totcagevert;
/* count number of influences above threshold */
for(b=0; b<totvert; b++) {
for(a=0; a<totcagevert; a++) {
weight= weights[a + b*totcagevert];
if(weight > MESHDEFORM_MIN_INFLUENCE)
mmd->totinfluence++;
}
}
/* allocate bind influences */
mmd->bindinfluences= MEM_callocN(sizeof(MDefInfluence)*mmd->totinfluence, "MDefBindInfluence");
mmd->bindoffsets= MEM_callocN(sizeof(int)*(totvert+1), "MDefBindOffset");
/* write influences */
totinfluence= 0;
for(b=0; b<totvert; b++) {
mmd->bindoffsets[b]= totinfluence;
totweight= 0.0f;
/* sum total weight */
for(a=0; a<totcagevert; a++) {
weight= weights[a + b*totcagevert];
if(weight > MESHDEFORM_MIN_INFLUENCE)
totweight += weight;
}
/* assign weights normalized */
for(a=0; a<totcagevert; a++) {
weight= weights[a + b*totcagevert];
if(weight > MESHDEFORM_MIN_INFLUENCE) {
mmd->bindinfluences[totinfluence].weight= weight/totweight;
mmd->bindinfluences[totinfluence].vertex= a;
totinfluence++;
}
}
}
mmd->bindoffsets[b]= totinfluence;
/* free */
MEM_freeN(mmd->bindweights);
mmd->bindweights= NULL;
}
ModifierTypeInfo modifierType_MeshDeform = {
/* name */ "MeshDeform",