Forum Discussion

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

Orientation for left handed coordinate system

Hi I was just looking through the docs and api, and noticed the rift returns only quaternion for right handed coordinate system. There doesn't seem to be a matrix of the orientation so I can build a left handed quaternion. I don't want to use euler angles as they produce gimbal lock in certain situations. any chance of getting a matrix of the orientations instead of just quats in the next sdk update or patch.
or, as I might have missed something does anyone know another way to get a left handed quaternion currently from the sdk?

5 Replies

  • "genetransfer" wrote:
    does anyone know another way to get a left handed quaternion currently from the sdk?


    Simply converting the quaternion to a matrix won't change the handed-ness of the resulting matrix.
    However, the Quaternion type in the SDK has a method for extracting the Euler angles in an arbitrary coordinate system:

        template <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S>
    void GetEulerAngles(T *a, T *b, T *c)


    You can call it like this:

    glm::vec3 eulerAngles;
    sensorFusion.GetOrientation().GetEulerAngles<
    OVR::Axis_X, OVR::Axis_Y, OVR::Axis_Z,
    OVR::Rotate_CW, OVR::Handed_R
    >
    (&eulerAngles.x, &eulerAngles.y, &eulerAngles.z);


    In your cases you'd want to change Handed_R to Handed_L.

    You can then reconstruct a type in your preferred coordinate system using the Euler angles.

    glm::quat quaternion(getEulerAngles(sensorFusion));  
    glm::mat4 matrix(glm::mat4_cast(quaternion))
  • thanks but from the matrix data I can rebuild it as left handed and convert to quaternion whereas rebuilding the quat from euler angles can cause gimbal lock in some situations, which is why I was wanting to avoid that.
  • If anyone is using directx left handed coord system and want the hmd orientation with +Z Direction and no gimbal lock,
    this might help you...

    function to convert matrix right to left (used with following function)

    D3DXMATRIX iOddityEngine_MatrixRightHandedToLeft(Matrix4f* matrix)
    {
    //-------------------------------------------------------------
    D3DXMATRIX m1,m2;
    //-------------------------------------------------------------
    //convert row major to column major
    m2.m[0][0] = matrix->M[0][0];
    m2.m[1][0] = matrix->M[0][1];
    m2.m[2][0] = matrix->M[0][2];
    m2.m[3][0] = matrix->M[0][3];

    m2.m[0][1] = matrix->M[1][0];
    m2.m[1][1] = matrix->M[1][1];
    m2.m[2][1] = matrix->M[1][2];
    m2.m[3][1] = matrix->M[1][3];

    m2.m[0][2] = matrix->M[2][0];
    m2.m[1][2] = matrix->M[2][1];
    m2.m[2][2] = matrix->M[2][2];
    m2.m[3][2] = matrix->M[2][3];

    m2.m[0][3] = matrix->M[3][0];
    m2.m[1][3] = matrix->M[3][1];
    m2.m[2][3] = matrix->M[3][2];
    m2.m[3][3] = matrix->M[3][3];
    //-------------------------------------------------------------
    //convert right handed to left handed as row major
    m1.m[0][0] = -m2.m[0][0];
    m1.m[0][1] = m2.m[0][1];
    m1.m[0][2] = m2.m[0][2];
    m1.m[0][3] = 0.0f;

    m1.m[1][0] = -m2.m[1][0];
    m1.m[1][1] = m2.m[1][1];
    m1.m[1][2] = m2.m[1][2];
    m1.m[1][3] = 0.0f;

    m1.m[2][0] = m2.m[2][0];
    m1.m[2][1] = -m2.m[2][1];
    m1.m[2][2] = -m2.m[2][2];
    m1.m[2][3] = 0.0f;

    m1.m[3][0] = 0.0f;
    m1.m[3][1] = 0.0f;
    m1.m[3][2] = 0.0f;
    m1.m[3][3] = 1.0f;
    return m1;
    //-------------------------------------------------------------
    }


    The function to return the HMD orientation as quaternion...

    void iOculusRiftHMDOrientation(D3DXQUATERNION* q1,bool bUsePrediction)
    {
    //-------------------------------------------------------------
    if (pOculusRift.pSensor)
    {
    Quatf qf1;
    if(bUsePrediction)
    {
    qf1 = pOculusRift.SFusion->GetPredictedOrientation();
    }
    else
    {
    qf1 = pOculusRift.SFusion->GetOrientation();
    }

    Matrix4f matrix = qf1.operator OVR::Matrix4f();

    D3DXMATRIX m1 = iOddityEngine_MatrixRightHandedToLeft(&matrix);

    D3DXQUATERNION q2 = D3DXQUATERNION(0.0f,0.0f,0.0f,1.0f);
    D3DXQUATERNION q3 = D3DXQUATERNION(0.0f,0.0f,0.0f,1.0f);

    //----below function uses "D3DXQuaternionRotationMatrix()"
    iRotationMatrixToQuaternion(&q2,&m1);

    //----below function uses "D3DXQuaternionRotationYawPitchRoll()"
    iQuaternionFromEulerAngles(&q3,0.0f,180.0f,0.0f);

    //to face +z
    iQuaternionMultiply(&q2,&q2,&q3);

    q1->x = q2.x;
    q1->y = q2.y;
    q1->z = q2.z;
    q1->w = q2.w;
    }
    return;
    //-------------------------------------------------------------
    }
  • Or just swap and negate terms to change coordinate systems, which is equivalent to swapping a rotation matrix between column major and row major order.

    With 12 sets of Cartesian coordinate systems to choose from (all easily interchangeable) it can be a bit confusing at times...

    And the names of the axes can change too, especially when using non-Cartesian (e.g. cylindrical or spherical) coordinates:
    http://www.spenvis.oma.be/help/background/coortran/coortran.html

    Cartesian handedness:
    http://en.wikipedia.org/wiki/Cartesian_coordinates#Orientation_and_handedness

    More info about the how and why of coordinate swapping:
    http://blog.safe.com/2011/06/fmeevangelist81/

    And even more fun stuff:
    http://www.mathsisfun.com/geometry/solid-geometry.html