New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
testcase and fix for issue #1388 (Quaternion javadoc is misleading) #1451
testcase and fix for issue #1388 (Quaternion javadoc is misleading) #1451
Conversation
X-Z-Y order... meaning that if you want to duplicate that rotation in steps, first you rotate around Y then you rotate around Z and then you rotate around X. We should be explicit because even though its common to state rotation from "child up", it's backwards in most conversational descriptions of rotations. For example, to duplicate the same rotation with separate nodes parent, child, grandchild... rotate parent Y, rotate child Z, rotate grandchild X. And even though JME is Z forward, it chose to implement default rotation order as if it were X forward... which is unfortunate because it means Z (roll) is basically useless for 99% of games that might have otherwise been able to use the angle triple. Such are the joys of 'backwards bugpatability'. |
Child-up or parent-down ordering only matter in a scene graph, and there's no scene graph here. In order to duplicate a If "X-Z-Y" means something different to you, then I should rephase the documentation to say "X then Z then Y" instead of "X-Z-Y". |
That looks good to me @stephengold |
re: "In order to duplicate a fromAngles() rotation in steps, you would actually apply X then Z then Y. (See the test case.) If "X-Z-Y" means something different to you, then I should rephase the documentation to say "X then Z then Y" instead of "X-Z-Y"." Here is kind of where we get to the crux of the confusion and how the context of the reader becomes super important because we've given them nothing to go on. Your test is multiplying the vector once by each quaternion which from that perspective is indeed going to be x then z then y. But if you are thinking about composing rotations (and why wouldn't you because fromAngles() IS composing a rotation) then it's backwards. For example, if you replace this code block:
With:
Then you get a different answer and the order is backwards.
Fixes the test again. Your test is treating the object like it's sitting on the desk in front of you. Rotate around X. Grab that and rotatearound Z, etc.. qy.mult(qz).mult(qx) is from the perspective of the object itself... rotate me around y then rotate me around z, etc.. This can be a more useful way of looking at rotations in the environment of a scene graph. Put another way, if you were trying to explain to a user what is happening, which looks right based on your javadoc:
Or:
This bottom up versus top down rotational ordering has been the subject of many a discussion and even involves post order versus pre-order quaternion/matrix multiplication and so on. So if we are going to talk about order then we need to talk about what order means. Or just provide a succinct example... given the nature of the method, you could do worse than showing how it would look if you multiplied the three separate calls together as:
Note: a small quibble with the test is that it's using fromAngleAxis() which might inadvertently be testing the difference between fromAngles() and fromAngleAxis(). (It's not but it could be.) |
Thank you for the detailed explanation. I agree that the javadoc should be clear and unambiguous. I thought I knew what Euler angles were, but I was mistaken. I'll come back and try again after I've done some more research into the various conventions for defining Euler angles. |
According to my reading, the formalism implemented in the The best way I've found to clarify the order (in which rotations are applied) is to distinguish "intrinsic" rotations (around movable body axes) from "extrinsic" rotations (around fixed world axes). For maximum clarity, I've documented the implementation both ways. If/when this PR is integrated, please perform a "squash and merge". |
Unless there's substantive discussion, I plan to self-integrate this PR in 24 hours. |
This PR corrects the documentation for 4 methods in
com.jme3.math.Quaternion
:fromAngles(float, float, float)
fromAngles(float[])
Quaternion(angles)
constructortoAngles(float[])
It also adds a test case which provides strong evidence that all 4 methods implement X-Z-Y rotation order.