TEST(BasicJointClientKitWithInterface, ConstructDestruct) { auto options = osvrJointClientCreateOptions(); ASSERT_NE(nullptr, options); ASSERT_EQ(OSVR_RETURN_SUCCESS, osvrJointClientOptionsLoadPlugin(options, "com_osvr_example_AnalogSync")); ASSERT_EQ(OSVR_RETURN_SUCCESS, osvrJointClientOptionsTriggerHardwareDetect(options)); auto ctx = osvrJointClientInit("org.osvr.test.jointclientkit", options); ASSERT_NE(nullptr, ctx); ASSERT_EQ(OSVR_RETURN_SUCCESS, osvrClientUpdate(ctx)); OSVR_ClientInterface eye = nullptr; ASSERT_EQ(OSVR_RETURN_SUCCESS, osvrClientGetInterface(ctx, "/com_osvr_example_AnalogSync/MySyncDevice/analog/0", &eye)); ASSERT_EQ(OSVR_RETURN_SUCCESS, osvrRegisterAnalogCallback(eye, &myAnalogCallback, nullptr)); ASSERT_EQ(OSVR_RETURN_SUCCESS, osvrClientUpdate(ctx)); ASSERT_EQ(true, reportReceived); ASSERT_EQ(OSVR_RETURN_SUCCESS, osvrClientShutdown(ctx)); }
void FOSVRInputDevice::SendControllerEvents() { FScopeLock lock(contextMutex); if (osvrClientUpdate(context) == OSVR_RETURN_FAILURE) { UE_LOG(LogOSVRInputDevice, Warning, TEXT("FOSVRInputDevice::SendControllerEvents(): osvrClientUpdate failed.")); } const int32 controllerId = 0; for (auto& button : osvrButtons) { if (button->bIsValid) { while (!button->digitalStateQueue.IsEmpty()) { bool state = false; button->digitalStateQueue.Dequeue(state); if (state) { MessageHandler->OnControllerButtonPressed(button->key, controllerId, false); } else { MessageHandler->OnControllerButtonReleased(button->key, controllerId, false); } } while (!button->analogStateQueue.IsEmpty()) { float state = 0.0f; button->analogStateQueue.Dequeue(state); MessageHandler->OnControllerAnalog(button->key, controllerId, state); } } } }
void FOSVRHMD::UpdateHeadPose(FQuat& lastHmdOrientation, FVector& lastHmdPosition, FQuat& hmdOrientation, FVector& hmdPosition) { OSVR_Pose3 pose; OSVR_ReturnCode returnCode; FScopeLock lock(mOSVREntryPoint->GetClientContextMutex()); auto clientContext = mOSVREntryPoint->GetClientContext(); returnCode = osvrClientUpdate(clientContext); check(returnCode == OSVR_RETURN_SUCCESS); returnCode = osvrClientGetViewerPose(DisplayConfig, 0, &pose); if (returnCode == OSVR_RETURN_SUCCESS) { LastHmdOrientation = CurHmdOrientation; LastHmdPosition = CurHmdPosition; CurHmdPosition = BaseOrientation.Inverse().RotateVector(OSVR2FVector(pose.translation, WorldToMetersScale) - BasePosition); CurHmdOrientation = BaseOrientation.Inverse() * OSVR2FQuat(pose.rotation); lastHmdOrientation = LastHmdOrientation; lastHmdPosition = LastHmdPosition; hmdOrientation = CurHmdOrientation; hmdPosition = CurHmdPosition; } else { lastHmdOrientation = hmdOrientation = FQuat::Identity; lastHmdPosition = hmdPosition = FVector(0.0f, 0.0f, 0.0f); } }
int main() { OSVR_ClientContext ctx = osvrClientInit("com.osvr.exampleclients.MinimalInit", 0); printf("OK, library initialized.\n"); /* Pretend that this is your application's mainloop. */ int i; for (i = 0; i < 1000000; ++i) { osvrClientUpdate(ctx); } osvrClientShutdown(ctx); printf("Library shut down, exiting.\n"); return 0; }
OSVREntryPoint::OSVREntryPoint() { // avoid BuildCookRun hangs if (IsRunningCommandlet() || IsRunningDedicatedServer()) { UE_LOG(OSVREntryPointLog, Display, TEXT("OSVREntryPoint::OSVREntryPoint(): running as commandlet or dedicated server - skipping client context startup.")); return; } osvrClientAttemptServerAutoStart(); osvrClientContext = osvrClientInit("com.osvr.unreal.plugin"); { bool bClientContextOK = false; bool bFailure = false; auto begin = FDateTime::Now().GetTicks(); auto end = begin + 10 * ETimespan::TicksPerSecond; while (FDateTime::Now().GetTicks() < end && !bClientContextOK && !bFailure) { bClientContextOK = osvrClientCheckStatus(osvrClientContext) == OSVR_RETURN_SUCCESS; if (!bClientContextOK) { bFailure = osvrClientUpdate(osvrClientContext) == OSVR_RETURN_FAILURE; if (bFailure) { UE_LOG(OSVREntryPointLog, Display, TEXT("osvrClientUpdate failed during startup. Treating this as if the HMD is not connected.")); break; } FPlatformProcess::Sleep(0.2f); } } if (!bClientContextOK) { UE_LOG(OSVREntryPointLog, Display, TEXT("OSVR client context could not connect. Most likely the server isn't running. Treating this as if the HMD is not connected.")); } } #if OSVR_DEPRECATED_BLUEPRINT_API_ENABLED InterfaceCollection = MakeShareable(new OSVRInterfaceCollection(osvrClientContext)); #endif }
int main() { OSVR_ClientContext ctx = osvrClientInit("com.osvr.exampleclients.ButtonCallback", 0); OSVR_ClientInterface button1 = NULL; /* This is just one of the paths: specifically, the Hydra's left * controller's button labelled "1". More are in the docs and/or listed on * startup */ osvrClientGetInterface(ctx, "/controller/left/1", &button1); osvrRegisterButtonCallback(button1, &myButtonCallback, NULL); /* Pretend that this is your application's mainloop. */ int i; for (i = 0; i < 1000000; ++i) { osvrClientUpdate(ctx); } osvrClientShutdown(ctx); printf("Library shut down, exiting.\n"); return 0; }
/** * Returns the calibration-space orientation of the requested controller's hand. * * @param ControllerIndex The Unreal controller (player) index of the contoller set * @param DeviceHand Which hand, within the controller set for the player, to get the orientation and position for * @param OutOrientation (out) If tracked, the orientation (in calibrated-space) of the controller in the specified hand * @param OutPosition (out) If tracked, the position (in calibrated-space) of the controller in the specified hand * @return True if the device requested is valid and tracked, false otherwise */ bool FOSVRInputDevice::GetControllerOrientationAndPosition(const int32 ControllerIndex, const EControllerHand DeviceHand, FRotator& OutOrientation, FVector& OutPosition) const { bool bRet = false; if (ControllerIndex == 0) { FScopeLock lock(contextMutex); if (osvrClientCheckStatus(context) == OSVR_RETURN_SUCCESS && osvrClientUpdate(context) == OSVR_RETURN_SUCCESS) { auto iface = DeviceHand == EControllerHand::Left ? leftHand : rightHand; OSVR_PoseState state; OSVR_TimeValue tvalue; if (osvrGetPoseState(iface, &tvalue, &state) == OSVR_RETURN_SUCCESS) { // @todo: how do we get the world to meters scale without the HMD? float worldToMetersScale = mOSVRHMD.IsValid() ? mOSVRHMD->GetWorldToMetersScale() : 100.0f; OutPosition = OSVR2FVector(state.translation, worldToMetersScale); OutOrientation = OSVR2FQuat(state.rotation).Rotator(); bRet = true; } } } return bRet; }
void OSVREntryPoint::Tick(float DeltaTime) { FScopeLock lock(this->GetClientContextMutex()); osvrClientUpdate(osvrClientContext); }
FOSVRHMD::FOSVRHMD(TSharedPtr<class OSVREntryPoint, ESPMode::ThreadSafe> entryPoint) : mOSVREntryPoint(entryPoint) { static const FName RendererModuleName("Renderer"); RendererModule = FModuleManager::GetModulePtr<IRendererModule>(RendererModuleName); FScopeLock lock(mOSVREntryPoint->GetClientContextMutex()); auto osvrClientContext = mOSVREntryPoint->GetClientContext(); // Prevents debugger hangs that sometimes occur with only one monitor. #if OSVR_UNREAL_DEBUG_FORCED_WINDOWMODE FSystemResolution::RequestResolutionChange(1280, 720, EWindowMode::Windowed); // bStereo ? WindowedMirror : Windowed #endif EnablePositionalTracking(true); StartCustomPresent(); // enable vsync IConsoleVariable* CVSyncVar = IConsoleManager::Get().FindConsoleVariable(TEXT("r.VSync")); if (CVSyncVar) { CVSyncVar->Set(false); } // Uncap fps to enable FPS higher than 62 GEngine->bSmoothFrameRate = false; // check if the client context is ok. bool bClientContextOK = entryPoint->IsOSVRConnected(); // get the display context bool bDisplayConfigOK = false; if (bClientContextOK) { bool bFailure = false; auto rc = osvrClientGetDisplay(osvrClientContext, &DisplayConfig); if (rc == OSVR_RETURN_FAILURE) { UE_LOG(OSVRHMDLog, Warning, TEXT("Could not create DisplayConfig. Treating this as if the HMD is not connected.")); } else { auto begin = FDateTime::Now().GetSecond(); auto end = begin + 3; while (!bDisplayConfigOK && FDateTime::Now().GetSecond() < end) { bDisplayConfigOK = osvrClientCheckDisplayStartup(DisplayConfig) == OSVR_RETURN_SUCCESS; if (!bDisplayConfigOK) { bFailure = osvrClientUpdate(osvrClientContext) == OSVR_RETURN_FAILURE; if (bFailure) { UE_LOG(OSVRHMDLog, Warning, TEXT("osvrClientUpdate failed during startup. Treating this as \"HMD not connected\"")); break; } } FPlatformProcess::Sleep(0.2f); } bDisplayConfigOK = bDisplayConfigOK && !bFailure; if (!bDisplayConfigOK) { UE_LOG(OSVRHMDLog, Warning, TEXT("DisplayConfig failed to startup. This could mean that there is nothing mapped to /me/head. Treating this as if the HMD is not connected.")); } } } bool bDisplayConfigMatchesUnrealExpectations = false; if (bDisplayConfigOK) { bool bSuccess = HMDDescription.Init(osvrClientContext, DisplayConfig); if (bSuccess) { bDisplayConfigMatchesUnrealExpectations = HMDDescription.OSVRViewerFitsUnrealModel(DisplayConfig); if (!bDisplayConfigMatchesUnrealExpectations) { UE_LOG(OSVRHMDLog, Warning, TEXT("The OSVR display config does not match the expectations of Unreal. Possibly incompatible HMD configuration.")); } } else { UE_LOG(OSVRHMDLog, Warning, TEXT("Unable to initialize the HMDDescription. Possible failures during initialization.")); } } // our version of connected is that the client context is ok (server is running) // and the display config is ok (/me/head exists and received a pose) bHmdConnected = bClientContextOK && bDisplayConfigOK && bDisplayConfigMatchesUnrealExpectations; }
void OSVREntryPoint::Tick(float DeltaTime) { #if OSVR_ENABLED osvrClientUpdate(osvrClientContext); #endif // OSVR_ENABLED }
/** * Handle OSVR tracking. ***/ void* OSVR_Tracker::Provoke(void* pThis, int eD3D, int eD3DInterface, int eD3DMethod, DWORD dwNumberConnected, int& nProvokerIndex) { // update game timer m_cGameTimer.Tick(); static UINT unFrameSkip = 200; if (unFrameSkip > 0) { unFrameSkip--; return nullptr; } if ((!m_psOSVR_ClientContext) || (!m_psOSVR_ClientInterface)) { // create client context handle m_psOSVR_ClientContext = osvrClientInit("com.mtbs3d.vireio.osvr.tracker", 0); // get client interface osvrClientGetInterface(m_psOSVR_ClientContext, "/me/head", &m_psOSVR_ClientInterface); } else { // update the client context osvrClientUpdate(m_psOSVR_ClientContext); // let's read the tracker state. OSVR_ReturnCode cRet = osvrGetPoseState(m_psOSVR_ClientInterface, &m_sTimestamp, &m_sState); if (cRet != OSVR_RETURN_SUCCESS) { OutputDebugStringA("No pose state!\n"); } else { m_bControlUpdate = true; // backup old euler angles and velocity float afEulerOld[3]; float afEulerVelocityOld[3]; memcpy(&afEulerOld[0], &m_afEuler[0], sizeof(float)* 3); memcpy(&afEulerVelocityOld[0], &m_afEulerVelocity[0], sizeof(float)* 3); // quaternion -> euler angles const float w = (float)m_sState.rotation.data[0]; const float x = (float)m_sState.rotation.data[1]; const float y = (float)m_sState.rotation.data[2]; const float z = (float)m_sState.rotation.data[3]; float sqw = w*w; float sqx = x*x; float sqy = y*y; float sqz = z*z; float unit = sqx + sqy + sqz + sqw; float test = x*y + z*w; if (test > 0.499*unit) { // singularity at north pole m_afEuler[1] = 2 * atan2(x, w); m_afEuler[2] = FLOAT_PI / 2; m_afEuler[0] = 0; } else if (test < -0.499*unit) { // singularity at south pole m_afEuler[1] = -2 * atan2(x, w); m_afEuler[2] = -FLOAT_PI / 2; m_afEuler[0] = 0; } else { m_afEuler[1] = atan2(2 * y*w - 2 * x*z, sqx - sqy - sqz + sqw); m_afEuler[2] = asin(2 * test / unit); m_afEuler[0] = atan2(2 * x * w - 2 * y * z, -sqx + sqy - sqz + sqw); } // PITCH = atan2(2.0 * (x * y + w * z), w * w + x * x - y * y - z * z); // ROLL = atan2(2 * y * w - 2 * x * z, 1 - 2 * y * y - 2 * z * z); // get euler velocity + acceleration float afEulerAcceleration[3]; for (UINT unI = 0; unI < 3; unI++) { // get the velocity m_afEulerVelocity[unI] = (m_afEuler[unI] - afEulerOld[unI]) / (float)m_cGameTimer.DeltaTime(); // get the acceleration afEulerAcceleration[unI] = (m_afEulerVelocity[unI] - afEulerVelocityOld[unI]) / (float)m_cGameTimer.DeltaTime(); } // get predicted euler for (UINT unI = 0; unI < 3; unI++) { // compute predicted euler m_afEulerPredicted[unI] = (0.5f * afEulerAcceleration[unI] * ((float)m_cGameTimer.DeltaTime() * (float)m_cGameTimer.DeltaTime())) + (m_afEulerVelocity[unI] * (float)m_cGameTimer.DeltaTime()) + m_afEuler[unI]; } // set position m_afPosition[0] = (float)m_sState.translation.data[0]; m_afPosition[1] = (float)m_sState.translation.data[1]; m_afPosition[2] = (float)m_sState.translation.data[2]; #ifdef _DEBUG // output debug data std::wstringstream szPose; szPose << L"Got POSE state: Position = (" << m_sState.translation.data[0] << L", " << m_sState.translation.data[1] << L", " << m_sState.translation.data[2] << L"), orientation = (" << osvrQuatGetW(&(m_sState.rotation)) << L", " << osvrQuatGetX(&(m_sState.rotation)) << L", " << osvrQuatGetY(&(m_sState.rotation)) << L", " << osvrQuatGetZ(&(m_sState.rotation)) << L")"; OutputDebugString(szPose.str().c_str()); #endif } } return nullptr; }