Advertisement

Blending Matices using weights

Started by May 03, 2005 02:10 PM
4 comments, last by McCLaw 19 years, 4 months ago
Hi All I am in the process of implementing a Bone Blending animation class, but I have hit a math snag. I have gotten to the point of getting all the interpolated matrices from the active animations, but I am unsure how to change them according to the weight of each animation, and then how to merge them. PS: My math knowledge sucks, so speak to me like i'm a three year old ;) Any ideas will be greatly appreciated
Can you post some code so I can get a better insight in what you want to make.
And explain what you want to create.
Live the life you lovelove the life you lead
Never be afraid of doing tasks you are not familiar with. Noah's Ark was built by an amateur. Professionals have built the Titanic.
You should never let your fears become the boundaries of your dreams.
Advertisement
I found looking at the docs and source of cal3d very useful in working this out.

If you can interpolate to get a current frame for each animation, you know how to interpolate I take it, so just do the same thing for each joint in each weighted animation.

Weighting multiple animations and making sure they are weighted correctly and sum to 1 is a bit more involved, but I recomend looking how cal3d does it.
[size="1"]
Hi mrbastard

Thanx for the reply :)

I used to use a version of cal3d that I converted to Delphi, but it proved to be waaayyyy to slow, so I decided to write my own.

I figured out a way of doing this with Nitrogens help (Thanx Dude):D

SetLength(FMergedMatrices,0);   if Count > 0 then // We have animations to check   begin     for i := 0 to Count - 1 do     begin       lAnim := Anims;       if lAnim.Active then       begin         lAnim.CalulateCurrentBoneMatrix(FCurrentTime); // Get the interpolated matrix list         // Merge With Other Bone Matrices         for j := 0 to Length(lAnim.MergedMatrices) - 1 do         begin           lMergedMatrix := lAnim.MergedMatrices[j];           // If FMergedMatrices is too small, make it bigger           if Length(FMergedMatrices) < j + 1 then           begin             SetLength(FMergedMatrices,j + 1);           end;           // Scale the matrix according to the Influence the animation has on the mesh            ScaleMatrix(lMergedMatrix,lAnim.Influence);           for n := 0 to 3 do           begin             // Concatinate the matrix to the other stored matrices             VectorAdd(lMergedMatrix[n],FMergedMatrices[j][n],FMergedMatrices[j][n]);           end;         end;       end;     end;   end;


Obviously this in only the first part of the process, I stil need to add individual bone weights into the algo to allow for feather blending.

The current code basically allows any number of interpolated frames in several animations to be blended by their influence (Value between 0 and 1)

I had a look at doing all the calculations per vertex, but that seemed way too expensive.(My thoughts: Rather do a 16 * amount of bones calculation then an undefined number of calculations for the number of vertices in the mesh) and then just apply the resulting matrix to the correct verts in the inverted mesh.

It seems that the same theory would apply to individual bone weights, but I'll only know once I have finished that :eek:

PS: I'm using the VectorGeometry.pas file from glscene if you know delphi.
Hello again. I can only vaguely follow the code you posted as I don't know delphi, but it looks to me like your bone weights may not always sum to 1.0; floating point round off means it's usually worth making the last weight (1.0-(all the other weights)). You probably take care of that outside the code you posted, but I thought I'd mention it just in case. :)

You're definately right to avoid doing anything per-vertex. My own way to do it is to do all the transforms on the skeleton to get the correct blended pose, and then apply the pose to the inverse-transformed vertices (in a vert shader...or that's how it will be once it's finished).

The other thing to think about is whether you need every animation to apply to every bone. For example a 'wave' animation would probably only affect the arm. The way I deal with this is to have an AnimationTrack for every joint affected by an animation, so only actual changes are applied and result in cpu work. Again, you may already be doing this, but from what you said about 16*bones I thought maybe not.

I'm leaving out multiple weighted bones per vertex for now - my artist friend uses milkshape a lot and milkshape only does one bone per vert. It also makes writing shaders much easier.
[size="1"]
Hi Dude

The lAnim.Influence is not actually the bone weight, but an indication of the complete effect of the animation on the final result.

The influence property is clamped between 0 and 1 for each animation to signify a total influence on the final product.

The actual bone weights must still be implemented in the code above, but will basically be a "slice" of the influence per animation.

This way, I can scale a complete animation by changing only one value, and the weights stay exactly the same.

I basically do the exact thing you do regarding the poses

When I call lAnim.CalulateCurrentBoneMatrix I am basically working out the final matrix list for that animation.

The resulting list is assigned to lAnim.MergedMatrices

Quote: The other thing to think about is whether you need every animation to apply to every bone. For example a 'wave' animation would probably only affect the arm. The way I deal with this is to have an AnimationTrack for every joint affected by an animation, so only actual changes are applied and result in cpu work. Again, you may already be doing this, but from what you said about 16*bones I thought maybe not.


Basically my thinking is that if any bone's weight in an animation is 0
(Or perhaps close to zero), it will have no effect on the rest of the system, so can be set to a null matrix (All 0's) and then disregarded in the code posted in the previous post. Also, since a weight of 0 will make the resulting matrix 0, no interpolation is needed either.

I hope all of this makes sense :S

This topic is closed to new replies.

Advertisement