-
Notifications
You must be signed in to change notification settings - Fork 1.3k
AnimatedTriangle shouldn't rotate around a complete circle? #185
Comments
Rotation quaternions should be interpolated using slerp algorithm. It enforces path between endpoints. There's notion about that in the spec. |
Slerping traverses the same set of points as lerping, just at a different speed. You still can't produce a value > 0.707 or < -0.707 in the Z component by interpolating (0, 0, 0.707, -0.707) and (0,0,0,1). Slerping can go either the long or short way round. Wikipedia notes this The choice of whether to slerp is independent of the choice of whether to always go the short way by negating one of the quaternions. It also seems strange to me that the direction of rotation would be completely changed by switching to CUBIC interpolation (and giving appropriate tangents). |
I'd need some time to wrap my head around the meaning of CUBIC interpolation for quaternions, so I'll have to put this aside for now. Regarding the sample model: Preventing the "long path", as you described it by quoting from wikipedia, seems to be the common approach. At least, all viewers at https://github.com/cx20/gltf-test#simple-models-for-testing-individual-features (that show a proper animation at all) do the rotation as it is shown in the GIF. The GIF was created using JglTF, where the quaternion interpolation is implemented like this, which in turn is based on the implementation in the Java "vecmath" library, which is mirrored here: https://github.com/hharrison/vecmath/blob/master/src/javax/vecmath/Quat4f.java#L609 It contains an implementation note
which seems to exactly refer to the case that you described. @lexaknyazev Maybe it could make sense to add a hint/implementation note in the spec? Something that basically says that the slerp interpolation of quaternions always has to take the shorter path (referring to the quote from wikipedia). |
Cubic interpolation for quaternions is just cubic interpolation of the XYZW components followed by normalization of the quaternion (just like lerping). But the precise interpolation method doesn't matter much because (this is what I was getting at with my argument about Z): The rotation quaternions shown in the GIF for times t=0.75 to t=1.0 lie in either U1 = {0}×{0}×[0, 0.707]×[-1, -0.707] or in U2 = -U1 = {0}×{0}×[-0.707, 0]×[0.707, 1]. These two sets are disconnected. Let f(t), t in [0.75, 1.0], interpolate between f(0.75) = (0, 0, 0.707, -0.707) and f(1.0) = (0, 0, 0, 1). If f is continuous (as lerp, slerp, and cubic spline are), then its image is connected, but then it is a contradiction that it contains both (0, 0, 0.707, -0.707), which is in U1, and (0, 0, 0, 1), which is in U2. (If we always choose the short way, f is not always continuous; it may have a jump discontinuity at its right end-point.) I opened an issue on the main spec repo at KhronosGroup/glTF#1395. |
I have a problem with the sample GIF shown for the AnimatedTriangle sample.
Here are the input/output lists for the rotation curve in the model (rounded off). The output targets the triangle's rotation quaternion.
So the triangle rotates around in the same direction as time passes from t=0.0 to t=0.75, but I expected the triangle to then rotate in the opposite direction, more quickly, and traverse again, in the reverse direction, the arc it had just taken until it returns to its original position, since this is the path which interpolates between (0.0, 0.0, 0.707, -0.707) and (0.0, 0.0, 0.0, 1.0).
Instead, the sample GIF shows it continuing to rotate in the same direction as it has been, and at the same speed, until it reaches its original position again. This is what I would have expected if the final output were (0.0, 0.0, 0.0, -1.0). As it is, this appears impossible, since at time, say, t=0.95, the quaternion's Z must be greater than 0.707 (or less than -0.707) for this to happen, but that can't result from interpolating between 0.707 and 0.0.
But the viewer also shows it completing a complete circle, which is extremely confusing to me. The only explanation I could think of is that the viewer is dynamically choosing between the stored quaternion q, and -q, based on which is closer to the last point; or it converts to matrices before interpolating.
The text was updated successfully, but these errors were encountered: