19 #define _USE_MATH_DEFINES 
   44 #include <unordered_map> 
   45 #include <OVR_CAPI_Util.h> 
   50 #pragma comment(lib, "dxgi.lib") 
   57  #define GLFW_EXPOSE_NATIVE_WIN32 
   58  #define GLFW_EXPOSE_NATIVE_WGL 
   60 #elif defined(__APPLE__) 
   61  #define GLFW_EXPOSE_NATIVE_COCOA 
   62  #define GLFW_EXPOSE_NATIVE_NSGL 
   64 #elif defined(__linux__) 
   65  #define GLFW_EXPOSE_NATIVE_X11 
   66  #define GLFW_EXPOSE_NATIVE_GLX 
   69 #include <GLFW/glfw3.h> 
   70 #include <GLFW/glfw3native.h> 
   72 #include <OVR_System.h> 
   73 #include <OVR_CAPI_GL.h> 
  112     float yaw, pitch, roll;
 
  115     rot.GetEulerAngles<OVR::Axis_Y, OVR::Axis_X, OVR::Axis_Z>(&yaw, &pitch, &roll);
 
  116     v[0] = -roll; v[1] = -pitch; v[2] = yaw;
 
  130 inline ovrVector3f 
vecSubtract(
const ovrVector3f& a, 
const ovrVector3f& b)
 
  139 static inline void debugTangent(std::string message, 
float tangent1, 
float tangent2)
 
  142             (message + 
"    %10f (%5f[rad] = %5f[deg])        %10f (%5f[rad] = %5f[deg])\n").c_str(),
 
  145             OVR::RadToDegree(atan(tangent1)),
 
  148             OVR::RadToDegree(atan(tangent2)));
 
  152             "             Left Eye                                           Right Eye\n");
 
  153     debugTangent(
"LeftTan",  fov[0].LeftTan , fov[0].LeftTan);
 
  154     debugTangent(
"RightTan", fov[0].RightTan, fov[0].RightTan);
 
  156     debugTangent(
"DownTan",  fov[0].DownTan , fov[0].DownTan );
 
  162 static int compareLuid(
const ovrGraphicsLuid& lhs, 
const ovrGraphicsLuid& rhs)
 
  164     return memcmp(&lhs, &rhs, 
sizeof(ovrGraphicsLuid));
 
  169     ovrGraphicsLuid luid = ovrGraphicsLuid();
 
  172     IDXGIFactory* factory = 
nullptr;
 
  174     if (SUCCEEDED(CreateDXGIFactory(IID_PPV_ARGS(&factory))))
 
  176         IDXGIAdapter* adapter = 
nullptr;
 
  178         if (SUCCEEDED(factory->EnumAdapters(0, &adapter)))
 
  180             DXGI_ADAPTER_DESC desc;
 
  182             adapter->GetDesc(&desc);
 
  183             memcpy(&luid, &desc.AdapterLuid, 
sizeof(luid));
 
  208 inline OVR::Vector3f 
radToDeg(
const OVR::Vector3f& v)
 
  212     ret.x = OVR::RadToDegree(v.x);
 
  213     ret.y = OVR::RadToDegree(v.y);
 
  214     ret.z = OVR::RadToDegree(v.z);
 
  220                                const float x,     
const float y,  
const float z, 
 
  221                                const float rx,    
const float ry, 
const float rz, 
float rw, 
 
  222                                const float sizeX, 
const float sizeY)
 
  224     layer.Header.Type                  = ovrLayerType_Quad;
 
  225     layer.Header.Flags                 = ovrLayerFlag_HeadLocked;
 
  227     layer.QuadPoseCenter.Position.x    = x;
 
  228     layer.QuadPoseCenter.Position.y    = y;
 
  229     layer.QuadPoseCenter.Position.z    = z;
 
  230     layer.QuadPoseCenter.Orientation.x = rx;
 
  231     layer.QuadPoseCenter.Orientation.y = ry;
 
  232     layer.QuadPoseCenter.Orientation.z = rz;
 
  233     layer.QuadPoseCenter.Orientation.w = rw;
 
  234     layer.QuadSize.x                   = sizeX;
 
  235     layer.QuadSize.y                   = sizeY;
 
  237     layer.Viewport = OVR::Recti(0, 0, tex->
width, tex->
height);
 
  241     const float x, 
const float y, 
const float z, 
 
  242     const float rx, 
const float ry, 
const float rz, 
float rw, 
 
  243     const float sizeX, 
const float sizeY)
 
  245     layer.Header.Type = ovrLayerType_Quad;
 
  246     layer.Header.Flags = ovrLayerFlag_HeadLocked;
 
  248     layer.QuadPoseCenter.Position.x = x;
 
  249     layer.QuadPoseCenter.Position.y = y;
 
  250     layer.QuadPoseCenter.Position.z = z;
 
  251     layer.QuadPoseCenter.Orientation.x = rx;
 
  252     layer.QuadPoseCenter.Orientation.y = ry;
 
  253     layer.QuadPoseCenter.Orientation.z = rz;
 
  254     layer.QuadPoseCenter.Orientation.w = rw;
 
  255     layer.QuadSize.x = sizeX;
 
  256     layer.QuadSize.y = sizeY;
 
  258     layer.Viewport = OVR::Recti(0, 0, tex->
width, tex->
height);
 
  274 void yarp::dev::OVRHeadset::fillAxisStorage()
 
  276     axisIdToValue.push_back(inputState.IndexTrigger);
 
  277     axisIdToValue.push_back(inputState.IndexTrigger + 1);
 
  278     axisIdToValue.push_back(inputState.HandTrigger);
 
  279     axisIdToValue.push_back(inputState.HandTrigger + 1 );
 
  283         axisIdToValue.push_back(&inputState.Thumbstick[ovrHand_Left].x);
 
  284         axisIdToValue.push_back(&inputState.Thumbstick[ovrHand_Left].y);
 
  285         axisIdToValue.push_back(&inputState.Thumbstick[ovrHand_Right].x);
 
  286         axisIdToValue.push_back(&inputState.Thumbstick[ovrHand_Right].y);
 
  291 void yarp::dev::OVRHeadset::fillErrorStorage()
 
  293     error_messages[ovrError_MemoryAllocationFailure       ] = 
"Failure to allocate memory.";
 
  294     error_messages[ovrError_InvalidSession                ] = 
"Invalid ovrSession parameter provided.";
 
  295     error_messages[ovrError_Timeout                       ] = 
"The operation timed out.";
 
  296     error_messages[ovrError_NotInitialized                ] = 
"The system or component has not been initialized.";
 
  297     error_messages[ovrError_InvalidParameter              ] = 
"Invalid parameter provided.See error info or log for details.";
 
  298     error_messages[ovrError_ServiceError                  ] = 
"Generic service error.See error info or log for details.";
 
  299     error_messages[ovrError_NoHmd                         ] = 
"The given HMD doesn't exist.";
 
  300     error_messages[ovrError_Unsupported                   ] = 
"Function call is not supported on this hardware / software.";
 
  301     error_messages[ovrError_DeviceUnavailable             ] = 
