Problem with Quaternions
I'm seeing some things I don't understand while converting a G8 armature from DAZ Studio to Blender:
I think I finally have understood what orientation is, and how to preserve it in Blender. If I take a G8 and set Left Thigh Bend to -90 in Daz Studio, and take the same exported G8 in Blender and rotate the Left Thigh Bone with rxx-90, the models look identical. So that much is good.
If I switch the rotation to Quaternion (WXYZ) in Blender, it correctly shows (0.707, -0.707, 0, -0) which is exactly what I would expect, cos(90/2) being .707 .
But if in DAZ Studio, I call getLocalRot() on the same bone, it instead gives me w x y z = (0.707107 0.697806 0.0973892 -0.0598513) and so DAZ does not even agree with itself... this is not a rotation of -90 degrees about the local x axis.
Can anyone explain the discrepancy?
Thank you...
Comments
With a little further experimentation, I find that if, in Blender, I instead rotate the Left Thigh Bend bone around the global x axis with rx-90 (instead of rxx-90), the quaternions values match the Daz Studio values much, much more closely. Could it really be that when you express the rotations as quaternions, the bone's orientation is ignored?
OK, this is very wierd, but it appears to be how DS actually behaves:
If you rotate a bone in the DS GUI with bend twist, and side-to-side, and presumably programmatically with Euler angles, the bone rotates around its oriented axes.
But if you rotate the bone by calling node->setLocalRot( qRot ); where qRot is a DzQuat, the bone rotates around its unoriented axes.
More experimentation is warranted, but as soon as I stopped orienting the exported bone in Blender, applying the WXYZ that DS reports to the bone in Blender ( y-up vs z-up notwithstanding, of course) causes the position to match quite perfectly.
I've came to the conclusion many months ago that Daz's euler-to-quat functions do not give the same results as other 3D modellers. So, I don't trust any euler-to-quat functions from Daz Studio's interface. If there's a function to set them directly without conversion, use it.
@Seven193 It may even have been your thread that I remembered that convinced me to not use Euler angles at all, only for orientation.
some of the DzQuat functions let you use a different order of rotation
I don't trust any functions that pass DzQuat, as it must be converted internally to euler angles.
So, I would avoid calling functions like these:
setLocalTransform( DzVec3 posLocal, DzQuat rotLocal, DzMatrix3 scaleLocal );
setWSTransform ( DzVec3 posWS, DzQuat rotWS, DzMatrix3 scaleWS );
To get around this, rotation can be set directly as euler angles:
getXRotControl().setValue( DzTime tm, Number val );
getYRotControl().setValue( DzTime tm, Number val );
getZRotControl().setValue( DzTime tm, Number val );
This is the only reliable way I've found of passing rotation data that doesn't change through conversion.