[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [24966] trunk/blender: Mesh Deform Modifier

Brecht Van Lommel brecht at blender.org
Sat Nov 28 14:33:18 CET 2009


Revision: 24966
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=24966
Author:   blendix
Date:     2009-11-28 14:33:17 +0100 (Sat, 28 Nov 2009)

Log Message:
-----------
Mesh Deform Modifier

* Now support a Surface mode next to the existing Volume mode. This binds
  the mesh to the cage mesh surface rather than it's volume.
* Implemented reusing the bone heat weighting code.
* Advantage is that it works for cage meshes that are not volumes and that
  binding is much faster.
* Weak point is that disconnected components of a mesh are not guaranteed
  to stick together (same problem exists with bone heat weighting).
* Bind weights could still be compressed better to use less memory.

Example file:
http://download.blender.org/ftp/incoming/cloth_mdef_surface.blend

Modified Paths:
--------------
    trunk/blender/release/scripts/ui/properties_data_modifier.py
    trunk/blender/source/blender/blenkernel/intern/modifier.c
    trunk/blender/source/blender/editors/armature/meshlaplacian.c
    trunk/blender/source/blender/editors/armature/meshlaplacian.h
    trunk/blender/source/blender/editors/include/ED_armature.h
    trunk/blender/source/blender/editors/object/object_modifier.c
    trunk/blender/source/blender/makesdna/DNA_modifier_types.h
    trunk/blender/source/blender/makesrna/intern/rna_modifier.c

Modified: trunk/blender/release/scripts/ui/properties_data_modifier.py
===================================================================
--- trunk/blender/release/scripts/ui/properties_data_modifier.py	2009-11-28 13:11:41 UTC (rev 24965)
+++ trunk/blender/release/scripts/ui/properties_data_modifier.py	2009-11-28 13:33:17 UTC (rev 24966)
@@ -365,11 +365,11 @@
     def MESH_DEFORM(self, layout, ob, md, wide_ui):
         split = layout.split()
         col = split.column()
-        col.label(text="Object:")
-        col.prop(md, "object", text="")
-        if md.object and md.object.type == 'ARMATURE':
-            col.label(text="Bone:")
-            col.prop_object(md, "subtarget", md.object.data, "bones", text="")
+        sub = col.column()
+        sub.label(text="Object:")
+        sub.prop(md, "object", text="")
+        sub.prop(md, "mode", text="")
+        sub.active = not md.is_bound
         if wide_ui:
             col = split.column()
         col.label(text="Vertex Group:")
@@ -385,15 +385,17 @@
             layout.operator("object.meshdeform_bind", text="Unbind")
         else:
             layout.operator("object.meshdeform_bind", text="Bind")
-            split = layout.split()
 
-            col = split.column()
-            col.prop(md, "precision")
+            if md.mode == 'VOLUME':
+                split = layout.split()
 
-            if wide_ui:
                 col = split.column()
-            col.prop(md, "dynamic")
+                col.prop(md, "precision")
 
+                if wide_ui:
+                    col = split.column()
+                col.prop(md, "dynamic")
+
     def MIRROR(self, layout, ob, md, wide_ui):
         layout.prop(md, "merge_limit")
         if wide_ui:

Modified: trunk/blender/source/blender/blenkernel/intern/modifier.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/modifier.c	2009-11-28 13:11:41 UTC (rev 24965)
+++ trunk/blender/source/blender/blenkernel/intern/modifier.c	2009-11-28 13:33:17 UTC (rev 24966)
@@ -7894,7 +7894,7 @@
 		/* progress bar redraw can make this recursive .. */
 		if(!recursive) {
 			recursive = 1;
-			mmd->bindfunc(md->scene, mmd, (float*)vertexCos, numVerts, cagemat);
+			mmd->bindfunc(md->scene, dm, mmd, (float*)vertexCos, numVerts, cagemat);
 			recursive = 0;
 		}
 	}