"Specified device type isn't available.";
 
  302     error_messages[ovrError_InvalidHeadsetOrientation     ] = 
"The headset was in an invalid orientation for the requested operation(e.g.vertically oriented during ovr_RecenterPose).";
 
  303     error_messages[ovrError_ClientSkippedDestroy          ] = 
"The client failed to call ovr_Destroy on an active session before calling ovr_Shutdown.Or the client crashed.";
 
  304     error_messages[ovrError_ClientSkippedShutdown         ] = 
"The client failed to call ovr_Shutdown or the client crashed.";
 
  305     error_messages[ovrError_ServiceDeadlockDetected       ] = 
"The service watchdog discovered a deadlock.";
 
  306     error_messages[ovrError_InvalidOperation              ] = 
"Function call is invalid for object's current state.";
 
  307     error_messages[ovrError_AudioDeviceNotFound           ] = 
"Failure to find the specified audio device.";
 
  308     error_messages[ovrError_AudioComError                 ] = 
"Generic COM error.";
 
  309     error_messages[ovrError_Initialize                    ] = 
"Generic initialization error.";
 
  310     error_messages[ovrError_LibLoad                       ] = 
"Couldn't load LibOVRRT.";
 
  311     error_messages[ovrError_LibVersion                    ] = 
"LibOVRRT version incompatibility.";
 
  312     error_messages[ovrError_ServiceConnection             ] = 
"Couldn't connect to the OVR Service.";
 
  313     error_messages[ovrError_ServiceVersion                ] = 
"OVR Service version incompatibility.";
 
  314     error_messages[ovrError_IncompatibleOS                ] = 
"The operating system version is incompatible.";
 
  315     error_messages[ovrError_DisplayInit                   ] = 
"Unable to initialize the HMD display.";
 
  316     error_messages[ovrError_ServerStart                   ] = 
"Unable to start the server.Is it already running ?";
 
  317     error_messages[ovrError_Reinitialization              ] = 
"Attempting to re - initialize with a different version.";
 
  318     error_messages[ovrError_MismatchedAdapters            ] = 
"Chosen rendering adapters between client and service do not match.";
 
  319     error_messages[ovrError_LeakingResources              ] = 
"Calling application has leaked resources.";
 
  320     error_messages[ovrError_ClientVersion                 ] = 
"Client version too old to connect to service.";
 
  321     error_messages[ovrError_OutOfDateOS                   ] = 
"The operating system is out of date.";
 
  322     error_messages[ovrError_OutOfDateGfxDriver            ] = 
"The graphics driver is out of date.";
 
  323     error_messages[ovrError_IncompatibleGPU               ] = 
"The graphics hardware is not supported.";
 
  324     error_messages[ovrError_NoValidVRDisplaySystem        ] = 
"No valid VR display system found.";
 
  325     error_messages[ovrError_Obsolete                      ] = 
"Feature or API is obsolete and no longer supported.";
 
  326     error_messages[ovrError_DisabledOrDefaultAdapter      ] = 
"No supported VR display system found, but disabled or driverless adapter found.";
 
  327     error_messages[ovrError_HybridGraphicsNotSupported    ] = 
"The system is using hybrid graphics(Optimus, etc...), which is not support.";
 
  328     error_messages[ovrError_DisplayManagerInit            ] = 
"Initialization of the DisplayManager failed.";
 
  329     error_messages[ovrError_TrackerDriverInit             ] = 
"Failed to get the interface for an attached tracker.";
 
  330     error_messages[ovrError_LibSignCheck                  ] = 
"LibOVRRT signature check failure.";
 
  331     error_messages[ovrError_LibPath                       ] = 
"LibOVRRT path failure.";
 
  332     error_messages[ovrError_LibSymbols                    ] = 
"LibOVRRT symbol resolution failure.";
 
  333     error_messages[ovrError_RemoteSession                 ] = 
"Failed to connect to the service because remote connections to the service are not allowed.";
 
  334     error_messages[ovrError_DisplayLost                   ] = 
"In the event of a system - wide graphics reset or cable unplug this is returned to the app.";
 
  335     error_messages[ovrError_TextureSwapChainFull          ] = 
"ovr_CommitTextureSwapChain was called too many times on a texture swapchain without calling submit to use the chain.";
 
  336     error_messages[ovrError_TextureSwapChainInvalid       ] = 
"The ovrTextureSwapChain is in an incomplete or inconsistent state.Ensure ovr_CommitTextureSwapChain was called at least once first.";
 
  337     error_messages[ovrError_GraphicsDeviceReset           ] = 
"Graphics device has been reset(TDR, etc...)";
 
  338     error_messages[ovrError_DisplayRemoved                ] = 
"HMD removed from the display adapter.";
 
  339     error_messages[ovrError_ContentProtectionNotAvailable ] = 
"Content protection is not available for the display.";
 
  340     error_messages[ovrError_ApplicationInvisible          ] = 
"Application declared itself as an invisible type and is not allowed to submit frames.";
 
  341     error_messages[ovrError_Disallowed                    ] = 
"The given request is disallowed under the current conditions.";
 
  342     error_messages[ovrError_DisplayPluggedIncorrectly     ] = 
"Display portion of HMD is plugged into an incompatible port(ex: IGP)";
 
  343     error_messages[ovrError_RuntimeException              ] = 
"A runtime exception occurred.The application is required to shutdown LibOVR and re - initialize it before this error state will be cleared.";
 
  344     error_messages[ovrError_NoCalibration                 ] = 
"Result of a missing calibration block.";
 
  345     error_messages[ovrError_OldVersion                    ] = 
"Result of an old calibration block.";
 
  346     error_messages[ovrError_MisformattedBlock             ] = 
"Result of a bad calibration block due to lengths.";
 
  349 void yarp::dev::OVRHeadset::fillButtonStorage()
 
  351     buttonIdToOvrButton.push_back(ovrButton_A);
 
  352     buttonIdToOvrButton.push_back(ovrButton_B);
 
  353     buttonIdToOvrButton.push_back(ovrButton_RThumb);
 
  354     buttonIdToOvrButton.push_back(ovrButton_RShoulder);
 
  355     buttonIdToOvrButton.push_back(ovrButton_X);
 
  356     buttonIdToOvrButton.push_back(ovrButton_Y);
 
  357     buttonIdToOvrButton.push_back(ovrButton_LThumb);
 
  358     buttonIdToOvrButton.push_back(ovrButton_LShoulder);
 
  359     buttonIdToOvrButton.push_back(ovrButton_Enter);
 
  360     buttonIdToOvrButton.push_back(ovrButton_Back);
 
  361     buttonIdToOvrButton.push_back(ovrButton_VolUp);
 
  362     buttonIdToOvrButton.push_back(ovrButton_VolDown);
 
  363     buttonIdToOvrButton.push_back(ovrButton_Home);
 
  366 void yarp::dev::OVRHeadset::fillHatStorage()
 
  379     typedef std::vector<std::pair<yarp::os::BufferedPort<yarp::os::Bottle>**, std::string> > port_params;
 
  380     typedef std::vector<std::tuple<std::string, std::string, bool*, bool> >                 optionalParamType;
 
  384     optionalParamType  optionalParams;
 
  385     std::string        standardPortPrefix;
 
  387     standardPortPrefix = 
