ovrQuatf (w,x,y,z)
为了方便地在程序中应用这个四元数,我们需要将其转换成矩阵形式,以方便用线性代数的矩阵知识来计算:
// Returns the 4x4 rotation matrix for the given quaternion.
static inline ovrMatrix4f ovrMatrix4f_CreateFromQuaternion( const ovrQuatf * q )
{
const float ww = q->w * q->w;
const float xx = q->x * q->x;
const float yy = q->y * q->y;
const float zz = q->z * q->z;
ovrMatrix4f out;
out.M[0][0] = ww + xx - yy - zz;
out.M[0][1] = 2 * ( q->x * q->y - q->w * q->z );
out.M[0][2] = 2 * ( q->x * q->z + q->w * q->y );
out.M[0][3] = 0;
out.M[1][0] = 2 * ( q->x * q->y + q->w * q->z );
out.M[1][1] = ww - xx + yy - zz;
out.M[1][2] = 2 * ( q->y * q->z - q->w * q->x );
out.M[1][3] = 0;
out.M[2][0] = 2 * ( q->x * q->z - q->w * q->y );
out.M[2][1] = 2 * ( q->y * q->z + q->w * q->x );
out.M[2][2] = ww - xx - yy + zz;
out.M[2][3] = 0;
out.M[3][0] = 0;
out.M[3][1] = 0;
out.M[3][2] = 0;
out.M[3][3] = 1;
return out;
}
因为眼部姿态和头部姿态的旋转用的是同一个四元数。所以,我们将头部姿态的四元数经过上面的转换,就得到了双眼中心旋转矩阵centerEyeRotation
const ovrMatrix4f centerEyeRotation = ovrMatrix4f_CreateFromQuaternion( &tracking->HeadPose.Pose.Orientation );
const ovrMatrix4f centerEyeTranslation = ovrMatrix4f_CreateTranslation( centerEyeOffset.x, centerEyeOffset.y, centerEyeOffset.z );
然后将旋转矩阵和偏移矩阵相乘,即可得到双眼中心的转换矩阵centerEyeTransform
const ovrMatrix4f centerEyeTransform = ovrMatrix4f_Multiply( ¢erEyeTranslation, ¢erEyeRotation );
然后求其逆矩阵,即得到双眼中心视角矩阵(centerEyeViewMatrix)
ovrMatrix4f inverseMatrix = ovrMatrix4f_Inverse( ¢erEyeTransform );
const float eyeOffset = ( eye ? -0.5f : 0.5f ) * headModelParms->InterpupillaryDistance;
// Returns a 4x4 homogeneous translation matrix.
static inline ovrMatrix4f ovrMatrix4f_CreateTranslation( const float x, const float y, const float z )
{
ovrMatrix4f out;
out.M[0][0] = 1.0f; out.M[0][1] = 0.0f; out.M[0][2] = 0.0f; out.M[0][3] = x;
out.M[1][0] = 0.0f; out.M[1][1] = 1.0f; out.M[1][2] = 0.0f; out.M[1][3] = y;
out.M[2][0] = 0.0f; out.M[2][1] = 0.0f; out.M[2][2] = 1.0f; out.M[2][3] = z;
out.M[3][0] = 0.0f; out.M[3][1] = 0.0f; out.M[3][2] = 0.0f; out.M[3][3] = 1.0f;
return out;
}
const ovrMatrix4f eyeOffsetMatrix = ovrMatrix4f_CreateTranslation( eyeOffset, 0.0f, 0.0f );
// Apply the eye transformation to the camera.
Matrix.multiplyMM(view, 0, eye.getEyeView(), 0, camera, 0);
multiplyMM的函数实现为:
/**
* Multiplies two 4x4 matrices together and stores the result in a third 4x4
* matrix. In matrix notation: result = lhs x rhs. Due to the way
* matrix multiplication works, the result matrix will have the same
* effect as first multiplying by the rhs matrix, then multiplying by
* the lhs matrix. This is the opposite of what you might expect.
*
* The same float array may be passed for result, lhs, and/or rhs. However,
* the result element values are undefined if the result elements overlap
* either the lhs or rhs elements.
*
* @param result The float array that holds the result.
* @param resultOffset The offset into the result array where the result is
* stored.
* @param lhs The float array that holds the left-hand-side matrix.
* @param lhsOffset The offset into the lhs array where the lhs is stored
* @param rhs The float array that holds the right-hand-side matrix.
* @param rhsOffset The offset into the rhs array where the rhs is stored.
*
* @throws IllegalArgumentException if result, lhs, or rhs are null, or if
* resultOffset + 16 > result.length or lhsOffset + 16 > lhs.length or
* rhsOffset + 16 > rhs.length.
*/
public static native void multiplyMM(float[] result, int resultOffset,
float[] lhs, int lhsOffset, float[] rhs, int rhsOffset);
eyeinfo = 1
0.7840466 0.17531556 -0.5954287 0.0
-0.21760693 0.9760361 8.4029883E-4 0.0
0.5813073 0.1289106 0.80340767 0.0
0.015629478 -0.0017972889 0.080063015 1.0
{
left: 35.19728,
right: 50.898663,
bottom: 50.099197,
top: 48.315865,
} false
eyeinfo = 2
0.7840466 0.17531556 -0.5954287 0.0
-0.21760693 0.9760361 8.4029883E-4 0.0
0.5813073 0.1289106 0.80340767 0.0
-0.048270524 -0.0017972889 0.080063015 1.0
{
left: 50.89864,
right: 35.19729,
bottom: 50.09919,
top: 48.31586,
} false
// Set the position of the light
Matrix.multiplyMV(lightPosInEyeSpace, 0, view, 0, LIGHT_POS_IN_WORLD_SPACE, 0);
// Build the ModelView and ModelViewProjection matrices
// for calculating cube position and light.
float[] perspective = eye.getPerspective(Z_NEAR, Z_FAR);
Matrix.multiplyMM(modelView, 0, view, 0, modelCube, 0);
Matrix.multiplyMM(modelViewProjection, 0, perspective, 0, modelView, 0);
drawCube();
// Set modelView for the floor, so we draw floor in the correct location
Matrix.multiplyMM(modelView, 0, view, 0, modelFloor, 0);
Matrix.multiplyMM(modelViewProjection, 0, perspective, 0, modelView, 0);
drawFloor();