Forum Discussion

🚨 This forum is archived and read-only. To submit a forum post, please visit our new Developer Forum. 🚨
Matlock's avatar
Matlock
Honored Guest
12 years ago

GetPredictedOrientation() causes shear on roll

Quatf hmdOrient = poculussensor->GetPredictedOrientation();
Matrix4f View = Matrix4f(hmdOrient);

If you use this matrix to render, yaw, and pitch work as intended, but of you roll(twist) your head, the scene shears.

as you can see I am not using the postprocess shaders now.
But this seems to be a problem when the quat is converted to a matrix. Maybe the matrix is not orthogonal.

here is my basic scene:


At 45 degrees, the tree and fence is no longer perpendicular to ground


At 90 degrees, it looks correct, but it is squashed, half height.


Any ideas? Is this the matrix I am supposed to use?
The sample programs convert the oculus matrix to euler angles, and then recreate a new matrix.
Is this because the matrix provided by oculus is wrong, or non orthogonal?

8 Replies

  • Check if the quaternion is unit length. A non unit length quaternion can do all kinds of freaky stuff (skewing and distorting), while a unit length one will be a simple rotation.

    Hmm. Looking at the code, the oculus sdk converts a quaternion to a matrix using this code:
           return Matrix4f(float(ww + xx - yy - zz),  float(T(2) * (x*y - w*z)), float(T(2) * (x*z + w*y)),
    float(T(2) * (x*y + w*z)), float(ww - xx + yy - zz), float(T(2) * (y*z - w*x)),
    float(T(2) * (x*z - w*y)), float(T(2) * (y*z + w*x)), float(ww - xx - yy + zz) );

    But the standard formula for converting is:
    1 - 2*qy2 - 2*qz2 	2*qx*qy - 2*qz*qw 	2*qx*qz + 2*qy*qw
    2*qx*qy + 2*qz*qw 1 - 2*qx2 - 2*qz2 2*qy*qz - 2*qx*qw
    2*qx*qz - 2*qy*qw 2*qy*qz + 2*qx*qw 1 - 2*qx2 - 2*qy2

    Everything is the same except the main diagonal.
  • Matlock's avatar
    Matlock
    Honored Guest
    ok so the length of the quaternion ranges from 0.99999970 - 1.0000091

    I tried your alternative quaternion to matrix, however the results are the same, shear on roll.

    How am I the first person to try to use this matrix for rendering?
    Why do the oculus demos not use this matrix directly.?
    Anyone??????!!!!!
  • Matlock's avatar
    Matlock
    Honored Guest
    I tried Ortho-normalizing the matrix, but the effect is the same...

    ANYONE?
  • The shear is caused by incorrect aspect ratio, but the aspect ratio is handled by the projection matrix, not the modelview matrix. You need to make sure you're not modifying the projection matrix with the matrix you get out of sensor fusion.
  • Matlock's avatar
    Matlock
    Honored Guest
    Thank you jherico for the information
    You were correct that the aspect ratio was causing the shear.

    I still have some other problem.
    Now the camera seemingly moves on roll, even though the [12][13][14] elements of the view matrix are fixed(pre invert). Ill repost it as a different question if I cant figure it out.

    anyways, oculus should hire jherico. :!:
  • "matlock" wrote:
    I still have some other problem.
    Now the camera seemingly moves on roll, even though the [12][13][14] elements of the view matrix are fixed(pre invert). Ill repost it as a different question if I cant figure it out.


    if your camera is moving when you roll the device, there's probably an issue with how you're applying the modelview offset and or the Rift orientation to the modelview matrix. Typically this means you're doing a post-multiplication where you should be doing pre-multiplication, or you're compounding the matrices in the wrong order.

    Suppose you have a matrix which represents the player position:

    glm::mat4 player;


    This represents the player's position and the direction they're facing, best thought of as the direction their torso is facing really. In order to convert that to a view matrix, you have to invert it:

    glm::mat4 view = glm::inverse(player);


    In order to apply the Rift orientation to that, you have to pre-multiply it by the rift orientation. Pre-multiplying means that the Rotation is applied in the coordinate system of the existing matrix. If you post-multiply instead, you end up rotating the player position around the world axis.

    view = riftOrientation * view;


    In order to get stereo seperation, you have to apply the per-eye modelview offset on top of that. Again, this is a pre-multiplication, which should occur after you've already applied the Rift orientation to the view matrix:

    view = perEyeModelviewOffset * view;


    At this point, you've completely set up the view matrix. If you draw a cube at the origin of the world, it will appear there relative to wherever the player is. Subsequent operations of the matrix will move things around relative to that world origin, hence the view matrix is now the modelview matrix, because operations applied to it have an effect on the models in the world.

    I've written up a blog post on how to do the setup of the projection and modelview matrices, and a (hopefully) easy way to test to make sure that you're getting the correct results.

    "matlock" wrote:
    anyways, oculus should hire jherico. :!:


    Heh. Well, in lieu of that, you can always support me directly by buying my book. :D
  • "matlock" wrote:
    I will in fact buy your book, jherico


    Thanks! If you happen to have a few thousand friends working on the Rift, you should tell them to buy copies too!