Bone scaling problems
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 07/11/2004 at 09:35, xxxxxxxx wrote:
A more systematic view of the problem. The legs, unscaled, are symmetric. Scaled, well, what can I say?
1. This seems to only be an issue when the scaling is not overall (varying axis scales).
2. Scales are compensated down the bone hierarchy - even when setting Global scale values (i.e.: parent = 0.8, child = 1.0, therefore, child is set to 1.2 by C4D). 'pscale' in the previous code example rectifies this.
Correct, no scaling:
Incorrect, scaling:
Here's the rigged Ant prior to transformations being applied (to illustrate WHY transformations must be applied to the fixed bone hierarchy) :
Robert
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 07/11/2004 at 09:44, xxxxxxxx wrote:
Look, I've read through the "Matrix" tutorial to get C4D's take on this and even tried the SetGlobalNN() approach. The results were identical - which goes to show that, yes, I do know what I'm doing. Matrices are child's play compared to some of the math having been dealt with. Basic, good approach to transformations: scale, rotate, translate. This is the standard mantra and the order in which to apply transformations from default (untransformed) in world coordinates. Ah, but fixed bone hierarchies aren't default, are they? They are another beast altogether and no one will describe the beast. Does anyone really understand (even at Maxon) how the beast operates from a programmatic p.o.v.?
I cannot fix or compensate for that which there is insufficient information. Please decrease my ignorance.
Robert
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 08/11/2004 at 03:54, xxxxxxxx wrote:
Hmm, yes the second pair of images do look strange. From the looks of it, it should be possible to reproduce this problem with only two fixed bones. Have you worked on such reduced instances? Then please send the code and scene to [email protected].
Otherwise I'll try to make one myself and see if I get the same behaviour. Am I right that the problem is that when you add the MatrixSclae() factor, the rotation of the child bone will change? Could you give some typical values for the other parameters, for example the ones from the second leg? -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 08/11/2004 at 08:57, xxxxxxxx wrote:
I have not done a simplified instance, but will endeavor to do so 'in the spirit' of the code and circumstances that cause this problem.
Yes, when the MatrixScale() factor is added, the rotation of the bones will change (not sure if this is cascading from parent to child, but it is a possibility). I have attempted to traverse the hierarchy in reverse (from children to parent) using a separate Scale traversal (both before and after traversal for the other transformations) to see if parental influence could be mitigated, but to no avail.
You could probably extrapolate the general rotations from the last image (untransformed rig) to the image before it. The scalings are along the bone length, so that the other two are 1.0 - e.g.: (1.0, 1.0, 0.85). I transform the bones into the "untransformed" rig as in the last image prior to fixing them. The matrices for each bone are then stored as "Default" from which to apply further "Pose" transformations (the ones giving me hell). But, as can be seen in that line of code, the entire matrix is rebuilt for "Pose" transformations (position and rotation from "Default" are included as position additions and HPBToMatrix(vrot), respectively. Default position and rotation are extracted from Global Matrix). To get to the point, each bone is scaled from its base position (at the origin, length down the Z-axis), Pose rotated, Default rotated (this order, albeit counterintuitive, is the only one that works - my assumption is there is something to the fact that I extract the Default rotation from the Global Matrix as HPB but must use XYZ rotations for Pose rotation), and then Default+Pose translated.
One very interesting thing to note (which is my latest direction of attack) is that this only affects bones that are oriented along the negative X-axis (the Ant's right legs). It is probably the case for the -Y-axis and -Z-axis, but have not had an occassion to have non-homogenous scaling on these axes on test files yet. The positive X-axis bones (Ant's left legs) are handled correctly.
I will try to get you a set of values for a left and right leg for reference and post it here. When I have a working reduced example, I will sent it to the email that you supplied.
Thanks Mikael,
Robert -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 08/11/2004 at 09:44, xxxxxxxx wrote:
Here are the values for the entire middle left and right legs:
<CODE>
Angles in degrees
Rotation order is important [X]YZ for all. Length along bracketed axis.
origin : position vector, start of bone (Global)
endPoint : position vector, end of bone (Global) - used to determine BoneLength*** MIDDLE RIGHT LEG
rMidCollar
{
scaleX 1
scaleY 1
scaleZ 0.85
rotateX -8
rotateY -18
rotateZ 26
translateX 0.032
translateY 0.064
translateZ -0.03
endPoint -0.087872 0.009406 -0.09408
origin -0.042121 0.008741 -0.093
}rMidShldr
{
scaleX 0.75
scaleY 1
scaleZ 1
rotateX 0
rotateY 9
rotateZ -75
translateX 0
translateY 0
translateZ 0
endPoint -0.267611 0.009919 -0.092555
origin -0.087872 0.009406 -0.09408
}rMidForeArm
{
scaleX 0.85
scaleY 1
scaleZ 1
rotateX 0
rotateY 0
rotateZ 132
translateX 0
translateY 0
translateZ 0
endPoint -0.409466 0.009942 -0.092791
origin -0.267611 0.009919 -0.092555
}rMidHand
{
scaleX 0.8
scaleY 1
scaleZ 1
rotateX 0
rotateY 0
rotateZ -35
translateX 0
translateY 0
translateZ 0
endPoint -0.526319 0.009953 -0.092602
origin -0.409466 0.009942 -0.092791
}rMidFinger1
{
scaleX 1
scaleY 1
scaleZ 1
rotateX 0
rotateY 0
rotateZ -4
translateX 0
translateY 0
translateZ 0
endPoint -0.551226 0.009953 -0.092602
origin -0.526319 0.009953 -0.092602
}rMidFinger2
{
scaleX 1
scaleY 1
scaleZ 1
rotateX 0
rotateY 0
rotateZ -4
translateX 0
translateY 0
translateZ 0
endPoint -0.577751 0.010033 -0.092602
origin -0.551226 0.009953 -0.092602
}rMidFinger3
{
scaleX 1
scaleY 1
scaleZ 1
rotateX 0
rotateY 0
rotateZ -5
translateX 0
translateY 0
translateZ 0
endPoint -0.601401 0.010111 -0.092602
origin -0.577751 0.010033 -0.092602
}rMidFinger4
{
scaleX 1
scaleY 1
scaleZ 1
rotateX 0
rotateY 0
rotateZ -8
translateX 0
translateY 0
translateZ 0
endPoint -0.633879 0.010111 -0.092602
origin -0.601401 0.010111 -0.092602
}*** MIDDLE LEFT LEG
lMidCollar
{
scaleX 1
scaleY 1
scaleZ 0.85
rotateX -8
rotateY 18
rotateZ -26
translateX -0.032
translateY 0.064
translateZ -0.03
endPoint 0.087872 0.009406 -0.09192
origin 0.042121 0.008741 -0.093
}lMidShldr
{
scaleX 0.75
scaleY 1
scaleZ 1
rotateX 0
rotateY -9
rotateZ 75
translateX 0
translateY 0
translateZ 0
endPoint 0.267611 0.009919 -0.093445
origin 0.087872 0.009406 -0.09192
}lMidForeArm
{
scaleX 0.85
scaleY 1
scaleZ 1
rotateX 0
rotateY 0
rotateZ -132
translateX 0
translateY 0
translateZ 0
endPoint 0.409466 0.009942 -0.093208
origin 0.267611 0.009919 -0.093445
}lMidHand
{
scaleX 0.8
scaleY 1
scaleZ 1
rotateX 0
rotateY 0
rotateZ 35
translateX 0
translateY 0
translateZ 0
endPoint 0.526319 0.009953 -0.093398
origin 0.409466 0.009942 -0.093208
}lMidFinger1
{
scaleX 1
scaleY 1
scaleZ 1
rotateX 0
rotateY 0
rotateZ 4
translateX 0
translateY 0
translateZ 0
endPoint 0.551226 0.009953 -0.093398
origin 0.526319 0.009953 -0.093398
}lMidFinger2
{
scaleX 1
scaleY 1
scaleZ 1
rotateX 0
rotateY 0
rotateZ 4
translateX 0
translateY 0
translateZ 0
endPoint 0.577751 0.010033 -0.093398
origin 0.551226 0.009953 -0.093398
}lMidFinger3
{
scaleX 1
scaleY 1
scaleZ 1
rotateX 0
rotateY 0
rotateZ 5
translateX 0
translateY 0
translateZ 0
endPoint 0.601401 0.010111 -0.093398
origin 0.577751 0.010033 -0.093398
}lMidFinger4
{
scaleX 1
scaleY 1
scaleZ 1
rotateX 0
rotateY 0
rotateZ 8
translateX 0
translateY 0
translateZ 0
endPoint 0.633879 0.010111 -0.093398
origin 0.601401 0.010111 -0.093398
}
</CODE>Robert
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 08/11/2004 at 09:47, xxxxxxxx wrote:
I should also add that you may want to scale the position values by 1000 since they are in their default units which tend to be too small for C4D.
Z-axis position values are negated.
Z-axis rotation values are negated when the bone direction is along a negative axis (since Z is negated in general, it has the inverse situation).Robert
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 10/11/2004 at 02:22, xxxxxxxx wrote:
You mail server does not seem to want me to help you. It says:
> Sorry. Your message could not be delivered to:
> vp***nd.com
> DATA
> Received: 500 Mail appears to be unsolicited -- send error reports to [email protected]
I'll post the mail here instead:
Okay, I managed to reproduce the problem now. First of all, this does not seem to be a C4D problem, or a problem with bones. The same thing happens with null objects for example. Rather it's a problem with the mathematics involved, specifically leaving the orthonormal matrix domain. (Making it, strictly speaking, outside of the domain of developer support.)
When you scale the parent bone non-uniformly (by different amounts in X/Y/Z), then the mg matrix of the rotated child bone will no longer be orthogonal. Its axes do no longer form the angle 90° with each other. This means for example that its rotation state isn't fully captured by MatrixToHPB(). This is of course also why you see that the scale has changed from Vector(1.0) in TransformBone(). When you do GetMg(), the scale you just set in the parent the last time TransformBone() was called is included.
There are several ways to work around this. For example, you could do the calculations without putting the bones into their hierarchy and only put them there when everything's done. You'd then have to handle the hierarchy transformations manually, and could choose to only propagate the positional influence of the non-uniform scaling.
You could also do a separate TransformScale() pass backwards after the normal pass, so that the scaling of the children is done first.
Of course all workarounds are pointless without knowing how it's done in Poser. Do you have a C4D bone rig that matches how it looks in Poser, or do you know how the scale is handled there? (I guess this is a chicken and egg problem...)
Mikael Sterner
Developer Support
PS. When debugging these matrix problems I find a function like this helpful:void MakeDummyObject(Matrix mg, String name) { BaseDocument* doc = GetActiveDocument(); BaseObject* obj = BaseObject::Alloc(Onull); BaseObject* parent = doc->SearchObject("Dummies"); if (!parent) { parent = BaseObject::Alloc(Onull); parent->SetName("Dummies"); doc->InsertObject(parent, NULL, NULL); } doc->InsertObject(obj, parent, NULL); obj->SetName(name); obj->SetMg(mg); }
You just give it an mg and you can then see what it represents by selecting the created null object.
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 10/11/2004 at 09:04, xxxxxxxx wrote:
Sorry about the email - I expected this. Seems the only way to get mail through is for me to send mail out or physically add to the whitelist (it's a Bayesian filter on the server).
Yes, this is what I suspected. The departure from orthonormality was noticed and why I suspected as much.
Have no idea how Poser does most of anything. Curious Labs surely will not give up program algorithms - I've heard something about an 'SDK' for some $10K - I'll pass. It is very difficult doing this conversion process in the dark. And knowing their methodology more accurately would only slightly reduce the difficulty since Poser's and C4D's methodologies are vastly different. As far as I can discern, even CL's free plugin for R7 is just an encapsulation of their own code that then basically passes an exported polygonal object with materials and PLA keyframes into C4D. The result is not a live Poser object, but a C4D static or animated mesh. I'm, of course, trying to recreate a live Poser object.
With no or uniform scaling, yes, I have compared exported posed Poser figures to overlayed Poser figures loaded by my plugin. In this case, they match.
I will try your suggestions. The backwards TransformScale() was already tried, but maybe a new understanding of the processes causing the issue will change the results.
Back to the grind.
Thanks, Mikael
P.S.: I've sent you a private message about the email server. -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 10/11/2004 at 11:49, xxxxxxxx wrote:
One last question before grinding. :0)
Would there be any merit to setting the Obase properties (e.g.: ID_BASEOBJECT_GLOBAL_POSITION or ID_BASEOBJECT_POSITION) for the bones instead of using the SetMg() process? My thinking, albeit very warm and fuzzy, is that C4D would then handle these issues in the background - in the same fashion it does with interactive user changes of these values - allaying any of the problematic results.
Thanks,
Robert -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 11/11/2004 at 16:57, xxxxxxxx wrote:
Just thought to let you know that I've found a solution - one that doesn't require reverse hierarchy traversal, separate scale methods, or other painful approaches.
// Transform vscale = ppgscale * Scalar; vscale.x *= Scale.x; vscale.y *= Scale.y; vscale.z *= Scale.z; SetGlobalRotation(boneObject, MatrixToHPB(HPBToMatrix(vrot) * mrot)); SetGlobalScale(boneObject, vscale); SetGlobalPosition(boneObject, vpos); boneObject->Message(MSG_UPDATE);
I implemented all of the global matrix methods and, with some trial-and-error, found that this works.
An image for your patience and assistance!
Thanks,
Robert -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 14/11/2004 at 10:53, xxxxxxxx wrote:
That's great.