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:
		@@ -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,8 +12254,8 @@ 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);
 | 
			
		||||
 | 
			
		||||
							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);
 | 
			
		||||
@@ -12232,6 +12267,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
 | 
			
		||||
								}
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					if (fd) {
 | 
			
		||||
						fd->reports= basefd->reports;
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
@@ -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",
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user