Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2007-11-28 00:16:47 +0300
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2007-11-28 00:16:47 +0300
commit228416e108382df0dda7bff680ac46ce6e788821 (patch)
tree060d0397ffb539f90629180e8daa0d37fa8a5308 /source
parent044b78c83b0f9e0503d8077edc4d235ffcb97e85 (diff)
Heat Weighting
============== Now takes b-bones into account, solving as if each bone segment was an individual bone, and then adding the weights together.
Diffstat (limited to 'source')
-rw-r--r--source/blender/include/BIF_editdeform.h2
-rw-r--r--source/blender/src/editarmature.c149
-rw-r--r--source/blender/src/editdeform.c47
-rw-r--r--source/blender/src/meshlaplacian.c85
4 files changed, 220 insertions, 63 deletions
diff --git a/source/blender/include/BIF_editdeform.h b/source/blender/include/BIF_editdeform.h
index 2a8f43c14e7..62b850f9094 100644
--- a/source/blender/include/BIF_editdeform.h
+++ b/source/blender/include/BIF_editdeform.h
@@ -61,6 +61,8 @@ void add_vert_to_defgroup (struct Object *ob, struct bDeformGroup *dg,
int assignmode);
void remove_vert_defgroup (struct Object *ob, struct bDeformGroup *dg,
int vertnum);
+float get_vert_defgroup (struct Object *ob, struct bDeformGroup *dg,
+ int vertnum);
void create_dverts(ID *id);
void vertexgroup_select_by_name(struct Object *ob, char *name);
diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c
index 24c8382a445..9dcb190509f 100644
--- a/source/blender/src/editarmature.c
+++ b/source/blender/src/editarmature.c
@@ -2552,7 +2552,7 @@ int bone_looper(Object *ob, Bone *bone, void *data,
}
-static int bone_skinnable(Object *ob, Bone *bone, void *data)
+static int bone_skinnable(Object *ob, Bone *bone, void *datap)
{
/* Bones that are deforming
* are regarded to be "skinnable" and are eligible for
@@ -2576,16 +2576,26 @@ static int bone_skinnable(Object *ob, Bone *bone, void *data)
* pointers to bones that point to all
* skinnable bones.
*/
- Bone ***hbone;
+ Bone ***hbone;
+ int a, segments;
+ struct { Object *armob; void *list; int heat; } *data = datap;
if(!(G.f & G_WEIGHTPAINT) || !(bone->flag & BONE_HIDDEN_P)) {
if (!(bone->flag & BONE_NO_DEFORM)) {
- if (data != NULL) {
- hbone = (Bone ***) data;
- **hbone = bone;
- ++*hbone;
+ if(data->heat && data->armob->pose && get_pose_channel(data->armob->pose, bone->name))
+ segments = bone->segments;
+ else
+ segments = 1;
+
+ if (data->list != NULL) {
+ hbone = (Bone ***) &data->list;
+
+ for(a=0; a<segments; a++) {
+ **hbone = bone;
+ ++*hbone;
+ }
}
- return 1;
+ return segments;
}
}
return 0;
@@ -2606,7 +2616,7 @@ static int add_defgroup_unique_bone(Object *ob, Bone *bone, void *data)
return 0;
}
-static int dgroup_skinnable(Object *ob, Bone *bone, void *data)
+static int dgroup_skinnable(Object *ob, Bone *bone, void *datap)
{
/* Bones that are deforming
* are regarded to be "skinnable" and are eligible for
@@ -2632,19 +2642,28 @@ static int dgroup_skinnable(Object *ob, Bone *bone, void *data)
* of skinnable bones.
*/
bDeformGroup ***hgroup, *defgroup;
+ int a, segments;
+ struct { Object *armob; void *list; int heat; } *data= datap;
if(!(G.f & G_WEIGHTPAINT) || !(bone->flag & BONE_HIDDEN_P)) {
if (!(bone->flag & BONE_NO_DEFORM)) {
- if ( !(defgroup = get_named_vertexgroup(ob, bone->name)) ) {
+ if(data->heat && data->armob->pose && get_pose_channel(data->armob->pose, bone->name))
+ segments = bone->segments;
+ else
+ segments = 1;
+
+ if(!(defgroup = get_named_vertexgroup(ob, bone->name)))
defgroup = add_defgroup_name(ob, bone->name);
- }
- if (data != NULL) {
- hgroup = (bDeformGroup ***) data;
- **hgroup = defgroup;
- ++*hgroup;
+ if (data->list != NULL) {
+ hgroup = (bDeformGroup ***) &data->list;
+
+ for(a=0; a<segments; a++) {
+ **hgroup = defgroup;
+ ++*hgroup;
+ }
}
- return 1;
+ return segments;
}
}
return 0;
@@ -2682,7 +2701,7 @@ static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], i
/* store the distance-factor from the vertex to the bone */
distance = distfactor_to_bone (verts[i], root[j], tip[j],
bone->rad_head * scale, bone->rad_tail * scale, bone->dist * scale);
-
+
/* add the vert to the deform group if weight!=0.0 */
if (distance!=0.0)
add_vert_to_defgroup (ob, dgroup, i, distance, WEIGHT_REPLACE);
@@ -2713,59 +2732,95 @@ void add_verts_to_dgroups(Object *ob, Object *par, int heat, int mirror)
* The mesh vertex positions used are either the final deformed coords
* from the derivedmesh in weightpaint mode, the final subsurf coords
* when parenting, or simply the original mesh coords.
- */
+ */
- bArmature *arm;
- Bone **bonelist, **bonehandle, *bone;
- bDeformGroup **dgrouplist, **dgroupflip, **dgrouphandle;
+ bArmature *arm;
+ Bone **bonelist, *bone;
+ bDeformGroup **dgrouplist, **dgroupflip;
bDeformGroup *dgroup, *curdg;
- Mesh *mesh;
- float (*root)[3], (*tip)[3], (*verts)[3];
+ bPoseChannel *pchan;
+ Mesh *mesh;
+ Mat4 *bbone = NULL;
+ float (*root)[3], (*tip)[3], (*verts)[3];
int *selected;
- int numbones, vertsfilled = 0, i, j;
+ int numbones, vertsfilled = 0, i, j, segments = 0;
int wpmode = (G.f & G_WEIGHTPAINT);
+ struct { Object *armob; void *list; int heat; } looper_data;
- /* If the parent object is not an armature exit */
- arm = get_armature(par);
- if (!arm)
- return;
+ /* If the parent object is not an armature exit */
+ arm = get_armature(par);
+ if (!arm)
+ return;
+
+ looper_data.armob = par;
+ looper_data.heat= heat;
+ looper_data.list= NULL;
- /* count the number of skinnable bones */
- numbones = bone_looper(ob, arm->bonebase.first, NULL, bone_skinnable);
+ /* count the number of skinnable bones */
+ numbones = bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable);
if (numbones == 0)
return;
- /* create an array of pointer to bones that are skinnable
- * and fill it with all of the skinnable bones */
- bonelist = MEM_callocN(numbones*sizeof(Bone *), "bonelist");
- bonehandle = bonelist;
- bone_looper(ob, arm->bonebase.first, &bonehandle, bone_skinnable);
+ /* create an array of pointer to bones that are skinnable
+ * and fill it with all of the skinnable bones */
+ bonelist = MEM_callocN(numbones*sizeof(Bone *), "bonelist");
+ looper_data.list= bonelist;
+ bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable);
- /* create an array of pointers to the deform groups that
- * coorespond to the skinnable bones (creating them
- * as necessary. */
- dgrouplist = MEM_callocN(numbones*sizeof(bDeformGroup *), "dgrouplist");
- dgroupflip = MEM_callocN(numbones*sizeof(bDeformGroup *), "dgroupflip");
+ /* create an array of pointers to the deform groups that
+ * coorespond to the skinnable bones (creating them
+ * as necessary. */
+ dgrouplist = MEM_callocN(numbones*sizeof(bDeformGroup *), "dgrouplist");
+ dgroupflip = MEM_callocN(numbones*sizeof(bDeformGroup *), "dgroupflip");
- dgrouphandle = dgrouplist;
- bone_looper(ob, arm->bonebase.first, &dgrouphandle, dgroup_skinnable);
+ looper_data.list= dgrouplist;
+ bone_looper(ob, arm->bonebase.first, &looper_data, dgroup_skinnable);
- /* create an array of root and tip positions transformed into
+ /* create an array of root and tip positions transformed into
* global coords */
- root = MEM_callocN(numbones*sizeof(float)*3, "root");
- tip = MEM_callocN(numbones*sizeof(float)*3, "tip");
+ root = MEM_callocN(numbones*sizeof(float)*3, "root");
+ tip = MEM_callocN(numbones*sizeof(float)*3, "tip");
selected = MEM_callocN(numbones*sizeof(int), "selected");
for (j=0; j < numbones; ++j) {
bone = bonelist[j];
dgroup = dgrouplist[j];
+ /* handle bbone */
+ if(heat) {
+ if(segments == 0) {
+ segments = 1;
+ bbone = NULL;
+
+ if(par->pose && (pchan=get_pose_channel(par->pose, bone->name))) {
+ if(bone->segments > 1) {
+ segments = bone->segments;
+ bbone = b_bone_spline_setup(pchan, 1);
+ }
+ }
+ }
+
+ segments--;
+ }
+
/* compute root and tip */
- VECCOPY(root[j], bone->arm_head);
- Mat4MulVecfl(par->obmat, root[j]);
+ if(bbone) {
+ VECCOPY(root[j], bbone[segments].mat[3]);
+ Mat4MulVecfl(bone->arm_mat, root[j]);
+ if(segments+1 < bone->segments) {
+ VECCOPY(tip[j], bbone[segments+1].mat[3])
+ Mat4MulVecfl(bone->arm_mat, tip[j]);
+ }
+ else
+ VECCOPY(tip[j], bone->arm_tail)
+ }
+ else {
+ VECCOPY(root[j], bone->arm_head);
+ VECCOPY(tip[j], bone->arm_tail);
+ }
- VECCOPY(tip[j], bone->arm_tail);
+ Mat4MulVecfl(par->obmat, root[j]);
Mat4MulVecfl(par->obmat, tip[j]);
/* set selected */
diff --git a/source/blender/src/editdeform.c b/source/blender/src/editdeform.c
index 6d0c34f2bf8..b4206a510aa 100644
--- a/source/blender/src/editdeform.c
+++ b/source/blender/src/editdeform.c
@@ -704,6 +704,53 @@ void remove_vert_defgroup (Object *ob, bDeformGroup *dg, int vertnum)
remove_vert_def_nr (ob, def_nr, vertnum);
}
+/* for mesh in object mode lattice can be in editmode */
+static float get_vert_def_nr (Object *ob, int def_nr, int vertnum)
+{
+ MDeformVert *dvert= NULL;
+ int i;
+
+ /* get the deform vertices corresponding to the
+ * vertnum
+ */
+ if(ob->type==OB_MESH) {
+ if( ((Mesh*)ob->data)->dvert )
+ dvert = ((Mesh*)ob->data)->dvert + vertnum;
+ }
+ else if(ob->type==OB_LATTICE) {
+ Lattice *lt= ob->data;
+
+ if(ob==G.obedit)
+ lt= editLatt;
+
+ if(lt->dvert)
+ dvert = lt->dvert + vertnum;
+ }
+
+ if(dvert==NULL)
+ return 0.0f;
+
+ for(i=dvert->totweight-1 ; i>=0 ; i--)
+ if(dvert->dw[i].def_nr == def_nr)
+ return dvert->dw[i].weight;
+
+ return 0.0f;
+}
+
+/* mesh object mode, lattice can be in editmode */
+float get_vert_defgroup (Object *ob, bDeformGroup *dg, int vertnum)
+{
+ int def_nr;
+
+ if(!ob)
+ return 0.0f;
+
+ def_nr = get_defgroup_num(ob, dg);
+ if(def_nr < 0) return 0.0f;
+
+ return get_vert_def_nr (ob, def_nr, vertnum);
+}
+
/* Only available in editmode */
/* removes from active defgroup, if allverts==0 only selected vertices */
void remove_verts_defgroup (int allverts)
diff --git a/source/blender/src/meshlaplacian.c b/source/blender/src/meshlaplacian.c
index 5d15dbf47b0..d711419a927 100644
--- a/source/blender/src/meshlaplacian.c
+++ b/source/blender/src/meshlaplacian.c
@@ -407,7 +407,7 @@ static int heat_ray_check_func(Isect *is, RayFace *face)
if(v4) CalcNormFloat4(v1, v2, v3, v4, nor);
else CalcNormFloat(v1, v2, v3, nor);
-
+
return (INPR(nor, is->vec) < 0);
}
@@ -605,8 +605,9 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numbones,
{
LaplacianSystem *sys;
MFace *mface;
- float solution;
- int a, aflip, totface, j, thrownerror = 0;
+ float solution, weight;
+ int *vertsflipped = NULL;
+ int a, totface, j, bbone, firstsegment, lastsegment, thrownerror = 0;
/* count triangles */
for(totface=0, a=0, mface=me->mface; a<me->totface; a++, mface++) {
@@ -628,11 +629,31 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numbones,
laplacian_system_construct_end(sys);
+ if(dgroupflip) {
+ vertsflipped = MEM_callocN(sizeof(int)*me->totvert, "vertsflipped");
+ for(a=0; a<me->totvert; a++)
+ vertsflipped[a] = mesh_get_x_mirror_vert(ob, a);
+ }
+
/* compute weights per bone */
for(j=0; j<numbones; j++) {
if(!selected[j])
continue;
+ firstsegment= (j == 0 || dgrouplist[j-1] != dgrouplist[j]);
+ lastsegment= (j == numbones-1 || dgrouplist[j] != dgrouplist[j+1]);
+ bbone= !(firstsegment && lastsegment);
+
+ /* clear weights */
+ if(bbone && firstsegment) {
+ for(a=0; a<me->totvert; a++) {
+ remove_vert_defgroup(ob, dgrouplist[j], a);
+ if(vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0)
+ remove_vert_defgroup(ob, dgroupflip[j], vertsflipped[a]);
+ }
+ }
+
+ /* fill right hand side */
laplacian_begin_solve(sys, -1);
for(a=0; a<me->totvert; a++)
@@ -640,24 +661,39 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numbones,
laplacian_add_right_hand_side(sys, a,
sys->heat.H[a]*sys->heat.p[a]);
+ /* solve */
if(laplacian_system_solve(sys)) {
+ /* load solution into vertex groups */
for(a=0; a<me->totvert; a++) {
solution= laplacian_system_get_solution(a);
-
- if(solution > WEIGHT_LIMIT)
- add_vert_to_defgroup(ob, dgrouplist[j], a, solution,
- WEIGHT_REPLACE);
- else
- remove_vert_defgroup(ob, dgrouplist[j], a);
-
- /* do same for mirror */
- aflip = (dgroupflip)? mesh_get_x_mirror_vert(ob, a): 0;
- if (dgroupflip && dgroupflip[j] && aflip >= 0) {
+
+ if(bbone) {
+ if(solution > 0.0f)
+ add_vert_to_defgroup(ob, dgrouplist[j], a, solution,
+ WEIGHT_ADD);
+ }
+ else {
if(solution > WEIGHT_LIMIT)
- add_vert_to_defgroup(ob, dgroupflip[j], aflip,
- solution, WEIGHT_REPLACE);
+ add_vert_to_defgroup(ob, dgrouplist[j], a, solution,
+ WEIGHT_REPLACE);
else
- remove_vert_defgroup(ob, dgroupflip[j], aflip);
+ remove_vert_defgroup(ob, dgrouplist[j], a);
+ }
+
+ /* do same for mirror */
+ if(vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
+ if(bbone) {
+ if(solution > 0.0f)
+ add_vert_to_defgroup(ob, dgroupflip[j], vertsflipped[a],
+ solution, WEIGHT_ADD);
+ }
+ else {
+ if(solution > WEIGHT_LIMIT)
+ add_vert_to_defgroup(ob, dgroupflip[j], vertsflipped[a],
+ solution, WEIGHT_REPLACE);
+ else
+ remove_vert_defgroup(ob, dgroupflip[j], vertsflipped[a]);
+ }
}
}
}
@@ -667,9 +703,26 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numbones,
thrownerror= 1;
break;
}
+
+ /* remove too small vertex weights */
+ if(bbone && lastsegment) {
+ for(a=0; a<me->totvert; a++) {
+ weight= get_vert_defgroup(ob, dgrouplist[j], a);
+ if(weight > 0.0f && weight <= WEIGHT_LIMIT)
+ remove_vert_defgroup(ob, dgrouplist[j], a);
+
+ if(vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
+ weight= get_vert_defgroup(ob, dgroupflip[j], vertsflipped[a]);
+ if(weight > 0.0f && weight <= WEIGHT_LIMIT)
+ remove_vert_defgroup(ob, dgroupflip[j], vertsflipped[a]);
+ }
+ }
+ }
}
/* free */
+ if(vertsflipped) MEM_freeN(vertsflipped);
+
RE_ray_tree_free(sys->heat.raytree);
MEM_freeN(sys->heat.vface);