math & physics
jmab at January 7th, 2012 17:02 — #1
I'm currently trying to solve the problem of creating a bounding volume (OBB or capsule) in the middle of my bone for ragdoll creation. I suppose it's really just a general maths problem, that my paltry maths skills can't overcome. I have a position (the head of the bone), a rotation (quaternion decomposed from the head's transformation matrix) and a bone length (a scalar).
So what is the maths for finding a position given a starting position, rotation and scalar length? Or in terms of this problem, how do I find the midpoint of a bone?
I'm using C++ and XNAMath by the way.
Searching on the internet, I can see that every sample I've seen just uses either the parent transformation of the current bone, or the first child transformation of the current bone, to calculate the midpoint. I could go that route too, but then there are going to be bones missing out from being in the ragdoll - either the root bone (because it has no parent) or every bone at an extremity (because they have no children). I'm thinking there must be a way to calculate the midpoint of a bone without using it's parent or child???
Thanks in advance,
reedbeta at January 7th, 2012 20:42 — #2
Assuming that the bone extends along the X axis in its local space, couldn't you just create the vector (0.5 * bone_length, 0, 0) and transform to world space using the bone matrix?
jmab at January 7th, 2012 23:06 — #3
rouncer at January 7th, 2012 23:06 — #4
Thats what I was thinking... isnt this really easy? I would have said that exact thing myself but I thought the solution couldnt be that simple...
jmab at January 8th, 2012 00:03 — #5
Yes, I sometimes get stuck on the easy stuff. Here's my code, if anyone is as inept at maths as me and needs it:
// Decompose the bone head world matrix.
XMVECTOR boneHeadScale, boneHeadRotation, boneHeadPosition;
if (!XMMatrixDecompose(&boneHeadScale, &boneHeadRotation, &boneHeadPosition, worldMatrix))
Log::Warn(L"Failed to decompose bone world matrix.");
// Create the mid-point in local space.
XMVECTOR midPoint = XMVectorSet(0.0f, m_Bones[i].HalfLength, 0.0f, 0.0f);
// Transform the mid-point to world space.
midPoint = XMVector3TransformNormal(midPoint, worldMatrix) + boneHeadPosition;
// Construct the bounding volume world matrix.
worldMatrix = XMMatrixTransformation(XMVectorZero(), XMQuaternionIdentity(), boneHeadScale,
XMVectorZero(), boneHeadRotation, midPoint);
The ragdoll currently looks like this:
I was thinking of letting the artist define the bone volume "width" and "height" in the 3d editor, however I'm now thinking I should be able to automate this too - I should be able to just to min/max calculations on all of the vertices in each bone's vertex group to calculate the volume. Anyone tried this before, or should I just let the artist define the rest?
reedbeta at January 8th, 2012 00:47 — #6
What are you using the bone width and height for? Collision volumes? Calculating the bounding box of the vertices skinned to the bone should give a reasonable result, but it may be slightly too large; character physics can look better if the characters are allowed to interpenetrate just a little, since flesh isn't totally rigid. You might try scaling the generated box down to 90% of its original size, or something like that.
rouncer at January 8th, 2012 14:06 — #7
Ah funny! Im doing something almost exactly the same as you are in my engine, and yes, I use my ragdolls for collision detection too.