OSVR_ReturnCode osvrClientSetRoomRotationUsingHead(OSVR_ClientContext ctx) { if (nullptr == ctx) { /// Return failure if given a null context return OSVR_RETURN_FAILURE; } auto xform = ctx->getRoomToWorldTransform(); auto iface = osvr::client::InternalInterfaceOwner{ctx, "/me/head"}; OSVR_OrientationState state; OSVR_TimeValue t; /// Give ourselves 200 milliseconds to get a head tracker report. using std::chrono::system_clock; const auto deadline = system_clock::now() + std::chrono::milliseconds(200); do { if (OSVR_RETURN_SUCCESS == osvrGetOrientationState(&(*iface), &t, &state)) { // OK, we've gotten state successfully: extract yaw, update // transform, and return success. auto q = osvr::util::eigen_interop::map(state); auto yaw = osvr::util::extractYaw(q); Eigen::AngleAxisd correction(-yaw, Eigen::Vector3d::UnitY()); xform.concatPost(Eigen::Isometry3d(correction).matrix()); ctx->setRoomToWorldTransform(xform); return OSVR_RETURN_SUCCESS; } ctx->update(); } while (system_clock::now() < deadline); return OSVR_RETURN_FAILURE; }
OSVR_ReturnCode osvrClientClearRoomToWorldTransform(OSVR_ClientContext ctx) { if (nullptr == ctx) { /// Return failure if given a null context return OSVR_RETURN_FAILURE; } osvr::common::Transform nullTransform; ctx->setRoomToWorldTransform(nullTransform); return OSVR_RETURN_SUCCESS; }
RenderManagerConfigPtr RenderManagerConfigFactory::createShared(OSVR_ClientContext ctx) { try { auto const configString = ctx->getStringParameter("/renderManagerConfig"); RenderManagerConfigPtr cfg(new RenderManagerConfig(configString)); return cfg; } catch (std::exception const &e) { OSVR_DEV_VERBOSE( "Couldn't create a render manager config internally! Exception: " << e.what()); return RenderManagerConfigPtr{}; } catch (...) { OSVR_DEV_VERBOSE("Couldn't create a render manager config internally! " "Unknown exception!"); return RenderManagerConfigPtr{}; } }
DisplayConfigPtr DisplayConfigFactory::create(OSVR_ClientContext ctx) { DisplayConfigPtr cfg(new DisplayConfig); try { auto const descriptorString = ctx->getStringParameter("/display"); auto desc = display_schema_1::DisplayDescriptor(descriptorString); cfg->m_viewers.container().emplace_back(Viewer(ctx, HEAD_PATH)); auto &viewer = cfg->m_viewers.container().front(); auto eyesDesc = desc.getEyes(); /// Set up stereo vs mono std::vector<uint8_t> eyeIndices; Eigen::Vector3d offset; if (eyesDesc.size() == 2) { // stereo offset = desc.getIPDMeters() / 2. * Eigen::Vector3d::UnitX(); eyeIndices = {0, 1}; } else { // if (eyesDesc.size() == 1) // mono offset = Eigen::Vector3d::Zero(); eyeIndices = {0}; } /// Handle radial distortion parameters boost::optional<OSVR_RadialDistortionParameters> distort; auto k1 = desc.getDistortion(); if (k1.k1_red != 0 || k1.k1_green != 0 || k1.k1_blue != 0) { OSVR_RadialDistortionParameters params; params.k1.data[0] = k1.k1_red; params.k1.data[1] = k1.k1_green; params.k1.data[2] = k1.k1_blue; distort = params; } /// Compute angular offset about Y of the optical (view) axis util::Angle axisOffset = 0. * util::radians; { auto overlapPct = desc.getOverlapPercent(); if (overlapPct < 1.) { const auto hfov = desc.getHorizontalFOV(); const auto angularOverlap = hfov * overlapPct; axisOffset = (hfov - angularOverlap) / 2.; } } /// Infer the number of display inputs and their association with /// eyes (actually surfaces) based on the descriptor. std::vector<OSVR_DisplayInputCount> displayInputIndices; if (eyesDesc.size() == 2 && display_schema_1::DisplayDescriptor::FULL_SCREEN == desc.getDisplayMode()) { // two eyes, full screen - that means two screens. displayInputIndices = {0, 1}; cfg->m_displayInputs.push_back(DisplayInput( desc.getDisplayWidth(), desc.getDisplayHeight())); cfg->m_displayInputs.push_back(DisplayInput( desc.getDisplayWidth(), desc.getDisplayHeight())); } else { // everything else, assume 1 screen. // Note that it's OK that displayInputIndices.size() >= // eyesDesc.size(), we'll just not end up using the second // entry. displayInputIndices = {0, 0}; cfg->m_displayInputs.push_back(DisplayInput( desc.getDisplayWidth(), desc.getDisplayHeight())); } BOOST_ASSERT_MSG(displayInputIndices.size() >= eyesDesc.size(), "Must have at least as many indices as eyes"); /// Create the actual eye (with implied surface) objects for (auto eye : eyeIndices) { // This little computation turns 0 into -1 and 1 into 1, used as // a coefficient to make the two eyes do opposite things. // Doesn't affect mono, which has a zero offset vector. double offsetFactor = (2. * eye) - 1.; // Set up per-eye distortion parameters, if needed boost::optional<OSVR_RadialDistortionParameters> distortEye( distort); if (distortEye) { distortEye->centerOfProjection.data[0] = eyesDesc[eye].m_CenterProjX; distortEye->centerOfProjection.data[1] = eyesDesc[eye].m_CenterProjY; } // precompute translation offset for this eye auto xlateOffset = (offsetFactor * offset).eval(); // precompute the optical axis rotation for this eye // here, the left eye should get a positive offset since it's a // positive rotation about y, hence the -1 factor. auto eyeAxisOffset = axisOffset * -1. * offsetFactor; // Look up the display index for this eye. auto displayInputIdx = displayInputIndices[eye]; /// Create the ViewerEye[Surface] and add it to the container. viewer.container().emplace_back(ViewerEye( ctx, xlateOffset, HEAD_PATH, computeViewport(eye, desc), computeRect(desc), eyesDesc[eye].m_rotate180, desc.getPitchTilt().value(), distortEye, displayInputIdx, eyeAxisOffset)); } OSVR_DEV_VERBOSE("Display: " << desc.getHumanReadableDescription()); return cfg; } catch (std::exception const &e) { OSVR_DEV_VERBOSE( "Couldn't create a display config internally! Exception: " << e.what()); return DisplayConfigPtr{}; } catch (...) { OSVR_DEV_VERBOSE("Couldn't create a display config internally! " "Unknown exception!"); return DisplayConfigPtr{}; } }
OSVR_ReturnCode osvrClientFreeImage(OSVR_ClientContext ctx, OSVR_ImageBufferElement *buf) { auto ret = ctx->releaseObject(buf); return (ret ? OSVR_RETURN_SUCCESS : OSVR_RETURN_FAILURE); }