[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