"/oculus";
 
  391         constexpr 
unsigned int STRING = 0;
 
  392         constexpr 
unsigned int BOOL   = 1;
 
  393         constexpr 
unsigned int INT    = 2;
 
  394         constexpr 
unsigned int DOUBLE = 3;
 
  396         std::map<int, std::string>                err_msgs;
 
  397         std::map<int, valueIsType>                isFunctionMap;
 
  398         std::vector<std::pair<std::string, int> > paramParser;
 
  400         err_msgs[STRING]      = 
"a string";
 
  401         err_msgs[BOOL]        = 
"a boolean type";
 
  402         err_msgs[INT]         = 
"an integer type";
 
  403         err_msgs[DOUBLE]      = 
"a real type";
 
  410         paramParser.push_back(std::make_pair(
"tfDevice",            STRING));
 
  411         paramParser.push_back(std::make_pair(
"tfLocal",             STRING));
 
  412         paramParser.push_back(std::make_pair(
"tfRemote",            STRING));
 
  413         paramParser.push_back(std::make_pair(
"tf_left_hand_frame",  STRING));
 
  414         paramParser.push_back(std::make_pair(
"tf_right_hand_frame", STRING));
 
  415         paramParser.push_back(std::make_pair(
"tf_root_frame",       STRING));
 
  416         paramParser.push_back(std::make_pair(
"stick_as_axis",       BOOL));
 
  417         paramParser.push_back(std::make_pair(
"gui_elements",        INT));
 
  419         for (
auto& p : paramParser)
 
  421             if (!cfg.
check(p.first) || !(cfg.
find(p.first).*isFunctionMap[p.second])())
 
  423                 std::string err_type = err_msgs.find(p.second) == err_msgs.end() ? 
"[unknown type]" : err_msgs[p.second];
 
  424                 yCError(
OVRHEADSET) << 
"ovrHeadset: parameter" << p.first << 
"not found or not" << err_type << 
"in configuration file";
 
  432             paramParser.push_back(std::make_pair(
"width",  DOUBLE));
 
  433             paramParser.push_back(std::make_pair(
"height", DOUBLE));
 
  434             paramParser.push_back(std::make_pair(
"x",      DOUBLE));
 
  435             paramParser.push_back(std::make_pair(
"y",      DOUBLE));
 
  436             paramParser.push_back(std::make_pair(
"z",      DOUBLE));
 
  437             paramParser.push_back(std::make_pair(
"alpha",  DOUBLE));
 
  439             for (
unsigned int i = 0; i < guiCount; ++i)
 
  441                 std::string       groupName  = 
"GUI_" + std::to_string(i);
 
  447                     yCError(
OVRHEADSET) << 
"group:" << groupName << 
"not found in configuration file..";
 
  451                 for (
auto& p : paramParser)
 
  453                     if (!guip.
check(p.first) || !(guip.
find(p.first).*isFunctionMap[p.second])())
 
  455                         std::string err_type = err_msgs.find(p.second) == err_msgs.end() ? 
"[unknow type]" : err_msgs[p.second];
 
  456                         yCError(
OVRHEADSET) << 
"ovrHeadset: parameter" << p.first << 
"not found or not" << err_type << 
"in" << groupName << 
"group in configuration file";
 
  469                 std::transform(groupName.begin(), groupName.end(), groupName.begin(), ::tolower);
 
  470                 hud.
port->
open(standardPortPrefix + 
"/" + groupName);
 
  482     getStickAsAxis = cfg.
find(
"stick_as_axis").
asBool();
 
  484     right_frame    = cfg.
find(
"tf_right_hand_frame").
asString();
 
  500     if (!driver.open(tfClientCfg))
 
  506     if (!driver.view(tfPublisher) || tfPublisher == 
nullptr)
 
  508         yCError(
OVRHEADSET) << 
"unable to dynamic cast device to IFrameTransform interface";
 
  516         { &orientationPort,                  
"orientation"                  },
 
  517         { &positionPort,                     
"position"                     },
 
  518         { &angularVelocityPort,              
"angularVelocity"              },
 
  519         { &linearVelocityPort,               
"linearVelocity"               },
 
  520         { &angularAccelerationPort,          
"angularAcceleration"          },
 
  521         { &linearAccelerationPort,           
"linearAcceleration"           },
 
  522         { &predictedOrientationPort,         
"predictedOrientation"         },
 
  523         { &predictedPositionPort,            
"predictedPosition"            },
 
  524         { &predictedAngularVelocityPort,     
"predictedAngularVelocity"     },
 
  525         { &predictedLinearVelocityPort,      
"predictedLinearVelocity"      },
 
  526         { &predictedAngularAccelerationPort, 
"predictedAngularAcceleration" },
 
  527         { &predictedLinearAccelerationPort,  
"predictedLinearAcceleration"  }
 
  530     for (
auto port : ports)
 
  532         std::string name, prefix;
 
  536         predicted   = port.second.find(
"predicted") != std::string::npos;
 
  537         prefix      = predicted ? standardPortPrefix+
"/predicted" : standardPortPrefix;
 
  538         name        = prefix + 
