# DzQuats and Eulers

I'm trying to track down a problem, and I think it has something to do with the way Daz Studio converts eulers to quaternions, and vice versa.

``function doIt() { var DEG2RAD = Math.PI / 180; var RAD2DEG = 180 / Math.PI; var angles = new DzVec3(-20*DEG2RAD,0,0); var rot = new DzQuat( DzRotationOrder("XYZ"), angles ); print( "angles: " + angles ); print( "rot: " + rot );}doIt();Executing Script...angles: [-0.349066,0,0]rot: [0.173648,0,0,0.984808]Result: Script executed in 0 secs 31 msecs.``

This converts euler angles (-20,0,0) to a quaternion (0.173648, 0,0,0.984808), which I believe is wrong.

My very own code converts (-20,0,0)  to (-0.173648, 0,0,0.984808).  Note the negative sign for x.

I also tried this random online site:
https://www.andre-gaschler.com/rotationconverter/

and it also converts (-20,0,0)  to (-0.173648, 0,0,0.984808).

Why is Daz quaternion conversion so bad?

• Sounds like the coordinate systems for DS and your math are oriented differently.

• edited December 2021

My coordinate system is the same as Daz Studio, Y+ up, right-handed.  Daz Studio seems to be the one using bad math here.  It shouldn't be flipping the sign on that conversion.

Post edited by Seven193 on
• According to this: http://docs.daz3d.com/doku.php/public/dson_spec/format_description/units_coordinate_systems/start the coordinate system is RIGHT-handed. That could account for the difference

• Those docs describe the DSON file format.  Whether or not Daz Studio shares the same coordinate system as the DSON file format, it's not clear.  I do believe quaternion math works the same way in both coordinate systems.  Please show me proof otherwise.

• Which is more probable? That Daz Studio gets this fundamental calculation wrong and yet everything somehow still works, or that you get this fundamental calculation wrong, with nothing to suggest that you are correct besides your own egocentrism? Daz Studio can of course adopt whatever coordinate system it prefers without being "bad math" as long as it is "consistent math".

I would think it pretty obvious, but the proof you request is this: Go into Daz Studio and create a new cube. Move it in the positive x direction. It will move to the right. Move it in the positive y direction. It will move up. Move it in the positive z direction. It will move forward, towards you. Notice that you can orient your index finger, middle finger, and thumb of your RIGHT hand along these axes respectively, but you cannot with your left.

• edited December 2021

My proof is in my first post.  It doesn't matter whether Daz Studio is LH or RH, quaternion math works the same. A negative euler angle of (-20,0,0) should not produce a quaternion of (0.173648,0,0,0.984808).  That is flipping the x-axis.

Even more proof:
DzQuat is initialized correctly when using axis-angle:

``function doIt() { var DEG2RAD = Math.PI / 180; var RAD2DEG = 180 / Math.PI; var angle = 20*DEG2RAD; var axis = new DzVec3( -1,0,0 ); var rot = new DzQuat( axis, angle ); print( "axis: " + axis );  print( "angle: " + angle ); print( "rot: " + rot );}doIt();Executing Script...axis: [-1,0,0]angle: 0.3490658503988659rot: [-0.173648,0,0,0.984808]``

These two methods should compute the same quaternion.  They do not.

Post edited by Seven193 on
• You are right, it doesn't matter whether DS is left or right handed and the math is the same... within Daz Studio. It matters tremendously when you are comparing to external calculations, as you are doing. But given the new evidence you provided, all within DS, I agree there's something fishy going on.

Let's try some silly things:

1. Is there an undocumented restriction on the domain of the angles? i.e. what happens if you use 340 instead of -20?

2. Maybe there actually really is a bug in their Quaternion code. I can easily imagine the code optimizing for the trivial rotations parallel to an axis, which your example would trigger. So:

2a. Does it still happen with (0,-20,0) or (0,0,-20)?

2b. Does it happen with Euler angles with more than one non-zero component?

3. What about all the permutations of #1 and #2?

4. Maybe its the scripting? Could you by any chance write a dummy plugin in C++ to see if it still happens?

• edited December 2021

From what I can tell, every single euler component needs to be negated to get it to work correctly. So, if I want to pass (-20,-20,-20), I should pass (20,20,20) instead.

I printed out all angles, from 0 to 360, for each x,y,z component.  I got negated results for all of them.

I work in both script and C++, and they both give similar results.  When I started using scripting, I wasn't so sure how to pass enumerated values, but I think scripting can either use strings or constant values like:

var rot = new DzQuat( DzRotationOrder("XYZ"), angles );
var rot = new DzQuat( DzRotationOrder(0), angles );

but either way, the default order is XYZ, which is what I want.

``function doIt() { var DEG2RAD = Math.PI / 180; var RAD2DEG = 180 / Math.PI; for(var i=0; i &lt; 360; i++) {    var a = -i*DEG2RAD;    var angles = new DzVec3(a,0,0);    var rot = new DzQuat( DzRotationOrder("XYZ"), angles );    print( "i: " + i + ", rot: " + rot ); }}doIt();``

