void VR_OVR_FrameStart() { const char *results = ovrHmd_GetLatencyTestResult(hmd); if (results && strncmp(results,"",1)) { static float lastms = 0; float ms; if (sscanf(results,"RESULT=%f ",&ms) && ms != lastms) { Cvar_SetInteger("vr_prediction",(int) ms); lastms = ms; } } if (vr_ovr_lowpersistence->modified) { unsigned int caps = 0; if (hmd->HmdCaps & ovrHmdCap_DynamicPrediction) caps |= ovrHmdCap_DynamicPrediction; if (hmd->HmdCaps & ovrHmdCap_LowPersistence && vr_ovr_lowpersistence->value) caps |= ovrHmdCap_LowPersistence; ovrHmd_SetEnabledCaps(hmd,caps); vr_ovr_lowpersistence->modified = false; } if (!withinFrame) { frameTime = ovrHmd_BeginFrameTiming(hmd,0); } else { ovrHmd_EndFrameTiming(hmd); ovrHmd_ResetFrameTiming(hmd,0); frameTime = ovrHmd_BeginFrameTiming(hmd,0); } withinFrame = true; }
int setup_rift(struct weston_compositor *compositor) { struct oculus_rift *rift = compositor->rift; rift->enabled = 1; rift->screen_z = -5.0; rift->screen_scale = 1.0; weston_compositor_add_key_binding(compositor, KEY_5, MODIFIER_SUPER, toggle_sbs, compositor); weston_compositor_add_key_binding(compositor, KEY_6, MODIFIER_SUPER, toggle_rotate, compositor); weston_compositor_add_key_binding(compositor, KEY_7, MODIFIER_SUPER, move_in, compositor); weston_compositor_add_key_binding(compositor, KEY_8, MODIFIER_SUPER, move_out, compositor); weston_compositor_add_key_binding(compositor, KEY_9, MODIFIER_SUPER, scale_up, compositor); weston_compositor_add_key_binding(compositor, KEY_0, MODIFIER_SUPER, scale_down, compositor); /*// use this at some point in the future to detect and grab the rift display struct weston_output *output; wl_list_for_each(output, &compositor->output_list, link) { weston_log("Output (%i): %s\n\t%ix%i\n", output->id, output->name, output->width, output->height); }*/ rift->distortion_shader = calloc(1, sizeof *(rift->distortion_shader)); struct distortion_shader_ *d = rift->distortion_shader; d->program = CreateProgram(distortion_vertex_shader, distortion_fragment_shader); d->EyeToSourceUVScale = glGetUniformLocation(d->program, "EyeToSourceUVScale"); d->EyeToSourceUVOffset = glGetUniformLocation(d->program, "EyeToSourceUVOffset"); d->RightEye = glGetUniformLocation(d->program, "RightEye"); d->angle = glGetUniformLocation(d->program, "angle"); d->Position = glGetAttribLocation(d->program, "Position"); d->TexCoord0 = glGetAttribLocation(d->program, "TexCoord0"); d->TexCoordR = glGetAttribLocation(d->program, "TexCoordR"); d->TexCoordG = glGetAttribLocation(d->program, "TexCoordG"); d->TexCoordB = glGetAttribLocation(d->program, "TexCoordB"); d->eyeTexture = glGetAttribLocation(d->program, "Texture0"); rift->eye_shader = calloc(1, sizeof *(rift->eye_shader)); struct eye_shader_ *e = rift->eye_shader; e->program = CreateProgram(eye_vertex_shader, eye_fragment_shader); e->Position = glGetAttribLocation(d->program, "Position"); e->TexCoord0 = glGetAttribLocation(d->program, "TexCoord0"); e->Projection = glGetUniformLocation(e->program, "Projection"); e->ModelView = glGetUniformLocation(e->program, "ModelView"); e->virtualScreenTexture = glGetAttribLocation(d->program, "Texture0"); rift->scene = calloc(1, sizeof *(rift->scene)); glGenBuffers(1, &rift->scene->vertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, rift->scene->vertexBuffer); static const GLfloat rectangle[] = {-1.0f, -1.0f, -0.5f, 1.0f, -1.0f, -0.5f, -1.0f, 1.0f, -0.5f, 1.0f, -1.0f, -0.5f, 1.0f, 1.0f, -0.5f, -1.0f, 1.0f, -0.5f}; glBufferData(GL_ARRAY_BUFFER, sizeof(rectangle), rectangle, GL_STATIC_DRAW); glGenBuffers(2, &rift->scene->SBSuvsBuffer[0]); glGenBuffers(1, &rift->scene->uvsBuffer); static const GLfloat uvs[3][12] = {{ 0.0, 0.0, 0.5, 0.0, 0.0, 1.0, 0.5, 0.0, 0.5, 1.0, 0.0, 1.0}, { 0.5, 0.0, 1.0, 0.0, 0.5, 1.0, 1.0, 0.0, 1.0, 1.0, 0.5, 1.0}, { 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0}}; glBindBuffer(GL_ARRAY_BUFFER, rift->scene->SBSuvsBuffer[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(uvs[0]), uvs[0], GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, rift->scene->SBSuvsBuffer[1]); glBufferData(GL_ARRAY_BUFFER, sizeof(uvs[1]), uvs[1], GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, rift->scene->uvsBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(uvs[2]), uvs[2], GL_STATIC_DRAW); rift->width = 1920; rift->height = 1080; glGenTextures(1, &rift->fbTexture); glBindTexture(GL_TEXTURE_2D, rift->fbTexture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rift->width, rift->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glGenFramebuffers(1, &rift->redirectedFramebuffer); glBindFramebuffer(GL_FRAMEBUFFER, rift->redirectedFramebuffer); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rift->fbTexture, 0); show_error(); if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { switch(glCheckFramebufferStatus(GL_FRAMEBUFFER)) { case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: weston_log("incomplete attachment\n"); break; case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: weston_log("incomplete dimensions\n"); break; case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: weston_log("incomplete missing attachment\n"); break; case GL_FRAMEBUFFER_UNSUPPORTED: weston_log("unsupported\n"); break; } weston_log("framebuffer not working\n"); show_error(); exit(1); } glClear(GL_COLOR_BUFFER_BIT); /*EGLint pbufferAttributes[] = { EGL_WIDTH, rift->width, EGL_HEIGHT, rift->height, EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB, EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, EGL_NONE }; rift->pbuffer = eglCreatePbufferSurface( rift->egl_display, rift->egl_config, pbufferAttributes); glGenTextures(1, &(rift->texture)); glBindTexture(GL_TEXTURE_2D, rift->texture); //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rift->width, rift->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); eglMakeCurrent(rift->egl_display, rift->pbuffer, rift->pbuffer, rift->egl_context); eglBindTexImage(rift->egl_display, rift->pbuffer, EGL_BACK_BUFFER); eglMakeCurrent(rift->egl_display, rift->orig_surface, rift->orig_surface, rift->egl_context);*/ ovr_Initialize(0); rift->hmd = ovrHmd_Create(0); if(rift->hmd == NULL) { rift->hmd = ovrHmd_CreateDebug(ovrHmd_DK2); } ovrHmd_ConfigureTracking(rift->hmd, ovrTrackingCap_Orientation | ovrTrackingCap_Position | ovrTrackingCap_MagYawCorrection, 0); ovrHmd_ResetFrameTiming(rift->hmd, 0); int eye; for(eye = 0; eye < 2; eye++) { ovrFovPort fov = rift->hmd->DefaultEyeFov[eye]; ovrEyeRenderDesc renderDesc = ovrHmd_GetRenderDesc(rift->hmd, eye, fov); struct EyeArg *eyeArg = &rift->eyeArgs[eye]; eyeArg->projection = ovrMatrix4f_Projection(fov, 0.1, 100000, true); /*int j, k; for(k=0; k<4; k++) { for(j=0; j<4; j++) { printf("%f\t", eyeArg->projection.M[k][j]); } printf("\n"); }*/ rift->hmdToEyeOffsets[eye] = renderDesc.HmdToEyeViewOffset; ovrRecti texRect; texRect.Size = ovrHmd_GetFovTextureSize(rift->hmd, eye, rift->hmd->DefaultEyeFov[eye], 1.0f); texRect.Pos.x = texRect.Pos.y = 0; eyeArg->textureWidth = texRect.Size.w; eyeArg->textureHeight = texRect.Size.h; glGenTextures(1, &eyeArg->texture); glBindTexture(GL_TEXTURE_2D, eyeArg->texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, eyeArg->textureWidth, eyeArg->textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glGenFramebuffers(1, &eyeArg->framebuffer); show_error(); glBindFramebuffer(GL_FRAMEBUFFER, eyeArg->framebuffer); show_error(); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, eyeArg->texture, 0); show_error(); if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { switch(glCheckFramebufferStatus(GL_FRAMEBUFFER)) { case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: weston_log("incomplete attachment\n"); break; case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: weston_log("incomplete dimensions\n"); break; case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: weston_log("incomplete missing attachment\n"); break; case GL_FRAMEBUFFER_UNSUPPORTED: weston_log("unsupported\n"); break; } weston_log("framebuffer not working\n"); show_error(); exit(1); } if(eye) { glClearColor(1.0, 0.0, 0.0, 1.0); show_error(); } else { glClearColor(0.0, 1.0, 0.0, 1.0); show_error(); } glClear(GL_COLOR_BUFFER_BIT); show_error(); /*EGLint eyePbufferAttributes[] = { EGL_WIDTH, texRect.Size.w, EGL_HEIGHT, texRect.Size.h, EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB, EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, EGL_NONE }; eyeArg.surface = eglCreatePbufferSurface( rift->egl_display, rift->egl_config, eyePbufferAttributes);*/ ovrVector2f scaleAndOffset[2]; ovrHmd_GetRenderScaleAndOffset(fov, texRect.Size, texRect, scaleAndOffset); eyeArg->scale = scaleAndOffset[0]; eyeArg->offset = scaleAndOffset[1]; ovrHmd_CreateDistortionMesh(rift->hmd, eye, fov, 0, &eyeArg->mesh); glGenBuffers(1, &eyeArg->indexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eyeArg->indexBuffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, eyeArg->mesh.IndexCount * sizeof(unsigned short), eyeArg->mesh.pIndexData, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); float vertices_buffer[eyeArg->mesh.VertexCount*2]; float uvs_buffer[3][eyeArg->mesh.VertexCount*2]; uint i; for(i=0; i<eyeArg->mesh.VertexCount; i++) { ovrDistortionVertex vertex = eyeArg->mesh.pVertexData[i]; vertices_buffer[i*2] = vertex.ScreenPosNDC.x; vertices_buffer[(i*2)+1] = vertex.ScreenPosNDC.y; uvs_buffer[0][i*2] = vertex.TanEyeAnglesR.x; uvs_buffer[0][(i*2)+1] = vertex.TanEyeAnglesR.y; uvs_buffer[1][i*2] = vertex.TanEyeAnglesG.x; uvs_buffer[1][(i*2)+1] = vertex.TanEyeAnglesG.y; uvs_buffer[2][i*2] = vertex.TanEyeAnglesB.x; uvs_buffer[2][(i*2)+1] = vertex.TanEyeAnglesB.y; } glGenBuffers(1, &eyeArg->vertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, eyeArg->vertexBuffer); glBufferData(GL_ARRAY_BUFFER, eyeArg->mesh.VertexCount * sizeof(GL_FLOAT) * 2, vertices_buffer, GL_STATIC_DRAW); glGenBuffers(3, &eyeArg->uvsBuffer[0]); for(i=0; i<3; i++) { glBindBuffer(GL_ARRAY_BUFFER, eyeArg->uvsBuffer[i]); glBufferData(GL_ARRAY_BUFFER, eyeArg->mesh.VertexCount * sizeof(GL_FLOAT) * 2, uvs_buffer[i], GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); } } return 0; }
int32_t VR_OVR_Enable() { int32_t failure = 0; unsigned int hmdCaps = 0; qboolean isDebug = false; unsigned int device = 0; if (!vr_ovr_enable->value) return 0; if (!libovrInitialized) { libovrInitialized = ovr_Initialize(); if (!libovrInitialized) { Com_Printf("VR_OVR: Fatal error: could not initialize LibOVR!\n"); return 0; } else { Com_Printf("VR_OVR: %s initialized...\n",ovr_GetVersionString()); } } { int numDevices = ovrHmd_Detect(); int i; qboolean found = false; memset(hmdnames,0,sizeof(ovrname_t) * 255); Com_Printf("VR_OVR: Enumerating devices...\n"); Com_Printf("VR_OVR: Found %i devices\n", numDevices); for (i = 0 ; i < numDevices ; i++) { ovrHmd tempHmd = ovrHmd_Create(i); if (tempHmd) { Com_Printf("VR_OVR: Found device #%i '%s' s/n:%s\n",i,tempHmd->ProductName, tempHmd->SerialNumber); sprintf(hmdnames[i].label,"%i: %s",i + 1, tempHmd->ProductName); sprintf(hmdnames[i].serialnumber,"%s",tempHmd->SerialNumber); if (!strncmp(vr_ovr_device->string,tempHmd->SerialNumber,strlen(tempHmd->SerialNumber))) { device = i; found = true; } ovrHmd_Destroy(tempHmd); } } } Com_Printf("VR_OVR: Initializing HMD: "); withinFrame = false; hmd = ovrHmd_Create(device); if (!hmd) { Com_Printf("no HMD detected!\n"); failure = 1; } else { Com_Printf("ok!\n"); } if (failure && vr_ovr_debug->value) { ovrHmdType temp = ovrHmd_None; switch((int) vr_ovr_debug->value) { default: temp = ovrHmd_DK1; break; case 2: temp = ovrHmd_DKHD; break; case 3: temp = ovrHmd_DK2; break; } hmd = ovrHmd_CreateDebug(temp); isDebug = true; Com_Printf("VR_OVR: Creating debug HMD...\n"); } if (!hmd) return 0; if (hmd->HmdCaps & ovrHmdCap_ExtendDesktop) { Com_Printf("...running in extended desktop mode\n"); } else if (!isDebug) { Com_Printf("...running in Direct HMD mode\n"); Com_Printf("...Direct HMD mode is unsupported at this time\n"); VR_OVR_Disable(); VR_OVR_Shutdown(); return 0; } Com_Printf("...device positioned at (%i,%i)\n",hmd->WindowsPos.x,hmd->WindowsPos.y); if (hmd->HmdCaps & ovrHmdCap_Available) Com_Printf("...sensor is available\n"); if (hmd->HmdCaps & ovrHmdCap_LowPersistence) Com_Printf("...supports low persistance\n"); if (hmd->HmdCaps & ovrHmdCap_DynamicPrediction) Com_Printf("...supports dynamic motion prediction\n"); if (hmd->TrackingCaps & ovrTrackingCap_Position) Com_Printf("...supports position tracking\n"); Com_Printf("...has type %s\n", hmd->ProductName); Com_Printf("...has %ux%u native resolution\n", hmd->Resolution.w, hmd->Resolution.h); if (!VR_OVR_InitSensor()) { Com_Printf("VR_OVR: Sensor initialization failed!\n"); } ovrHmd_ResetFrameTiming(hmd,0); return 1; }
OculusDevice::OculusDevice(float nearClip, float farClip, bool useTimewarp) : m_hmdDevice(0), m_nearClip(nearClip), m_farClip(farClip), m_useTimeWarp(useTimewarp), m_position(osg::Vec3(0.0f, 0.0f, 0.0f)), m_orientation(osg::Quat(0.0f, 0.0f, 0.0f, 1.0f)) { ovr_Initialize(); // Enumerate HMD devices int numberOfDevices = ovrHmd_Detect(); osg::notify(osg::DEBUG_INFO) << "Number of connected devices: " << numberOfDevices << std::endl; // Get first available HMD m_hmdDevice = ovrHmd_Create(0); // If no HMD is found try an emulated device if (!m_hmdDevice) { osg::notify(osg::WARN) << "Warning: No device could be found. Creating emulated device " << std::endl; m_hmdDevice = ovrHmd_CreateDebug(ovrHmd_DK1); ovrHmd_ResetFrameTiming(m_hmdDevice, 0); } if (m_hmdDevice) { // Print out some information about the HMD osg::notify(osg::ALWAYS) << "Product: " << m_hmdDevice->ProductName << std::endl; osg::notify(osg::ALWAYS) << "Manufacturer: " << m_hmdDevice->Manufacturer << std::endl; osg::notify(osg::ALWAYS) << "VendorId: " << m_hmdDevice->VendorId << std::endl; osg::notify(osg::ALWAYS) << "ProductId: " << m_hmdDevice->ProductId << std::endl; osg::notify(osg::ALWAYS) << "SerialNumber: " << m_hmdDevice->SerialNumber << std::endl; osg::notify(osg::ALWAYS) << "FirmwareVersion: " << m_hmdDevice->FirmwareMajor << "." << m_hmdDevice->FirmwareMinor << std::endl; // Get more details about the HMD. m_resolution = m_hmdDevice->Resolution; // Compute recommended render texture size float pixelsPerDisplayPixel = 1.0f; // Decrease this value to scale the size on render texture on lower performance hardware. Values above 1.0 is unnecessary. ovrSizei recommenedLeftTextureSize = ovrHmd_GetFovTextureSize(m_hmdDevice, ovrEye_Left, m_hmdDevice->DefaultEyeFov[0], pixelsPerDisplayPixel); ovrSizei recommenedRightTextureSize = ovrHmd_GetFovTextureSize(m_hmdDevice, ovrEye_Right, m_hmdDevice->DefaultEyeFov[1], pixelsPerDisplayPixel); // Compute size of render target m_renderTargetSize.w = recommenedLeftTextureSize.w + recommenedRightTextureSize.w; m_renderTargetSize.h = osg::maximum(recommenedLeftTextureSize.h, recommenedRightTextureSize.h); // Initialize ovrEyeRenderDesc struct. m_eyeRenderDesc[0] = ovrHmd_GetRenderDesc(m_hmdDevice, ovrEye_Left, m_hmdDevice->DefaultEyeFov[0]); m_eyeRenderDesc[1] = ovrHmd_GetRenderDesc(m_hmdDevice, ovrEye_Right, m_hmdDevice->DefaultEyeFov[1]); ovrVector3f leftEyeAdjust = m_eyeRenderDesc[0].ViewAdjust; m_leftEyeAdjust.set(leftEyeAdjust.x, leftEyeAdjust.y, leftEyeAdjust.z); ovrVector3f rightEyeAdjust = m_eyeRenderDesc[1].ViewAdjust; m_rightEyeAdjust.set(rightEyeAdjust.x, rightEyeAdjust.y, rightEyeAdjust.z); bool isRightHanded = true; ovrMatrix4f leftEyeProjectionMatrix = ovrMatrix4f_Projection(m_eyeRenderDesc[0].Fov, m_nearClip, m_farClip, isRightHanded); // Transpose matrix m_leftEyeProjectionMatrix.set(leftEyeProjectionMatrix.M[0][0], leftEyeProjectionMatrix.M[1][0], leftEyeProjectionMatrix.M[2][0], leftEyeProjectionMatrix.M[3][0], leftEyeProjectionMatrix.M[0][1], leftEyeProjectionMatrix.M[1][1], leftEyeProjectionMatrix.M[2][1], leftEyeProjectionMatrix.M[3][1], leftEyeProjectionMatrix.M[0][2], leftEyeProjectionMatrix.M[1][2], leftEyeProjectionMatrix.M[2][2], leftEyeProjectionMatrix.M[3][2], leftEyeProjectionMatrix.M[0][3], leftEyeProjectionMatrix.M[1][3], leftEyeProjectionMatrix.M[2][3], leftEyeProjectionMatrix.M[3][3]); ovrMatrix4f rightEyeProjectionMatrix = ovrMatrix4f_Projection(m_eyeRenderDesc[1].Fov, m_nearClip, m_farClip, isRightHanded); // Transpose matrix m_rightEyeProjectionMatrix.set(rightEyeProjectionMatrix.M[0][0], rightEyeProjectionMatrix.M[1][0], rightEyeProjectionMatrix.M[2][0], rightEyeProjectionMatrix.M[3][0], rightEyeProjectionMatrix.M[0][1], rightEyeProjectionMatrix.M[1][1], rightEyeProjectionMatrix.M[2][1], rightEyeProjectionMatrix.M[3][1], rightEyeProjectionMatrix.M[0][2], rightEyeProjectionMatrix.M[1][2], rightEyeProjectionMatrix.M[2][2], rightEyeProjectionMatrix.M[3][2], rightEyeProjectionMatrix.M[0][3], rightEyeProjectionMatrix.M[1][3], rightEyeProjectionMatrix.M[2][3], rightEyeProjectionMatrix.M[3][3]); // Start the sensor which provides the Rift’s pose and motion. ovrHmd_ConfigureTracking(m_hmdDevice, ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Position, 0); beginFrameTiming(); } }