"/headpose/" + port.second + 
":o";
 
  540         if (!(*port.first)->open(name))
 
  547         (*port.first)->setWriteOnly();
 
  551     for (
int eye = 0; 
eye < ovrEye_Count; ++
eye) {
 
  553         if (!displayPorts[
eye]->open(
eye == ovrEye_Left ? 
"/oculus/display/left:i" : 
"/oculus/display/right:i")) {
 
  554             yCError(
OVRHEADSET) << 
"Cannot open " << (
eye == ovrEye_Left ? 
"left" : 
"right") << 
"display port";
 
  558         displayPorts[
eye]->setReadOnly();
 
  561     texWidth  = cfg.
check(
"w",    
yarp::os::Value(640), 
"Texture width (usually same as camera width)").asInt32();
 
  562     texHeight = cfg.
check(
"h",    
yarp::os::Value(480), 
"Texture height (usually same as camera height)").asInt32();
 
  565     double hfov   = cfg.
check(
"hfov", 
yarp::os::Value(105.),  
"Camera horizontal field of view").asFloat64();
 
  572         { 
"flipinput",     
"[F] Enable input flipping",                &flipInputEnabled,  
true },
 
  573         { 
"no-imagepose",  
"[I] Disable image pose",                   &imagePoseEnabled,  
false },
 
  574         { 
"userpose",      
"[U] Use user pose instead of camera pose", &userPoseEnabled,   
true  },
 
  575         { 
"no-logo",       
"[L] Disable logo",                         &logoEnabled,       
false },
 
  576         { 
"no-crosshairs", 
"[C] Disable crosshairs",                   &crosshairsEnabled, 
false },
 
  577         { 
"no-battery",    
"[B] Disable battery",                      &batteryEnabled,    
false }
 
  580     for (
auto p : optionalParams)
 
  582         if (cfg.
check(std::get<0>(p), std::get<1>(p)))
 
  584             *std::get<2>(p) = std::get<3>(p);
 
  590     displayPorts[0]->rollOffset  = 
static_cast<float>(cfg.
check(
"left-roll-offset",   
yarp::os::Value(0.0), 
"[LEFT_SHIFT+PAGE_UP][LEFT_SHIFT+PAGE_DOWN] Left eye roll offset").asFloat64());
 
  591     displayPorts[0]->pitchOffset = 
static_cast<float>(cfg.
check(
"left-pitch-offset",  
yarp::os::Value(0.0), 
"[LEFT_SHIFT+UP_ARROW][LEFT_SHIFT+DOWN_ARROW] Left eye pitch offset").asFloat64());
 
  592     displayPorts[0]->yawOffset   = 
static_cast<float>(cfg.
check(
"left-yaw-offset",    
yarp::os::Value(0.0), 
"[LEFT_SHIFT+LEFT_ARROW][LEFT_SHIFT+RIGHT_ARROW] Left eye yaw offset").asFloat64());
 
  593     displayPorts[1]->rollOffset  = 
static_cast<float>(cfg.
check(
"right-roll-offset",  
yarp::os::Value(0.0), 
"[RIGHT_SHIFT+PAGE_UP][RIGHT_SHIFT+PAGE_DOWN] Right eye roll offset").asFloat64());
 
  594     displayPorts[1]->pitchOffset = 
static_cast<float>(cfg.
check(
"right-pitch-offset", 
yarp::os::Value(0.0), 
"[RIGHT_SHIFT+UP_ARROW][RIGHT_SHIFT+DOWN_ARROW] Right eye pitch offset").asFloat64());
 
  595     displayPorts[1]->yawOffset   = 
static_cast<float>(cfg.
check(
"right-yaw-offset",   
yarp::os::Value(0.0), 
"[RIGHT_SHIFT+LEFT_ARROW][RIGHT_SHIFT+RIGHT_ARROW] Right eye yaw offset").asFloat64());
 
  598     if (!this->start()) {
 
  605     for (
int eye = 0; 
eye < ovrEye_Count; ++
eye) {
 
  606         displayPorts[
eye]->useCallback();
 
  618     ovrInitParams initParams = { ovrInit_RequestVersion | ovrInit_FocusAware, OVR_MINOR_VERSION, ovrDebugCallback, 
reinterpret_cast<uintptr_t
>(
this), 0 };
 
  619     ovrResult r = ovr_Initialize(&initParams);
 
  621     if (!OVR_SUCCESS(r)) {
 
  626     ovrGraphicsLuid luid;
 
  627     ovrResult result = ovr_Create(&session, &luid);
 
  628     if (!OVR_SUCCESS(result)) {
 
  644     ovr_SetTrackingOriginType(session, ovrTrackingOrigin_EyeLevel);
 
  646     hmdDesc = ovr_GetHmdDesc(session);
 
  647     if (hmdDesc.ProductName[0] == 
'\0') {
 
  661     glfwSetErrorCallback(glfwErrorCallback);
 
  663     OVR::Sizei windowSize = hmdDesc.Resolution;
 
  665     if (!createWindow(windowSize.w, windowSize.h)) {
 
  674     glewExperimental = GL_TRUE;
 
  675     GLenum err = glewInit();
 
  676     if (err != GLEW_OK) {
 
  681     yCInfo(
OVRHEADSET) << 
"Using GLEW" << (
const char*)glewGetString(GLEW_VERSION);
 
  685     int fbwidth, fbheight;
 
  686     glfwGetFramebufferSize(window, &fbwidth, &fbheight);
 
  688     for (
int eye = 0; 
eye < ovrEye_Count; ++
eye) {
 
  689         camWidth[
eye] = texWidth;
 
  690         camHeight[
eye] = texHeight;
 
  694     reconfigureRendering();
 
  696     for (
int eye = 0; 
eye < ovrEye_Count; ++
eye) {
 
  697         displayPorts[
eye]->eyeRenderTexture = 
new TextureBuffer(texWidth, texHeight, 
eye, session);
 
  704     ovrMirrorTextureDesc desc;
 
  705     memset(&desc, 0, 
sizeof(desc));
 
  706     desc.Width = windowSize.w;
 
  707     desc.Height = windowSize.h;
 
  708     desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
 
  711     result = ovr_CreateMirrorTextureGL(session, &desc, &mirrorTexture);
 
  712     if (!OVR_SUCCESS(result))
 
  721     ovr_GetMirrorTextureBufferGL(session, mirrorTexture, &texId);
 
  723     glGenFramebuffers(1, &mirrorFBO);
 
  724     glBindFramebuffer(GL_READ_FRAMEBUFFER, mirrorFBO);
 
  725     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId, 0);
 
  726     glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
 
  727     glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
 
  730     ovr_RecenterTrackingOrigin(session);
 
  748         glDeleteFramebuffers(1, &mirrorFBO);
 
  752         ovr_DestroyMirrorTexture(session, mirrorTexture);
 
  757         textureLogo = 
nullptr;
 
  760     if (textureCrosshairs) {
 
  761         delete textureCrosshairs;
 
  762         textureCrosshairs = 
nullptr;
 
  765     if (textureBattery) {
 
  766         delete textureBattery;
 
  767         textureBattery = 
nullptr;
 
  777         int PerfHudMode = (int)ovrPerfHud_Off;
 
  778         ovr_SetInt(session, OVR_PERF_HUD_MODE, PerfHudMode);
 
  780         ovr_Destroy(session);
 
  784     std::vector<yarp::os::Contactable*> ports;
 
  786     ports.push_back(orientationPort);
 
  787     ports.push_back(positionPort);
 
  788     ports.push_back(angularVelocityPort);
 
  789     ports.push_back(linearVelocityPort);
 
  790     ports.push_back(angularAccelerationPort);
 
  791     ports.push_back(linearAccelerationPort);
 
  792     ports.push_back(predictedOrientationPort);
 
  793     ports.push_back(predictedPositionPort);
 
  794     ports.push_back(predictedAngularVelocityPort);
 
  795     ports.push_back(predictedLinearVelocityPort);
 
  796     ports.push_back(predictedAngularAccelerationPort);
 
  797     ports.push_back(predictedLinearAccelerationPort);
 
  799     for (
auto& hud : huds)
 
  802         ports.push_back(hud.port);
 
  805     for (
auto& p : ports)
 
  817     for (
int eye = 0; 
eye < ovrEye_Count; ++
eye) {
 
  818         if (displayPorts[
eye]) {
 
  819             displayPorts[
eye]->disableCallback();
 
  820             displayPorts[
eye]->interrupt();
 
  821             displayPorts[
eye]->close();
 
  822             delete displayPorts[
eye];
 
  823             displayPorts[
eye] = 
nullptr;
 
  847     constexpr 
double delay = 60.0;
 
  849             "Thread ran %d times, est period %lf[ms], used %lf[ms]",
 
  851             getEstimatedPeriod()*1000,
 
  852             getEstimatedUsed()*1000);
 
  854             "Display refresh: %3.1f[hz]", getIterations()/
delay);
 
  856     for (
int eye = 0; 
eye < ovrEye_Count; ++
eye) {
 
  858                 "%s eye: %3.1f[hz] - %d of %d frames missing, %d of %d frames dropped",
 
  859                 (
eye == ovrEye_Left ? 
"Left " : 
"Right"),
 
  860                 (getIterations() - displayPorts[
eye]->eyeRenderTexture->missingFrames) / 
delay,
 
  861                 displayPorts[
eye]->eyeRenderTexture->missingFrames,
 
  863                 displayPorts[
eye]->droppedFrames,
 
  865         displayPorts[
eye]->eyeRenderTexture->missingFrames = 0;
 
  867         displayPorts[
eye]->droppedFrames = 0;
 
  879     return this->close();
 
  882 void yarp::dev::OVRHeadset::resetInput()
 
  884     inputStateMutex.lock();
 
  885     inputState.Buttons = 0;
 
  886     inputState.HandTrigger[0] = 0;
 
  887     inputState.HandTrigger[1] = 0;
 
  888     inputState.IndexTrigger[0] = 0;
 
  889     inputState.IndexTrigger[1] = 0;
 
  890     inputState.Thumbstick[0].x = 0;
 
  891     inputState.Thumbstick[0].y = 0;
 
  892     inputState.Thumbstick[1].x = 0;
 
  893     inputState.Thumbstick[1].y = 0;
 
  894     inputStateMutex.unlock();
 
  899     ovrResult        result = ovrError_InvalidSession;
 
  900     ovrSessionStatus sessionStatus;
 
  902     if (glfwWindowShouldClose(window)) {
 
  908     ovr_GetSessionStatus(session, &sessionStatus);
 
  909     if (sessionStatus.ShouldQuit) {
 
  914     if (sessionStatus.ShouldRecenter) {
 
  915         ovr_RecenterTrackingOrigin(session);
 
  921     if (!sessionStatus.IsVisible) {
 
  926     if (!sessionStatus.HasInputFocus) {
 
  931     ++distortionFrameIndex;
 
  932     double frameTiming = ovr_GetPredictedDisplayTime(session, distortionFrameIndex);
 
  936     ts = ovr_GetTrackingState(session, ovr_GetTimeInSeconds(), 
false);
 
  937     headpose = ts.HeadPose;
 
  938     yarp::os::Stamp stamp(distortionFrameIndex, ts.HeadPose.TimeInSeconds);
 
  941     ovrPosef ViewPose[2] = {EyeRenderDesc[0].HmdToEyePose,EyeRenderDesc[1].HmdToEyePose};
 
  942     ovrPosef EyeRenderPose[2];
 
  943     ovr_CalcEyePoses(headpose.ThePose, ViewPose, EyeRenderPose);
 
  946     ovrTrackingState predicted_ts = ovr_GetTrackingState(session, ovr_GetTimeInSeconds() + prediction, 
false);
 
  947     ovrPoseStatef predicted_headpose = predicted_ts.HeadPose;
 
  948     yarp::os::Stamp predicted_stamp(distortionFrameIndex, predicted_ts.HeadPose.TimeInSeconds);
 
  953         yarp::sig::Matrix T_Conv(4, 4), T_Head(4, 4), T_LHand(4, 4), T_RHand(4, 4), T_robotHead(4, 4);
 
  956         tfPublisher->getTransform(
"head_link", 
"mobile_base_body_link", T_robotHead);
 
  957         ovrVector3f& leftH = ts.HandPoses[ovrHand_Left].ThePose.Position;
 
  958         ovrVector3f& rightH = ts.HandPoses[ovrHand_Right].ThePose.Position;
 
  960         T_RHand    = 
ovr2matrix(
vecSubtract(rightH, headpose.ThePose.Position), OVR::Quatf(ts.HandPoses[ovrHand_Right].ThePose.Orientation) * OVR::Quatf(OVR::Vector3f(0, 0, 1), M_PI_2));
 
  961         T_LHand    = 
ovr2matrix(
vecSubtract(leftH, headpose.ThePose.Position), OVR::Quatf(ts.HandPoses[ovrHand_Left].ThePose.Orientation)   * OVR::Quatf(OVR::Vector3f(0, 0, 1), M_PI_2));
 
  962         T_Head     = 
ovr2matrix(headpose.ThePose.Position, headpose.ThePose.Orientation);
 
  966         rpyHead[1] = rpyRobot[1];
 
  967         rpyHead[2] = rpyRobot[2];
 
  970         tfPublisher->setTransform(left_frame,    root_frame, 
operator*(T_Head.transposed(), T_LHand));
 
  971         tfPublisher->setTransform(right_frame,   root_frame, 
operator*(T_Head.transposed(), T_RHand));
 
  977         OVR::Quatf lRot = OVR::Quatf(ts.HandPoses[ovrHand_Left].ThePose.Orientation)  * OVR::Quatf(OVR::Vector3f(0, 0, 1), M_PI_2);
 
  978         OVR::Quatf rRot = OVR::Quatf(ts.HandPoses[ovrHand_Right].ThePose.Orientation) * OVR::Quatf(OVR::Vector3f(0, 0, 1), M_PI_2);
 
  979         tfPublisher->setTransform(left_frame, 
"mobile_base_body_link", 
ovr2matrix(ts.HandPoses[ovrHand_Left].ThePose.Position,   lRot));
 
  980         tfPublisher->setTransform(right_frame, 
"mobile_base_body_link", 
ovr2matrix(ts.HandPoses[ovrHand_Right].ThePose.Position, rRot));
 
  986     inputStateMutex.lock();
 
  987     result = ovr_GetInputState(session, ovrControllerType_Active, &inputState);
 
  988     inputStateMutex.unlock();
 
  989     if (!OVR_SUCCESS(result))
 
  991         errorManager(result);
 
  992         inputStateError = 
true;
 
  996     if (ts.StatusFlags & ovrStatus_OrientationTracked) {
 
  998         if (orientationPort->getOutputCount() > 0) {
 
  999             OVR::Quatf orientation = headpose.ThePose.Orientation;
 
 1000             float yaw, pitch, roll;
 
 1001             orientation.GetEulerAngles<OVR::Axis_Y, OVR::Axis_X, OVR::Axis_Z>(&yaw, &pitch, &roll);
 
 1003             output_orientation.
clear();
 
 1004             output_orientation.addFloat64(OVR::RadToDegree(pitch));
 
 1005             output_orientation.addFloat64(OVR::RadToDegree(-roll));
 
 1006             output_orientation.addFloat64(OVR::RadToDegree(yaw));
 
 1007             orientationPort->setEnvelope(stamp);
 
 1008             orientationPort->write();
 
 1016         static double lastOrientWarnTime = 0;
 
 1018         if (
now >= lastOrientWarnTime + 5) {
 
 1020             lastOrientWarnTime = 
now;
 
 1025     if (ts.StatusFlags & ovrStatus_PositionTracked) {
 
 1028         writeVec3OnPort(linearAccelerationPort, headpose.LinearAcceleration, stamp);
 
 1032         static double lastPosWarnTime = 0;
 
 1034         if (
now >= lastPosWarnTime + 5) {
 
 1036             lastPosWarnTime = 
now;
 
 1041     if (predicted_ts.StatusFlags & ovrStatus_OrientationTracked) {
 
 1043         if (predictedOrientationPort->getOutputCount() > 0) {
 
 1044             OVR::Quatf orientation = predicted_headpose.ThePose.Orientation;
 
 1045             float yaw, pitch, roll;
 
 1046             orientation.GetEulerAngles<OVR::Axis_Y, OVR::Axis_X, OVR::Axis_Z>(&yaw, &pitch, &roll);
 
 1047             yarp::os::Bottle& output_orientation = predictedOrientationPort->prepare();
 
 1048             output_orientation.
clear();
 
 1049             output_orientation.addFloat64(OVR::RadToDegree(pitch));
 
 1050             output_orientation.addFloat64(OVR::RadToDegree(-roll));
 
 1051             output_orientation.addFloat64(OVR::RadToDegree(yaw));
 
 1052             predictedOrientationPort->setEnvelope(predicted_stamp);
 
 1053             predictedOrientationPort->write();
 
 1061         static double lastPredOrientWarnTime = 0;
 
 1063         if (
now >= lastPredOrientWarnTime + 5) {
 
 1065             lastPredOrientWarnTime = 
now;
 
 1070     if (predicted_ts.StatusFlags & ovrStatus_PositionTracked) {
 
 1072         writeVec3OnPort(predictedPositionPort,           predicted_headpose.ThePose.Position,   stamp);
 
 1073         writeVec3OnPort(predictedLinearVelocityPort,     predicted_headpose.LinearVelocity,     stamp);
 
 1074         writeVec3OnPort(predictedLinearAccelerationPort, predicted_headpose.LinearAcceleration, stamp);
 
 1078         static double lastPredPosWarnTime = 0;
 
 1080         if (
now >= lastPredPosWarnTime + 5) {
 
 1082             lastPredPosWarnTime = 
now;
 
 1087     if (displayPorts[0]->eyeRenderTexture && displayPorts[1]->eyeRenderTexture) {
 
 1091         for (
int eye = 0; 
eye < ovrEye_Count; ++
eye) {
 
 1092             displayPorts[
eye]->eyeRenderTexture->update();
 
 1096         for (
int eye = 0; 
eye < ovrEye_Count; ++
eye) {
 
 1097             if (imagePoseEnabled) {
 
 1098                 if (userPoseEnabled) {
 
 1100                     EyeRenderPose[
eye].Orientation = headpose.ThePose.Orientation;
 
 1103                     EyeRenderPose[
eye].Orientation = displayPorts[
eye]->eyeRenderTexture->eyePose.Orientation;
 
 1106                 EyeRenderPose[
eye].Orientation.w = -1.0f;
 
 1107                 EyeRenderPose[
eye].Orientation.x = 0.0f;
 
 1108                 EyeRenderPose[
eye].Orientation.y = 0.0f;
 
 1109                 EyeRenderPose[
eye].Orientation.z = 0.0f;
 
 1114         bool needReconfigureFOV = 
false;
 
 1115         for (
int eye = 0; 
eye < ovrEye_Count; ++
eye) {
 
 1116             if ((displayPorts[
eye]->eyeRenderTexture->imageWidth != 0 && displayPorts[
eye]->eyeRenderTexture->imageWidth != camWidth[
eye]) ||
 
 1117                 (displayPorts[
eye]->eyeRenderTexture->imageHeight != 0 && displayPorts[
eye]->eyeRenderTexture->imageHeight != camHeight[
eye])) {
 
 1119                 camWidth[
eye] = displayPorts[
eye]->eyeRenderTexture->imageWidth;
 
 1120                 camHeight[
eye] = displayPorts[
eye]->eyeRenderTexture->imageHeight;
 
 1121                 needReconfigureFOV = 
true;
 
 1124         if (needReconfigureFOV) {
 
 1126             reconfigureRendering();
 
 1129         std::list<ovrLayerHeader*> layerList;
 
 1131         ovrLayerEyeFov eyeLayer;
 
 1132         eyeLayer.Header.Type = ovrLayerType_EyeFov;
 
 1133         eyeLayer.Header.Flags = ovrLayerFlag_HighQuality;
 
 1134         if (flipInputEnabled) {
 
 1135             eyeLayer.Header.Flags |= ovrLayerFlag_TextureOriginAtBottomLeft;
 
 1138             eyeLayer.ColorTexture[
eye] = displayPorts[
eye]->eyeRenderTexture->textureSwapChain;
 
 1139             eyeLayer.Viewport[
eye] = OVR::Recti(0, 0, displayPorts[
eye]->eyeRenderTexture->width, displayPorts[
eye]->eyeRenderTexture->height);
 
 1140             eyeLayer.Fov[
eye] = fov[
eye];
 
 1141             eyeLayer.RenderPose[
eye] = EyeRenderPose[
eye];
 
 1143         layerList.push_back(&eyeLayer.Header);
 
 1146             setHeadLockedLayer(logoLayer, textureLogo, 0.2f, -0.2f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.05f, 0.05f);
 
 1147             layerList.push_back(&logoLayer.Header);
 
 1150         if (crosshairsEnabled) {
 
 1151             setHeadLockedLayer(crosshairsLayer, textureCrosshairs, 0.0f, 0.0f, -5.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.08f, 0.08f);
 
 1152             layerList.push_back(&crosshairsLayer.Header);
 
 1155         if (batteryEnabled) {
 
 1156             setHeadLockedLayer(batteryLayer, textureBattery->currentTexture, 0.25f, 0.25f, -0.50f, 0.0f, 0.0f, 0.0f, 1.0f, 0.05f, 0.05f);
 
 1157             layerList.push_back(&batteryLayer.Header);
 
 1163             for (
auto& hud : huds)
 
 1165                 if (!hud.port->getInputCount())
 
 1174                     layerList.push_back(&hud.layer.Header);
 
 1178                 hud.texture->fromImage(session, *image, hud.alpha);
 
 1179                 setHeadLockedLayer(hud.layer, hud.texture, hud.x, hud.y, hud.z, 0.0f, 0.0f, 0.0f, 1.0f, hud.resizeW, hud.resizeH);
 
 1180                 layerList.push_back(&hud.layer.Header);
 
 1184         ovrLayerHeader** layers = 
new ovrLayerHeader*[layerList.size()];
 
 1185         std::copy(layerList.begin(), layerList.end(), layers);
 
 1187         ovr_WaitToBeginFrame(session, distortionFrameIndex);
 
 1188         ovr_BeginFrame(session, distortionFrameIndex);
 
 1189         ovr_EndFrame(session, distortionFrameIndex, 
nullptr, layers, layerList.size());
 
 1193         glBindFramebuffer(GL_READ_FRAMEBUFFER, mirrorFBO);
 
 1195         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
 
 1196         GLint bw = hmdDesc.Resolution.w;
 
 1197         GLint bh = hmdDesc.Resolution.h;
 
 1199         glfwGetWindowSize(window, &ww, &wh);
 
 1200         glBlitFramebuffer(0, bh, bw, 0, 0, 0, ww, wh, GL_COLOR_BUFFER_BIT, GL_NEAREST);
 
 1201         glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
 
 1205         glfwSwapBuffers(window);
 
 1209         static double lastImgWarnTime = 0;
 
 1211         if (
now >= lastImgWarnTime + 5) {
 
 1213             lastImgWarnTime = 
now;
 
 1218 bool yarp::dev::OVRHeadset::createWindow(
int w, 
int h)
 
 1221     glfwWindowHint(GLFW_DEPTH_BITS, 16);
 
 1222     window = glfwCreateWindow(w/2, h/2, 
"YARP Oculus", 
nullptr, 
nullptr);
 
 1228     glfwSetWindowUserPointer(window, 
this);
 
 1229     glfwSetKeyCallback(window, glfwKeyCallback);
 
 1230     glfwMakeContextCurrent(window);
 
 1235 void yarp::dev::OVRHeadset::onKey(
int key, 
int scancode, 
int action, 
int mods)
 
 1239     if (GLFW_PRESS != action) {
 
 1243     bool leftShiftPressed = (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS);
 
 1244     bool rightShiftPressed = (glfwGetKey(window, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS);
 
 1245     bool leftCtrlPressed = (glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS);
 
 1246     bool rightCtrlPressed = (glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS);
 
 1247     bool leftAltPressed = (glfwGetKey(window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS);
 
 1248     bool rightAltPressed = (glfwGetKey(window, GLFW_KEY_RIGHT_ALT) == GLFW_PRESS);
 
 1249     bool shiftPressed = leftShiftPressed || rightShiftPressed;
 
 1250     bool ctrlPressed = leftCtrlPressed || rightCtrlPressed;
 
 1251     bool altPressed = leftAltPressed || rightAltPressed;
 
 1256         if (!leftShiftPressed && !rightShiftPressed) {
 
 1258             ovr_RecenterTrackingOrigin(session);
 
 1261             for (
int eye = 0; 
eye < ovrEye_Count; ++
eye) {
 
 1262                 float iyaw, ipitch, iroll;
 
 1263                 if (imagePoseEnabled) {
 
 1264                     OVR::Quatf imageOrientation = displayPorts[
eye]->eyeRenderTexture->eyePose.Orientation;
 
 1265                     imageOrientation.GetEulerAngles<OVR::Axis_Y, OVR::Axis_X, OVR::Axis_Z>(&iyaw, &ipitch, &iroll);
 
 1272                 iyaw -= displayPorts[
eye]->yawOffset;
 
 1273                 displayPorts[
eye]->yawOffset = - iyaw;
 
 1274                 yCDebug(
OVRHEADSET) << (
eye == ovrEye_Left? 
"Left" : 
"Right") << 
"eye yaw offset =" << displayPorts[
eye]->yawOffset;
 
 1279         flipInputEnabled = !flipInputEnabled;
 
 1281         reconfigureRendering();
 
 1284         imagePoseEnabled = !imagePoseEnabled;
 
 1289         userPoseEnabled = !userPoseEnabled;
 
 1294         logoEnabled = !logoEnabled;
 
 1296             "Logo" << (logoEnabled ? 
"ON" : 
"OFF") <<
 
 1297             "Crosshairs" << (crosshairsEnabled ? 
"ON" : 
"OFF") <<
 
 1298             "Battery" << (batteryEnabled ? 
"ON" : 
"OFF") <<
 
 1299             "Gui" << ((guiCount != 0) ? (guiEnabled ? 
"ON" : 
"OFF") : 
"DISABLED");
 
 1302         crosshairsEnabled = !crosshairsEnabled;
 
 1304             "Logo" << (logoEnabled ? 
"ON" : 
"OFF") <<
 
 1305             "Crosshairs" << (crosshairsEnabled ? 
"ON" : 
"OFF") <<
 
 1306             "Battery" << (batteryEnabled ? 
"ON" : 
"OFF") <<
 
 1307             "Gui" << ((guiCount != 0) ? (guiEnabled ? 
"ON" : 
"OFF") : 
"DISABLED");
 
 1310         batteryEnabled = !batteryEnabled;
 
 1311         if (batteryEnabled) {
 
 1312             textureBattery->resume();
 
 1314             textureBattery->suspend();
 
 1317             "Logo" << (logoEnabled ? 
"ON" : 
"OFF") <<
 
 1318             "Crosshairs" << (crosshairsEnabled ? 
"ON" : 
"OFF") <<
 
 1319             "Battery" << (batteryEnabled ? 
"ON" : 
"OFF") <<
 
 1320             "Gui" << ((guiCount != 0) ? (guiEnabled ? 
"ON" : 
"OFF") : 
"DISABLED");
 
 1323         if (guiCount != 0) {
 
 1324             guiEnabled = !guiEnabled;
 
 1327             "Logo" << (logoEnabled ? 
"ON" : 
"OFF") <<
 
 1328             "Crosshairs" << (crosshairsEnabled ? 
"ON" : 
"OFF") <<
 
 1329             "Battery" << (batteryEnabled ? 
"ON" : 
"OFF") <<
 
 1330             "Gui" << ((guiCount != 0) ? (guiEnabled ? 
"ON" : 
"OFF") : 
"DISABLED") ;
 
 1332     case GLFW_KEY_ESCAPE:
 
 1336         if (!rightShiftPressed) {
 
 1340         if (!leftShiftPressed) {
 
 1345         reconfigureRendering();
 
 1348         if (!rightShiftPressed) {
 
 1352         if (!leftShiftPressed) {
 
 1357         reconfigureRendering();
 
 1360         if (!rightShiftPressed) {
 
 1361             displayPorts[0]->pitchOffset += ctrlPressed ? 0.05f : 0.0025f;
 
 1362             yCDebug(
OVRHEADSET) << 
"Left eye pitch offset =" << displayPorts[0]->pitchOffset;
 
 1364         if (!leftShiftPressed) {
 
 1365             displayPorts[1]->pitchOffset += ctrlPressed ? 0.05f : 0.0025f;
 
 1366             yCDebug(
OVRHEADSET) << 
"Right eye pitch offset =" << displayPorts[1]->pitchOffset;
 
 1370         if (!rightShiftPressed) {
 
 1371             displayPorts[0]->pitchOffset -= ctrlPressed ? 0.05f : 0.0025f;
 
 1372             yCDebug(
OVRHEADSET) << 
"Left eye pitch offset =" << displayPorts[0]->pitchOffset;
 
 1374         if (!leftShiftPressed) {
 
 1375             displayPorts[1]->pitchOffset -= ctrlPressed ? 0.05f : 0.0025f;
 
 1376             yCDebug(
OVRHEADSET) << 
"Right eye pitch offset =" << displayPorts[1]->pitchOffset;
 
 1380         if (!rightShiftPressed) {
 
 1381             displayPorts[0]->yawOffset += ctrlPressed ? 0.05f : 0.0025f;
 
 1384         if (!leftShiftPressed) {
 
 1385             displayPorts[1]->yawOffset += ctrlPressed ? 0.05f : 0.0025f;
 
 1389     case GLFW_KEY_RIGHT:
 
 1390         if (!rightShiftPressed) {
 
 1391             displayPorts[0]->yawOffset -= ctrlPressed ? 0.05f : 0.0025f;
 
 1394         if (!leftShiftPressed) {
 
 1395             displayPorts[1]->yawOffset -= ctrlPressed ? 0.05f : 0.0025f;
 
 1399     case GLFW_KEY_PAGE_UP:
 
 1400         if (!rightShiftPressed) {
 
 1401             displayPorts[0]->rollOffset += ctrlPressed ? 0.05f : 0.0025f;
 
 1404         if (!leftShiftPressed) {
 
 1405             displayPorts[1]->rollOffset += ctrlPressed ? 0.05f : 0.0025f;
 
 1406             yCDebug(
OVRHEADSET) << 
"Right eye roll offset =" << displayPorts[1]->rollOffset;
 
 1409     case GLFW_KEY_PAGE_DOWN:
 
 1410         if (!rightShiftPressed) {
 
 1411             displayPorts[0]->rollOffset -= ctrlPressed ? 0.05f : 0.0025f;
 
 1414         if (!leftShiftPressed) {
 
 1415             displayPorts[1]->rollOffset -= ctrlPressed ? 0.05f : 0.0025f;
 
 1416             yCDebug(
OVRHEADSET) << 
"Right eye roll offset =" << displayPorts[1]->rollOffset;
 
 1419     case GLFW_KEY_SLASH:
 
 1421             int PerfHudMode = ovr_GetInt(session, OVR_PERF_HUD_MODE, 0);
 
 1422             PerfHudMode = (PerfHudMode + 1) % 8;
 
 1423             ovr_SetInt(session, OVR_PERF_HUD_MODE, PerfHudMode);
 
 1436         yCDebug(
OVRHEADSET) << 
"    Gui" << ((guiCount != 0) ? (guiEnabled ? 
"ON" : 
"OFF") : 
"DISABLED");
 
 1454 void yarp::dev::OVRHeadset::reconfigureRendering()
 
 1456     for (
int eye = 0; 
eye < ovrEye_Count; ++
eye) {
 
 1457         ovr_GetRenderDesc(session, (ovrEyeType)
eye, fov[
eye]);
 
 1461 void yarp::dev::OVRHeadset::reconfigureFOV()
 
 1463     for (
int eye = 0; 
eye < ovrEye_Count; ++
eye) {
 
 1464         double camHFOV_rad = OVR::DegreeToRad(camHFOV[
eye]);
 
 1465         double texCamRatio = 
static_cast<double>(texWidth)/camWidth[
eye];
 
 1466         double texHFOV_rad = 2 * (atan(texCamRatio * tan(camHFOV_rad/2)));
 
 1468         double aspectRatio = 
static_cast<double>(texWidth)/texHeight;
 
 1469         fov[
eye].UpTan    = 
static_cast<float>(fabs(tan(texHFOV_rad/2)/aspectRatio));
 
 1470         fov[
eye].DownTan  = 
static_cast<float>(fabs(tan(texHFOV_rad/2)/aspectRatio));
 
 1471         fov[
eye].LeftTan  = 
static_cast<float>(fabs(tan(texHFOV_rad/2)));
 
 1472         fov[
eye].RightTan = 
static_cast<float>(fabs(tan(texHFOV_rad/2)));
 
 1477 void yarp::dev::OVRHeadset::glfwKeyCallback(GLFWwindow* window, 
int key, 
int scancode, 
int action, 
int mods)
 
 1479     OVRHeadset* instance = (OVRHeadset*)glfwGetWindowUserPointer(window);
 
 1480     instance->onKey(key, scancode, action, mods);
 
 1483 void yarp::dev::OVRHeadset::glfwErrorCallback(
int error, 
const char* description)
 
 1488 void yarp::dev::OVRHeadset::ovrDebugCallback(uintptr_t userData, 
int level, 
const char* message)
 
 1499     case ovrLogLevel_Debug:
 
 1502     case ovrLogLevel_Info:
 
 1505     case ovrLogLevel_Error:
 
 1514 void yarp::dev::OVRHeadset::DebugHmd(ovrHmdDesc hmdDesc)
 
 1518     yCDebug(
OVRHEADSET, 
"  * VendorId:ProductId: %04X:%04X", hmdDesc.VendorId, hmdDesc.ProductId);
 
 1520     yCDebug(
OVRHEADSET, 
"  * Firmware Version: %d.%d", hmdDesc.FirmwareMajor, hmdDesc.FirmwareMinor);
 
 1521     yCDebug(
OVRHEADSET, 
"  * Resolution: %dx%d", hmdDesc.Resolution.w, hmdDesc.Resolution.h);
 
 1524 void yarp::dev::OVRHeadset::errorManager(ovrResult error)
 
 1526     if (error_messages.find(error) != error_messages.end())
 
 1536     if (inputStateError) 
return false;
 
 1537     axis_count = axisIdToValue.size();
 
 1543     if (inputStateError) 
return false;
 
 1550     if (inputStateError) 
return false;
 
 1551     Trackball_count = 0;
 
 1557     if (inputStateError) 
return false;
 
 1564     if (inputStateError) 
return false;
 
 1571     if (inputStateError) 
return false;
 
 1584     if (inputStateError) 
return false;
 
 1585     std::lock_guard<std::mutex> lock(inputStateMutex);
 
 1586     if (button_id > buttonIdToOvrButton.size() - 1)
 
 1591     value = inputState.Buttons & buttonIdToOvrButton[button_id] ? 1.0f : 0.0f;
 
 1602     if (inputStateError) 
return false;
 
 1603     std::lock_guard<std::mutex> lock(inputStateMutex);
 
 1609     value = DButtonToHat[inputState.Buttons & ovrButton_Up]    |
 
 1610             DButtonToHat[inputState.Buttons & ovrButton_Down]  |
 
 1611             DButtonToHat[inputState.Buttons & ovrButton_Right] |
 
 1612             DButtonToHat[inputState.Buttons & ovrButton_Left];
 
 1618     std::lock_guard<std::mutex> lock(inputStateMutex);
 
 1619     if (axis_id > axisIdToValue.size())
 
 1625     value = *axisIdToValue[axis_id];
 
 1631     if (inputStateError) 
return false;
 
 1632     std::lock_guard<std::mutex> lock(inputStateMutex);
 
 1644     if (coordinate_mode == JoypadCtrl_coordinateMode::JypCtrlcoord_POLAR)
 
 1646         value.
push_back(sqrt(inputState.Thumbstick[stick_id].y * inputState.Thumbstick[stick_id].y +
 
 1647                              inputState.Thumbstick[stick_id].x * inputState.Thumbstick[stick_id].x));
 
 1649         value.
push_back(atan2(inputState.Thumbstick[stick_id].y, inputState.Thumbstick[stick_id].x));
 
 1651     value.
push_back(inputState.Thumbstick[stick_id].x);
 
 1652     value.
push_back(inputState.Thumbstick[stick_id].y);