- Home /
How do I blend two BoneWeights?
Or fake it?
I'm creating a new vertex C, X% of the way between vertices A and B of a skinned mesh. C needs to stay between A and B such that they form a single visual edge (A-C-B) - or, as close as possible.
I can put the vertex in place but I'm not sure how to get it to stay there. I need to give C a BoneWeight which is a weighted average of A and B's weights. Often, this is pretty trivial - if A and B are on the same bone, then the new BoneWeight is just X% weight A + (1-X%) weight B. But what happens if A is affected by bones 0-3 and B is affected by bones 2-5? A vertex can only be weighted by four bones max. :confusedface:
Here's the uncommented code dump I have currently, which works great when the bones of two vertices already match exactly. If more bones than the quality settings allow are affecting a vertex, I get poor results. Is there any way around this and/or is my code doing silly things it shouldn't?
private class ArrayBoneWeight {
// makes it use arrays so i don't break my fingers typing
var weights:float[];
var bones:int[];
...
static function Combine(l:ArrayBoneWeight,r:ArrayBoneWeight,left:float,bones:int) : ArrayBoneWeight {
var right : float = 1-left;
var out : ArrayBoneWeight = new ArrayBoneWeight();
out.bones =[l.bones[0],l.bones[1],l.bones[2],l.bones[3],-1,-1,-1,-1];
out.weights=[l.weights[0]*left,l.weights[1]*left,l.weights[2]*left,l.weights[3]*left,-1,-1,-1,-1];
var lix : int;
var iix : int;
var tmp : float;
for ( lix = 0; lix < 4; lix++ ) {
for ( iix = 0; iix < 8; iix++ ) {
if ( out.bones[iix] == -1 ) break;
if ( out.bones[iix]==r.bones[lix] ) {
out.weights[iix]+=r.weights[lix] * right;
break;
}
}
if ( iix < 8 && out.bones[iix] == -1 ) {
out.bones[iix] = r.bones[lix];
out.weights[iix]=r.weights[lix]*right;
}
}
for ( lix = 1; lix < 8; lix++ ) {
while ( out.weights[lix] > out.weights[lix-1] ) {
tmp=out.weights[lix]; out.weights[lix]=out.weights[lix-1];out.weights[lix-1]=tmp;
iix=out.bones[lix];out.bones[lix]=out.bones[lix-1];out.bones[lix-1]=iix;
if ( lix > 1 ) lix--;
}
}
var bwgt : float = 0;
for ( lix = 0; lix < bones; lix++ ) { bwgt+= out.weights[lix]; }
bwgt = 1/bwgt;
for ( lix = 0; lix < 8; lix++ ) { out.weights[lix]=(lix>=bones)?0:out.weights[lix]*bwgt; }
return out;
}
}
// bones is the current bone quality setting - only that many bones can affect a vertex
static private function AverageBoneWeight( left : BoneWeight, right : BoneWeight, dist : float, bones : int ) : BoneWeight {
var bw : BoneWeight = new BoneWeight();
var negd : float = 1-dist;
var l : ArrayBoneWeight = new ArrayBoneWeight(left);
var r : ArrayBoneWeight = new ArrayBoneWeight(right);
l = ArrayBoneWeight.Combine(l,r,dist,bones);
return l.ToWeight();
}
Your answer
![](https://koobas.hobune.stream/wayback/20220613100142im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Using multiple custom water planes together (Welding multiple planes together) 1 Answer
normalising the vertices of a cube mesh 0 Answers
How to Avoid Unity Adding Vertices to Object? 1 Answer
How do I connect my vertices in my mesh 1 Answer
How to reduce polygon count? I have meshes from pointclouds. 0 Answers