Modified: trunk/blender/source/blender/editors/armature/meshlaplacian.c
===================================================================
--- trunk/blender/source/blender/editors/armature/meshlaplacian.c	2009-11-28 13:11:41 UTC (rev 24965)
+++ trunk/blender/source/blender/editors/armature/meshlaplacian.c	2009-11-28 13:33:17 UTC (rev 24966)
@@ -93,13 +93,16 @@
 	EdgeHash *edgehash;		/* edge hash for construction */
 
 	struct HeatWeighting {
-		Mesh *mesh;
+		MFace *mface;
+		int totvert;
+		int totface;
 		float (*verts)[3];	/* vertex coordinates */
 		float (*vnors)[3];	/* vertex normals */
 
 		float (*root)[3];	/* bone root */
 		float (*tip)[3];	/* bone tip */
-		int numbones;
+		float (*source)[3]; /* vertex source */
+		int numsource;
 
 		float *H;			/* diagonal H matrix */
 		float *p;			/* values from all p vectors */
@@ -394,38 +397,40 @@
 #define WEIGHT_LIMIT_END	0.025f
 #define DISTANCE_EPSILON	1e-4f
 
-/* Raytracing for vertex to bone visibility */
+/* Raytracing for vertex to bone/vertex visibility */
 static void heat_ray_tree_create(LaplacianSystem *sys)
 {
-	Mesh *me = sys->heat.mesh;
+	MFace *mface = sys->heat.mface;
+	int totface = sys->heat.totface;
+	int totvert = sys->heat.totvert;
 	int a;
 
-	sys->heat.raytree = RE_rayobject_vbvh_create(me->totface);
-	sys->heat.faces = MEM_callocN(sizeof(RayFace)*me->totface, "Heat RayFaces");
-	sys->heat.vface = MEM_callocN(sizeof(MFace*)*me->totvert, "HeatVFaces");
+	sys->heat.raytree = RE_rayobject_vbvh_create(totface);
+	sys->heat.faces = MEM_callocN(sizeof(RayFace)*totface, "Heat RayFaces");
+	sys->heat.vface = MEM_callocN(sizeof(MFace*)*totvert, "HeatVFaces");
 
-	for(a=0; a<me->totface; a++) {
+	for(a=0; a<totface; a++) {
 	
-		MFace *mface = me->mface+a;
+		MFace *mf = mface+a;
 		RayFace *rayface = sys->heat.faces+a;
 
 		RayObject *obj = RE_rayface_from_coords(
-							rayface, me, mface,
-							sys->heat.verts[mface->v1], sys->heat.verts[mface->v2],
-							sys->heat.verts[mface->v3], mface->v4 ? sys->heat.verts[mface->v4] : 0
+							rayface, &sys->heat, mf,
+							sys->heat.verts[mf->v1], sys->heat.verts[mf->v2],
+							sys->heat.verts[mf->v3], mf->v4 ? sys->heat.verts[mf->v4] : 0
 						);
 		RE_rayobject_add(sys->heat.raytree, obj); 
 		
 		//Setup inverse pointers to use on isect.orig
-		sys->heat.vface[mface->v1]= mface;
-		sys->heat.vface[mface->v2]= mface;
-		sys->heat.vface[mface->v3]= mface;
-		if(mface->v4) sys->heat.vface[mface->v4]= mface;
+		sys->heat.vface[mf->v1]= mf;
+		sys->heat.vface[mf->v2]= mf;
+		sys->heat.vface[mf->v3]= mf;
+		if(mf->v4) sys->heat.vface[mf->v4]= mf;
 	}
 	RE_rayobject_done(sys->heat.raytree); 
 }
 
-static int heat_ray_bone_visible(LaplacianSystem *sys, int vertex, int bone)
+static int heat_ray_source_visible(LaplacianSystem *sys, int vertex, int source)
 {
 	Isect isec;
 	MFace *mface;
@@ -440,30 +445,37 @@
 	memset(&isec, 0, sizeof(isec));
 	isec.mode= RE_RAY_SHADOW;
 	isec.lay= -1;
-	isec.orig.ob = sys->heat.mesh;
+	isec.orig.ob = &sys->heat;
 	isec.orig.face = mface;
 	isec.skip = RE_SKIP_CULLFACE;
 	
+	copy_v3_v3(isec.start, sys->heat.verts[vertex]);
 
-	VECCOPY(isec.start, sys->heat.verts[vertex]);
-	closest_to_line_segment_v3(end, isec.start, sys->heat.root[bone], sys->heat.tip[bone]);
+	if(sys->heat.root) /* bone */
+		closest_to_line_segment_v3(end, isec.start,
+			sys->heat.root[source], sys->heat.tip[source]);
+	else /* vertex */
+		copy_v3_v3(end, sys->heat.source[source]);
 
-	VECSUB(isec.vec, end, isec.start);
+	sub_v3_v3v3(isec.vec, end, isec.start);
 	isec.labda = 1.0f - 1e-5;
-	VECADDFAC( isec.start, isec.start, isec.vec, 1e-5);
+	madd_v3_v3v3fl(isec.start, isec.start, isec.vec, 1e-5);
 
 	visible= !RE_rayobject_raycast(sys->heat.raytree, &isec);
 
 	return visible;
 }
 
-static float heat_bone_distance(LaplacianSystem *sys, int vertex, int bone)
+static float heat_source_distance(LaplacianSystem *sys, int vertex, int source)
 {
 	float closest[3], d[3], dist, cosine;
 	
 	/* compute euclidian distance */
-	closest_to_line_segment_v3(closest, sys->heat.verts[vertex],
-		sys->heat.root[bone], sys->heat.tip[bone]);
+	if(sys->heat.root) /* bone */
+		closest_to_line_segment_v3(closest, sys->heat.verts[vertex],
+			sys->heat.root[source], sys->heat.tip[source]);
+	else /* vertex */
+		copy_v3_v3(closest, sys->heat.source[source]);
 
 	sub_v3_v3v3(d, sys->heat.verts[vertex], closest);
 	dist= normalize_v3(d);
@@ -474,16 +486,16 @@
 	return dist/(0.5f*(cosine + 1.001f));
 }
 
-static int heat_bone_closest(LaplacianSystem *sys, int vertex, int bone)
+static int heat_source_closest(LaplacianSystem *sys, int vertex, int source)
 {
 	float dist;
-	
-	dist= heat_bone_distance(sys, vertex, bone);
 
+	dist= heat_source_distance(sys, vertex, source);
+
 	if(dist <= sys->heat.mindist[vertex]*(1.0f + DISTANCE_EPSILON))
-		if(heat_ray_bone_visible(sys, vertex, bone))
+		if(heat_ray_source_visible(sys, vertex, source))
 			return 1;
-	
+		
 	return 0;
 }
 
@@ -495,8 +507,8 @@
 	mindist= 1e10;
 
 	/* compute minimum distance */
-	for(j=0; j<sys->heat.numbones; j++) {
-		dist= heat_bone_distance(sys, vertex, j);
+	for(j=0; j<sys->heat.numsource; j++) {
+		dist= heat_source_distance(sys, vertex, j);
 
 		if(dist < mindist)
 			mindist= dist;
@@ -504,9 +516,9 @@
 
 	sys->heat.mindist[vertex]= mindist;
 
-	/* count number of bones with approximately this minimum distance */
-	for(j=0; j<sys->heat.numbones; j++)
-		if(heat_bone_closest(sys, vertex, j))
+	/* count number of sources with approximately this minimum distance */
+	for(j=0; j<sys->heat.numsource; j++)
+		if(heat_source_closest(sys, vertex, j))
 			numclosest++;
 
 	sys->heat.p[vertex]= (numclosest > 0)? 1.0f/numclosest: 0.0f;
@@ -549,32 +561,45 @@
 
 static void heat_laplacian_create(LaplacianSystem *sys)
 {
-	Mesh *me = sys->heat.mesh;
-	MFace *mface;
+	MFace *mface = sys->heat.mface, *mf;
+	int totface= sys->heat.totface;
+	int totvert= sys->heat.totvert;
 	int a;
 
 	/* heat specific definitions */
-	sys->heat.mindist= MEM_callocN(sizeof(float)*me->totvert, "HeatMinDist");
-	sys->heat.H= MEM_callocN(sizeof(float)*me->totvert, "HeatH");
-	sys->heat.p= MEM_callocN(sizeof(float)*me->totvert, "HeatP");
+	sys->heat.mindist= MEM_callocN(sizeof(float)*totvert, "HeatMinDist");
+	sys->heat.H= MEM_callocN(sizeof(float)*totvert, "HeatH");
+	sys->heat.p= MEM_callocN(sizeof(float)*totvert, "HeatP");
 
 	/* add verts and faces to laplacian */
-	for(a=0; a<me->totvert; a++)
+	for(a=0; a<totvert; a++)
 		laplacian_add_vertex(sys, sys->heat.verts[a], 0);
 
-	for(a=0, mface=me->mface; a<me->totface; a++, mface++) {
-		laplacian_add_triangle(sys, mface->v1, mface->v2, mface->v3);
-		if(mface->v4)
-			laplacian_add_triangle(sys, mface->v1, mface->v3, mface->v4);
+	for(a=0, mf=mface; a<totface; a++, mf++) {
+		laplacian_add_triangle(sys, mf->v1, mf->v2, mf->v3);
+		if(mf->v4)
+			laplacian_add_triangle(sys, mf->v1, mf->v3, mf->v4);
 	}
 
 	/* for distance computation in set_H */
 	heat_calc_vnormals(sys);
 
-	for(a=0; a<me->totvert; a++)
+	for(a=0; a<totvert; a++)
 		heat_set_H(sys, a);
 }
 
+static void heat_system_free(LaplacianSystem *sys)
+{
+	RE_rayobject_free(sys->heat.raytree);
+	MEM_freeN(sys->heat.vface);
+	MEM_freeN(sys->heat.faces);
+
+	MEM_freeN(sys->heat.mindist);
+	MEM_freeN(sys->heat.H);
+	MEM_freeN(sys->heat.p);
+	MEM_freeN(sys->heat.vnors);
+}
+
 static float heat_limit_weight(float weight)
 {
 	float t;
@@ -590,7 +615,7 @@
 		return weight;
 }
 
-void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numbones, bDeformGroup **dgrouplist, bDeformGroup **dgroupflip, float (*root)[3], float (*tip)[3], int *selected)
+void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource, bDeformGroup **dgrouplist, bDeformGroup **dgroupflip, float (*root)[3], float (*tip)[3], int *selected)
 {
 	LaplacianSystem *sys;
 	MFace *mface;
@@ -607,11 +632,13 @@
 	/* create laplacian */
 	sys = laplacian_system_construct_begin(me->totvert, totface, 1);
 
-	sys->heat.mesh= me;
+	sys->heat.mface= me->mface;
+	sys->heat.totface= me->totface;
+	sys->heat.totvert= me->totvert;
 	sys->heat.verts= verts;
 	sys->heat.root= root;
 	sys->heat.tip= tip;

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list