diff --git a/android/app/src/main/cpp/code/vr/vr_input.c b/android/app/src/main/cpp/code/vr/vr_input.c index b420a8ba..76c55428 100644 --- a/android/app/src/main/cpp/code/vr/vr_input.c +++ b/android/app/src/main/cpp/code/vr/vr_input.c @@ -90,9 +90,7 @@ void rotateAboutOrigin(float x, float y, float rotation, vec2_t out) out[1] = cosf(DEG2RAD(-rotation)) * y - sinf(DEG2RAD(-rotation)) * x; } -//TODO: -/* -static ovrVector3f normalizeVec(ovrVector3f vec) { +XrVector3f normalizeVec(XrVector3f vec) { //NOTE: leave w-component untouched //@@const float EPSILON = 0.000001f; float xxyyzz = vec.x*vec.x + vec.y*vec.y + vec.z*vec.z; @@ -100,14 +98,13 @@ static ovrVector3f normalizeVec(ovrVector3f vec) { //@@ return *this; // do nothing if it is zero vector //float invLength = invSqrt(xxyyzz); - ovrVector3f result; + XrVector3f result; float invLength = 1.0f / sqrtf(xxyyzz); result.x = vec.x * invLength; result.y = vec.y * invLength; result.z = vec.z * invLength; return result; } -*/ static float length(float x, float y) { @@ -124,9 +121,7 @@ void NormalizeAngles(vec3_t angles) while (angles[2] < -180) angles[2] += 360; } -//TODO: -/* -void GetAnglesFromVectors(const ovrVector3f forward, const ovrVector3f right, const ovrVector3f up, vec3_t angles) +void GetAnglesFromVectors(const XrVector3f forward, const XrVector3f right, const XrVector3f up, vec3_t angles) { float sr, sp, sy, cr, cp, cy; @@ -175,7 +170,7 @@ void GetAnglesFromVectors(const ovrVector3f forward, const ovrVector3f right, co NormalizeAngles(angles); } -void QuatToYawPitchRoll(ovrQuatf q, vec3_t rotation, vec3_t out) { +void QuatToYawPitchRoll(XrQuaternionf q, vec3_t rotation, vec3_t out) { ovrMatrix4f mat = ovrMatrix4f_CreateFromQuaternion( &q ); @@ -185,25 +180,24 @@ void QuatToYawPitchRoll(ovrQuatf q, vec3_t rotation, vec3_t out) { mat = ovrMatrix4f_Multiply(&mat, &rot); } - ovrVector4f v1 = {0, 0, -1, 0}; - ovrVector4f v2 = {1, 0, 0, 0}; - ovrVector4f v3 = {0, 1, 0, 0}; + XrVector4f v1 = {0, 0, -1, 0}; + XrVector4f v2 = {1, 0, 0, 0}; + XrVector4f v3 = {0, 1, 0, 0}; - ovrVector4f forwardInVRSpace = ovrVector4f_MultiplyMatrix4f(&mat, &v1); - ovrVector4f rightInVRSpace = ovrVector4f_MultiplyMatrix4f(&mat, &v2); - ovrVector4f upInVRSpace = ovrVector4f_MultiplyMatrix4f(&mat, &v3); + XrVector4f forwardInVRSpace = XrVector4f_MultiplyMatrix4f(&mat, &v1); + XrVector4f rightInVRSpace = XrVector4f_MultiplyMatrix4f(&mat, &v2); + XrVector4f upInVRSpace = XrVector4f_MultiplyMatrix4f(&mat, &v3); - ovrVector3f forward = {-forwardInVRSpace.z, -forwardInVRSpace.x, forwardInVRSpace.y}; - ovrVector3f right = {-rightInVRSpace.z, -rightInVRSpace.x, rightInVRSpace.y}; - ovrVector3f up = {-upInVRSpace.z, -upInVRSpace.x, upInVRSpace.y}; + XrVector3f forward = {-forwardInVRSpace.z, -forwardInVRSpace.x, forwardInVRSpace.y}; + XrVector3f right = {-rightInVRSpace.z, -rightInVRSpace.x, rightInVRSpace.y}; + XrVector3f up = {-upInVRSpace.z, -upInVRSpace.x, upInVRSpace.y}; - ovrVector3f forwardNormal = normalizeVec(forward); - ovrVector3f rightNormal = normalizeVec(right); - ovrVector3f upNormal = normalizeVec(up); + XrVector3f forwardNormal = normalizeVec(forward); + XrVector3f rightNormal = normalizeVec(right); + XrVector3f upNormal = normalizeVec(up); GetAnglesFromVectors(forwardNormal, rightNormal, upNormal, out); } -*/ //0 = left, 1 = right float vibration_channel_duration[2] = {0.0f, 0.0f}; @@ -958,28 +952,16 @@ void IN_VRInputFrame( void ) controllerInit = qtrue; } - //TODO: - /* - ovrMobile* ovr = VR_GetEngine()->ovr; - if (!ovr) { - return; - } - - ovrResult result; if (vr_extralatencymode != NULL && vr_extralatencymode->integer) { - result = vrapi_SetExtraLatencyMode(VR_GetEngine()->ovr, VRAPI_EXTRA_LATENCY_MODE_ON); - assert(result == VRAPI_INITIALIZE_SUCCESS); + //TODO:vrapi_SetExtraLatencyMode(VR_GetEngine()->ovr, VRAPI_EXTRA_LATENCY_MODE_ON); } if (vr_refreshrate != NULL && vr_refreshrate->integer) { - vrapi_SetDisplayRefreshRate(VR_GetEngine()->ovr, (float)vr_refreshrate->integer); + //TODO:vrapi_SetDisplayRefreshRate(VR_GetEngine()->ovr, (float)vr_refreshrate->integer); } - result = vrapi_SetClockLevels(VR_GetEngine()->ovr, 4, 4); - assert(result == VRAPI_INITIALIZE_SUCCESS); - vr.virtual_screen = VR_useScreenLayer(); VR_processHaptics(); @@ -990,10 +972,14 @@ void IN_VRInputFrame( void ) { // We extract Yaw, Pitch, Roll instead of directly using the orientation // to allow "additional" yaw manipulation with mouse/controller. - const ovrQuatf quatHmd = VR_GetEngine()->tracking.HeadPose.Pose.Orientation; - const ovrVector3f positionHmd = VR_GetEngine()->tracking.HeadPose.Pose.Position; + XrSpaceLocation loc = {}; + loc.type = XR_TYPE_SPACE_LOCATION; + OXR(xrLocateSpace(VR_GetEngine()->appState.HeadSpace, VR_GetEngine()->appState.CurrentSpace, VR_GetEngine()->predictedDisplayTime, &loc)); + XrPosef xfStageFromHead = loc.pose; + const XrQuaternionf quatHmd = xfStageFromHead.orientation; + const XrVector3f positionHmd = xfStageFromHead.position; vec3_t rotation = {0, 0, 0}; - QuatToYawPitchRoll(quatHmd, rotation, vr.hmdorientation); + QuatToYawPitchRoll(quatHmd, rotation, vr.hmdorientation); VectorSet(vr.hmdposition, positionHmd.x, positionHmd.y + vr_heightAdjust->value, positionHmd.z); //Position @@ -1014,7 +1000,8 @@ void IN_VRInputFrame( void ) vr.clientview_yaw_last = clientview_yaw; } - ovrInputCapabilityHeader capsHeader; + //TODO: + /*ovrInputCapabilityHeader capsHeader; uint32_t index = 0; for (;;) { ovrResult enumResult = vrapi_EnumerateInputDevices(ovr, index, &capsHeader); @@ -1067,11 +1054,10 @@ void IN_VRInputFrame( void ) IN_VRController(isRight, remoteTracking); IN_VRJoystick(isRight, state.Joystick.x, state.Joystick.y); IN_VRTriggers(isRight, state.IndexTrigger); - } + }*/ lastframetime = in_vrEventTime; in_vrEventTime = Sys_Milliseconds( ); - */ } //#endif diff --git a/android/app/src/main/cpp/code/vr/vr_renderer.c b/android/app/src/main/cpp/code/vr/vr_renderer.c index 1e28773b..6bec3735 100644 --- a/android/app/src/main/cpp/code/vr/vr_renderer.c +++ b/android/app/src/main/cpp/code/vr/vr_renderer.c @@ -335,6 +335,7 @@ void VR_DrawFrame( engine_t* engine ) { frameState.next = NULL; OXR(xrWaitFrame(engine->appState.Session, &waitFrameInfo, &frameState)); + engine->predictedDisplayTime = frameState.predictedDisplayTime; // Get the HMD pose, predicted for the middle of the time period during which // the new eye images will be displayed. The number of frames predicted ahead @@ -477,7 +478,7 @@ void VR_DrawFrame( engine_t* engine ) { cylinder_layer.subImage.imageRect.extent.height = engine->appState.Renderer.FrameBuffer[0].ColorSwapChain.Height; cylinder_layer.subImage.imageArrayIndex = 0; const XrVector3f axis = {0.0f, 1.0f, 0.0f}; - const XrVector3f pos = {0.0f, 0.0f, -1.0f}; + const XrVector3f pos = {xfStageFromHead.position.x, 0.0f, xfStageFromHead.position.z - 1.0f}; cylinder_layer.pose.orientation = XrQuaternionf_CreateFromVectorAngle(axis, 0); cylinder_layer.pose.position = pos; cylinder_layer.radius = 1.0f; diff --git a/android/app/src/main/cpp/code/vr/vr_types.c b/android/app/src/main/cpp/code/vr/vr_types.c index 44a1fd58..8ef6784e 100644 --- a/android/app/src/main/cpp/code/vr/vr_types.c +++ b/android/app/src/main/cpp/code/vr/vr_types.c @@ -567,4 +567,101 @@ ovrMatrix4f ovrMatrix4f_CreateProjectionFov( const float maxY = offsetY + halfHeight; return ovrMatrix4f_CreateProjection(minX, maxX, minY, maxY, nearZ, farZ); +} + +ovrMatrix4f ovrMatrix4f_CreateFromQuaternion(const XrQuaternionf* 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; +} + + +/// Use left-multiplication to accumulate transformations. +ovrMatrix4f ovrMatrix4f_Multiply(const ovrMatrix4f* a, const ovrMatrix4f* b) { + ovrMatrix4f out; + out.M[0][0] = a->M[0][0] * b->M[0][0] + a->M[0][1] * b->M[1][0] + a->M[0][2] * b->M[2][0] + + a->M[0][3] * b->M[3][0]; + out.M[1][0] = a->M[1][0] * b->M[0][0] + a->M[1][1] * b->M[1][0] + a->M[1][2] * b->M[2][0] + + a->M[1][3] * b->M[3][0]; + out.M[2][0] = a->M[2][0] * b->M[0][0] + a->M[2][1] * b->M[1][0] + a->M[2][2] * b->M[2][0] + + a->M[2][3] * b->M[3][0]; + out.M[3][0] = a->M[3][0] * b->M[0][0] + a->M[3][1] * b->M[1][0] + a->M[3][2] * b->M[2][0] + + a->M[3][3] * b->M[3][0]; + + out.M[0][1] = a->M[0][0] * b->M[0][1] + a->M[0][1] * b->M[1][1] + a->M[0][2] * b->M[2][1] + + a->M[0][3] * b->M[3][1]; + out.M[1][1] = a->M[1][0] * b->M[0][1] + a->M[1][1] * b->M[1][1] + a->M[1][2] * b->M[2][1] + + a->M[1][3] * b->M[3][1]; + out.M[2][1] = a->M[2][0] * b->M[0][1] + a->M[2][1] * b->M[1][1] + a->M[2][2] * b->M[2][1] + + a->M[2][3] * b->M[3][1]; + out.M[3][1] = a->M[3][0] * b->M[0][1] + a->M[3][1] * b->M[1][1] + a->M[3][2] * b->M[2][1] + + a->M[3][3] * b->M[3][1]; + + out.M[0][2] = a->M[0][0] * b->M[0][2] + a->M[0][1] * b->M[1][2] + a->M[0][2] * b->M[2][2] + + a->M[0][3] * b->M[3][2]; + out.M[1][2] = a->M[1][0] * b->M[0][2] + a->M[1][1] * b->M[1][2] + a->M[1][2] * b->M[2][2] + + a->M[1][3] * b->M[3][2]; + out.M[2][2] = a->M[2][0] * b->M[0][2] + a->M[2][1] * b->M[1][2] + a->M[2][2] * b->M[2][2] + + a->M[2][3] * b->M[3][2]; + out.M[3][2] = a->M[3][0] * b->M[0][2] + a->M[3][1] * b->M[1][2] + a->M[3][2] * b->M[2][2] + + a->M[3][3] * b->M[3][2]; + + out.M[0][3] = a->M[0][0] * b->M[0][3] + a->M[0][1] * b->M[1][3] + a->M[0][2] * b->M[2][3] + + a->M[0][3] * b->M[3][3]; + out.M[1][3] = a->M[1][0] * b->M[0][3] + a->M[1][1] * b->M[1][3] + a->M[1][2] * b->M[2][3] + + a->M[1][3] * b->M[3][3]; + out.M[2][3] = a->M[2][0] * b->M[0][3] + a->M[2][1] * b->M[1][3] + a->M[2][2] * b->M[2][3] + + a->M[2][3] * b->M[3][3]; + out.M[3][3] = a->M[3][0] * b->M[0][3] + a->M[3][1] * b->M[1][3] + a->M[3][2] * b->M[2][3] + + a->M[3][3] * b->M[3][3]; + return out; +} + +ovrMatrix4f ovrMatrix4f_CreateRotation(const float radiansX, const float radiansY, const float radiansZ) { + const float sinX = sinf(radiansX); + const float cosX = cosf(radiansX); + const ovrMatrix4f rotationX = { + {{1, 0, 0, 0}, {0, cosX, -sinX, 0}, {0, sinX, cosX, 0}, {0, 0, 0, 1}}}; + const float sinY = sinf(radiansY); + const float cosY = cosf(radiansY); + const ovrMatrix4f rotationY = { + {{cosY, 0, sinY, 0}, {0, 1, 0, 0}, {-sinY, 0, cosY, 0}, {0, 0, 0, 1}}}; + const float sinZ = sinf(radiansZ); + const float cosZ = cosf(radiansZ); + const ovrMatrix4f rotationZ = { + {{cosZ, -sinZ, 0, 0}, {sinZ, cosZ, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}}; + const ovrMatrix4f rotationXY = ovrMatrix4f_Multiply(&rotationY, &rotationX); + return ovrMatrix4f_Multiply(&rotationZ, &rotationXY); +} + +XrVector4f XrVector4f_MultiplyMatrix4f(const ovrMatrix4f* a, const XrVector4f* v) { + XrVector4f out; + out.x = a->M[0][0] * v->x + a->M[0][1] * v->y + a->M[0][2] * v->z + a->M[0][3] * v->w; + out.y = a->M[1][0] * v->x + a->M[1][1] * v->y + a->M[1][2] * v->z + a->M[1][3] * v->w; + out.z = a->M[2][0] * v->x + a->M[2][1] * v->y + a->M[2][2] * v->z + a->M[2][3] * v->w; + out.w = a->M[3][0] * v->x + a->M[3][1] * v->y + a->M[3][2] * v->z + a->M[3][3] * v->w; + return out; } \ No newline at end of file diff --git a/android/app/src/main/cpp/code/vr/vr_types.h b/android/app/src/main/cpp/code/vr/vr_types.h index cb8f2368..b340fde1 100644 --- a/android/app/src/main/cpp/code/vr/vr_types.h +++ b/android/app/src/main/cpp/code/vr/vr_types.h @@ -121,7 +121,7 @@ typedef struct { } ovrApp; -typedef struct ovrMatrix4f_ { +typedef struct { float M[4][4]; } ovrMatrix4f; @@ -129,6 +129,7 @@ typedef struct { uint64_t frameIndex; ovrApp appState; ovrJava java; + float predictedDisplayTime; } engine_t; typedef enum { @@ -157,6 +158,16 @@ void ovrFramebuffer_Release(ovrFramebuffer* frameBuffer); void ovrFramebuffer_SetCurrent(ovrFramebuffer* frameBuffer); void ovrFramebuffer_SetNone(); +void ovrRenderer_Create( + XrSession session, + ovrRenderer* renderer, + int suggestedEyeTextureWidth, + int suggestedEyeTextureHeight); +void ovrRenderer_Destroy(ovrRenderer* renderer); + +ovrMatrix4f ovrMatrix4f_Multiply(const ovrMatrix4f* a, const ovrMatrix4f* b); +ovrMatrix4f ovrMatrix4f_CreateRotation(const float radiansX, const float radiansY, const float radiansZ); +ovrMatrix4f ovrMatrix4f_CreateFromQuaternion(const XrQuaternionf* q); ovrMatrix4f ovrMatrix4f_CreateProjectionFov( const float fovDegreesX, const float fovDegreesY, @@ -165,11 +176,6 @@ ovrMatrix4f ovrMatrix4f_CreateProjectionFov( const float nearZ, const float farZ); -void ovrRenderer_Create( - XrSession session, - ovrRenderer* renderer, - int suggestedEyeTextureWidth, - int suggestedEyeTextureHeight); -void ovrRenderer_Destroy(ovrRenderer* renderer); +XrVector4f XrVector4f_MultiplyMatrix4f(const ovrMatrix4f* a, const XrVector4f* v); #endif