Mesh Deform Modifier: compress static binding weights better, threshold
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Fri, 23 Apr 2010 11:19:06 +0000 (11:19 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Fri, 23 Apr 2010 11:19:06 +0000 (11:19 +0000)
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.

source/blender/blenkernel/BKE_modifier.h
source/blender/blenloader/intern/readfile.c
source/blender/editors/armature/meshlaplacian.c
source/blender/makesdna/DNA_modifier_types.h
source/blender/modifiers/intern/MOD_meshdeform.c

index ae6f1f5ed853fcdf9effae50caa4c6fb769cb932..d6ab99d6534f73209f6138a1dd79e0efe4db2d71 100644 (file)
@@ -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
 
index 32a07db1768c0c0e79081b3db96e7160c8ae4da6..8b0861252fec8e16c9a67d7cf6b2be0edf38aba1 100644 (file)
@@ -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);
+                                                               }
                                                        }
                                                }
                                        }
index 700f4573e3a3c88933cc7e0d6a400b460f82ae94..f0f7bc9eb885c0aa871b6036444fd3bd878a2799 100644 (file)
@@ -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);
 }
index a52c1f8343329e2da5f948ceb74267257e2d2ba2..3117536a7dc03ec708ac7cbbaa0cf1dbb86e00f3 100644 (file)
@@ -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,
index f10dbf94060a5f96d068f530232b541034a323a1..4b53ac910d15e75c589823dfb88a811cfb0f0f77 100644 (file)
@@ -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",