Post edited by Seven193 on
• Try looking at Thomas's Diffeomorphic code. I would swear I remember seeing some code having to deal with wierdness in the domain of the Euler Angles. Maybe message him and ask him to chime in in this topic... this would be useful for many people, and Thomas has probably figured it all out.

• If you know of any Daz script or C++ code that imports a full jointed skeleton with animation, I would be interested in that.  That was what I was trying to do when I got sidetracked.  I think this negated Euler trick fixes my immediate problem for now.

• Diffeo exports animations back to Daz, but I don't know if it does so via Quaternions. Good luck figuring out what I refer to as DSBS.

• Importing animation back into Daz Studio was asked as a request, but I don't think it was added:
https://bitbucket.org/Diffeomorphic/import_daz/issues/466/is-it-possible-to-import-differomorpic

But, if he did do something, he might be creating .duf files in DSON format and letting DS load it, rather than trying to load the data directly from within DS.  I would rather try to use DS script or C++ code.

• I wonder if there's sample code floating around anywhere... maybe mcasual's scripts? Maybe the dev who wrote Limb Stick? I still can't believe that something so so basic and fundamental doesn't work... there must be some basic assumption that your simple example violates that we just don't know about.

• Maybe I'm barking the wrong tree, not being a math whiz, but this article talks about switching coordinate systems with QuTernions

https://gamedev.stackexchange.com/questions/129204/switch-axes-and-handedness-of-a-quaternion

Just wondering if the "doesn't make a difference what the handedness" statement is true. (If I'm misunderstanding, apologies)

• The quaternion equations make assumptions about the handedness, just as we have to establish the convention of whether increasing angles is clockwise or counter-clockwise. In that sense, handedness absolutely matters.

But Seven193 points out that in his context, the constructor calculates a different answer not only from his independent calculations (where he could conceivably have made a handedness error, but apparently did not), but also from and independent alternative method wholly within DS (where we could reasonably expect the two methods to assume the same handedness).

As unlikely as it seems, it really does look like there is a bug in DzQuat(), or something undocumented about its usaage.

• Handedness affects the way geometry is displayed on the screen, so even if there was a small chance my coordinate system was different, I would have noticed it a long time ago, by importing something simple as a textured cube.  The faces would be pointing in the wrong direction.

My issue with quaternions is something different, something yet unexplained.

• @Seven193

Whenever I find something that I can't explain, the littany I hear is that no one from Daz monitors these forums, and I should submit a ticket. It has never gone unignored for me, but maybe try that?

• Sure, they answer tickets, but I don't see this being resolved anytime soon.

I did find a way to skip the conversion by sending the angles directly to the slider control instead:
https://www.daz3d.com/forums/discussion/542656/setorientation-issue

• Seven193 said:

I'm trying to track down a problem, and I think it has something to do with the way Daz Studio converts eulers to quaternions, and vice versa.

``function doIt() { var DEG2RAD = Math.PI / 180; var RAD2DEG = 180 / Math.PI; var angles = new DzVec3(-20*DEG2RAD,0,0); var rot = new DzQuat( DzRotationOrder("XYZ"), angles ); print( "angles: " + angles ); print( "rot: " + rot );}doIt();Executing Script...angles: [-0.349066,0,0]rot: [0.173648,0,0,0.984808]Result: Script executed in 0 secs 31 msecs.``

This converts euler angles (-20,0,0) to a quaternion (0.173648, 0,0,0.984808), which I believe is wrong.

My very own code converts (-20,0,0)  to (-0.173648, 0,0,0.984808).  Note the negative sign for x.

I also tried this random online site:
https://www.andre-gaschler.com/rotationconverter/

and it also converts (-20,0,0)  to (-0.173648, 0,0,0.984808).

Why is Daz quaternion conversion so bad?

I noticed this when I began using quaternions to perform DAZ Studio rotations a few years ago. I was puzzled by it myself, until a couple years afterward, I began studying Geometric Algebra. I believe that what DAZ Studio calls quaternions are actually bivectors (plus scalars), and that bivectors are nothing more than quaternions with negative x, y and z axes. In Geometric Algebra, when you multiply two vectors together, you get a bivector (plus a scalar), and the sign of the bivector components have the same minus signs you are seeing in the DzQuat. When you do the reverse (multiply a vector by a bivector), you get a vector back, and the sign of the components goes back to normal.

I assume there is (or was) some geometric algebra being used internally in DAZ Studio for various purposes, and that is why bivectors are being used, instead of just quaternions.

So, when creating of DzQuat using a vector and an angle, you just negate the components of the vector to get the corresponding quaternion.

When I first noticed this sign oddity, I thought at first that the coordinate system was wrong, but I did testing and saw that it was OK. Then I thought the quaternions used the JPL convention, but they don't.

• Wow... the documentation is literally worse than no documentation at all.

That would explain why I discovered quite by chance that I have to negate omega when assigning the "Quaternion"... it's because the vector part is oriented precisely in the opposite sense.

Thanks for the explanation!