diff --git a/examples/entityScripts/sprayPaintCan.js b/examples/entityScripts/sprayPaintCan.js index 4407140184..aa04e94341 100644 --- a/examples/entityScripts/sprayPaintCan.js +++ b/examples/entityScripts/sprayPaintCan.js @@ -1,7 +1,8 @@ (function() { // Script.include("../libraries/utils.js"); //Need absolute path for now, for testing before PR merge and s3 cloning. Will change post-merge - Script.include("https://hifi-public.s3.amazonaws.com/scripts/libraries/utils.js"); + + Script.include("../libraries/utils.js"); GRAB_FRAME_USER_DATA_KEY = "grabFrame"; this.userData = {}; @@ -56,26 +57,21 @@ timeSinceLastMoved = 0; } - if (self.userData.grabKey && self.userData.grabKey.activated === true) { + //Only activate for the user who grabbed the object + if (self.userData.grabKey && self.userData.grabKey.activated === true && self.userData.grabKey.avatarId == MyAvatar.sessionUUID) { if (self.activated !== true) { //We were just grabbed, so create a particle system self.grab(); - Entities.editEntity(self.paintStream, { - animationSettings: startSetting - }); } //Move emitter to where entity is always when its activated self.sprayStream(); } else if (self.userData.grabKey && self.userData.grabKey.activated === false && self.activated) { - Entities.editEntity(self.paintStream, { - animationSettings: stopSetting - }); - self.activated = false; + self.letGo(); } } this.grab = function() { - self.activated = true; + this.activated = true; var animationSettings = JSON.stringify({ fps: 30, loop: true, @@ -92,9 +88,9 @@ emitVelocity: ZERO_VEC, emitAcceleration: ZERO_VEC, velocitySpread: { - x: .02, - y: .02, - z: 0.02 + x: .1, + y: .1, + z: 0.1 }, emitRate: 100, particleRadius: 0.01, @@ -103,14 +99,14 @@ green: 20, blue: 150 }, - lifetime: 500, //probably wont be holding longer than this straight + lifetime: 50, //probably wont be holding longer than this straight }); - } this.letGo = function() { - self.activated = false; + this.activated = false; Entities.deleteEntity(this.paintStream); + this.paintStream = null; } this.reset = function() { @@ -123,8 +119,7 @@ } this.sprayStream = function() { - var forwardVec = Quat.getFront(self.properties.rotation); - forwardVec = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, 90, 0), forwardVec); + var forwardVec = Quat.getFront(Quat.multiply(self.properties.rotation , Quat.fromPitchYawRollDegrees(0, 90, 0))); forwardVec = Vec3.normalize(forwardVec); var upVec = Quat.getUp(self.properties.rotation); @@ -132,11 +127,10 @@ position = Vec3.sum(position, Vec3.multiply(upVec, TIP_OFFSET_Y)) Entities.editEntity(self.paintStream, { position: position, - emitVelocity: Vec3.multiply(forwardVec, 4) + emitVelocity: Vec3.multiply(5, forwardVec) }); //Now check for an intersection with an entity - //move forward so ray doesnt intersect with gun var origin = Vec3.sum(position, forwardVec); var pickRay = { @@ -216,6 +210,8 @@ this.entityId = entityId; this.properties = Entities.getEntityProperties(self.entityId); this.getUserData(); + + //Only activate for the avatar who is grabbing the can! if (this.userData.grabKey && this.userData.grabKey.activated) { this.activated = true; } @@ -235,7 +231,9 @@ this.unload = function() { Script.update.disconnect(this.update); - Entities.deleteEntity(this.paintStream); + if(this.paintStream) { + Entities.deleteEntity(this.paintStream); + } this.strokes.forEach(function(stroke) { Entities.deleteEntity(stroke); }); @@ -244,6 +242,7 @@ }); + function randFloat(min, max) { return Math.random() * (max - min) + min; } diff --git a/examples/sprayPaintSpawner.js b/examples/sprayPaintSpawner.js index 77b74e6520..3b9cee6ef4 100644 --- a/examples/sprayPaintSpawner.js +++ b/examples/sprayPaintSpawner.js @@ -9,9 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html //Just temporarily using my own bucket here so others can test the entity. Once PR is tested and merged, then the entity script will appear in its proper place in S3, and I wil switch it -var scriptURL = "https://hifi-public.s3.amazonaws.com/eric/scripts/sprayPaintCan.js?=v1"; +// var scriptURL = "https://hifi-public.s3.amazonaws.com/eric/scripts/sprayPaintCan.js?=v6 "; +var scriptURL = Script.resolvePath("entityScripts/sprayPaintCan.js?v2"); var modelURL = "https://hifi-public.s3.amazonaws.com/eric/models/paintcan.fbx"; -var center = Vec3.sum(MyAvatar.position, Vec3.multiply(1, Quat.getFront(Camera.getOrientation()))); var sprayCan = Entities.addEntity({ type: "Model", @@ -32,7 +32,10 @@ var sprayCan = Entities.addEntity({ }); function cleanup() { - Entities.deleteEntity(sprayCan); + + // Uncomment the below line to delete sprayCan on script reload- for faster iteration during development + // Entities.deleteEntity(sprayCan); } Script.scriptEnding.connect(cleanup); + diff --git a/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp index 598e78e500..4af45d299b 100644 --- a/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp @@ -16,6 +16,7 @@ #include "openvr/OpenVrDisplayPlugin.h" #include "oculus/OculusDisplayPlugin.h" +#include "oculus/OculusDebugDisplayPlugin.h" #include "oculus/OculusLegacyDisplayPlugin.h" const QString& DisplayPlugin::MENU_PATH() { @@ -42,6 +43,10 @@ DisplayPluginList getDisplayPlugins() { // Windows Oculus SDK new OculusDisplayPlugin(), + // Windows Oculus Simulator... uses head tracking and the same rendering + // as the connected hardware, but without using the SDK to display to the + // Rift. Useful for debugging Rift performance with nSight. + new OculusDebugDisplayPlugin(), // Mac/Linux Oculus SDK (0.5) new OculusLegacyDisplayPlugin(), #ifdef Q_OS_WIN diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.cpp new file mode 100644 index 0000000000..fa9d09e392 --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.cpp @@ -0,0 +1,151 @@ +// +// Created by Bradley Austin Davis on 2014/04/13. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "OculusBaseDisplayPlugin.h" + +#include + +#include "OculusHelpers.h" + +uvec2 OculusBaseDisplayPlugin::getRecommendedRenderSize() const { + return _desiredFramebufferSize; +} + +void OculusBaseDisplayPlugin::preRender() { +#if (OVR_MAJOR_VERSION >= 6) + ovrFrameTiming ftiming = ovr_GetFrameTiming(_hmd, _frameIndex); + _trackingState = ovr_GetTrackingState(_hmd, ftiming.DisplayMidpointSeconds); + ovr_CalcEyePoses(_trackingState.HeadPose.ThePose, _eyeOffsets, _eyePoses); +#endif +} + +glm::mat4 OculusBaseDisplayPlugin::getProjection(Eye eye, const glm::mat4& baseProjection) const { + return _eyeProjections[eye]; +} + +void OculusBaseDisplayPlugin::resetSensors() { +#if (OVR_MAJOR_VERSION >= 6) + ovr_RecenterPose(_hmd); +#endif +} + +glm::mat4 OculusBaseDisplayPlugin::getEyePose(Eye eye) const { + return toGlm(_eyePoses[eye]); +} + +glm::mat4 OculusBaseDisplayPlugin::getHeadPose() const { + return toGlm(_trackingState.HeadPose.ThePose); +} + +bool OculusBaseDisplayPlugin::isSupported() const { +#if (OVR_MAJOR_VERSION >= 6) + if (!OVR_SUCCESS(ovr_Initialize(nullptr))) { + return false; + } + bool result = false; + if (ovrHmd_Detect() > 0) { + result = true; + } + ovr_Shutdown(); + return result; +#else + return false; +#endif +} + +void OculusBaseDisplayPlugin::init() { +} + +void OculusBaseDisplayPlugin::deinit() { +} + +void OculusBaseDisplayPlugin::activate() { +#if (OVR_MAJOR_VERSION >= 6) + if (!OVR_SUCCESS(ovr_Initialize(nullptr))) { + qFatal("Could not init OVR"); + } + +#if (OVR_MAJOR_VERSION == 6) + if (!OVR_SUCCESS(ovr_Create(0, &_hmd))) { +#elif (OVR_MAJOR_VERSION == 7) + if (!OVR_SUCCESS(ovr_Create(&_hmd, &_luid))) { +#endif + Q_ASSERT(false); + qFatal("Failed to acquire HMD"); + } + + _hmdDesc = ovr_GetHmdDesc(_hmd); + + _ipd = ovr_GetFloat(_hmd, OVR_KEY_IPD, _ipd); + + glm::uvec2 eyeSizes[2]; + ovr_for_each_eye([&](ovrEyeType eye) { + _eyeFovs[eye] = _hmdDesc.DefaultEyeFov[eye]; + ovrEyeRenderDesc& erd = _eyeRenderDescs[eye] = ovr_GetRenderDesc(_hmd, eye, _eyeFovs[eye]); + ovrMatrix4f ovrPerspectiveProjection = + ovrMatrix4f_Projection(erd.Fov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded); + _eyeProjections[eye] = toGlm(ovrPerspectiveProjection); + + ovrPerspectiveProjection = + ovrMatrix4f_Projection(erd.Fov, 0.001f, 10.0f, ovrProjection_RightHanded); + _compositeEyeProjections[eye] = toGlm(ovrPerspectiveProjection); + + _eyeOffsets[eye] = erd.HmdToEyeViewOffset; + eyeSizes[eye] = toGlm(ovr_GetFovTextureSize(_hmd, eye, erd.Fov, 1.0f)); + }); + ovrFovPort combined = _eyeFovs[Left]; + combined.LeftTan = std::max(_eyeFovs[Left].LeftTan, _eyeFovs[Right].LeftTan); + combined.RightTan = std::max(_eyeFovs[Left].RightTan, _eyeFovs[Right].RightTan); + ovrMatrix4f ovrPerspectiveProjection = + ovrMatrix4f_Projection(combined, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded); + _eyeProjections[Mono] = toGlm(ovrPerspectiveProjection); + + + + _desiredFramebufferSize = uvec2( + eyeSizes[0].x + eyeSizes[1].x, + std::max(eyeSizes[0].y, eyeSizes[1].y)); + + _frameIndex = 0; + + if (!OVR_SUCCESS(ovr_ConfigureTracking(_hmd, + ovrTrackingCap_Orientation | ovrTrackingCap_Position | ovrTrackingCap_MagYawCorrection, 0))) { + qFatal("Could not attach to sensor device"); + } + + // Parent class relies on our _hmd intialization, so it must come after that. + memset(&_sceneLayer, 0, sizeof(ovrLayerEyeFov)); + _sceneLayer.Header.Type = ovrLayerType_EyeFov; + _sceneLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft; + ovr_for_each_eye([&](ovrEyeType eye) { + ovrFovPort & fov = _sceneLayer.Fov[eye] = _eyeRenderDescs[eye].Fov; + ovrSizei & size = _sceneLayer.Viewport[eye].Size = ovr_GetFovTextureSize(_hmd, eye, fov, 1.0f); + _sceneLayer.Viewport[eye].Pos = { eye == ovrEye_Left ? 0 : size.w, 0 }; + }); + + if (!OVR_SUCCESS(ovr_ConfigureTracking(_hmd, + ovrTrackingCap_Orientation | ovrTrackingCap_Position | ovrTrackingCap_MagYawCorrection, 0))) { + qFatal("Could not attach to sensor device"); + } +#endif + + WindowOpenGLDisplayPlugin::activate(); +} + +void OculusBaseDisplayPlugin::deactivate() { + WindowOpenGLDisplayPlugin::deactivate(); + +#if (OVR_MAJOR_VERSION >= 6) + ovr_Destroy(_hmd); + _hmd = nullptr; + ovr_Shutdown(); +#endif +} + +void OculusBaseDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSize) { + ++_frameIndex; +} diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.h new file mode 100644 index 0000000000..12023db1ae --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.h @@ -0,0 +1,79 @@ +// +// Created by Bradley Austin Davis on 2015/05/29 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#pragma once + +#include "../WindowOpenGLDisplayPlugin.h" + +#include + +#include + +class OculusBaseDisplayPlugin : public WindowOpenGLDisplayPlugin { +public: + virtual bool isSupported() const override; + + virtual void init() override final; + virtual void deinit() override final; + + virtual void activate() override; + virtual void deactivate() override; + + // Stereo specific methods + virtual bool isHmd() const override final { return true; } + virtual glm::mat4 getProjection(Eye eye, const glm::mat4& baseProjection) const override; + virtual glm::uvec2 getRecommendedRenderSize() const override final; + virtual glm::uvec2 getRecommendedUiSize() const override final { return uvec2(1920, 1080); } + virtual void resetSensors() override final; + virtual glm::mat4 getEyePose(Eye eye) const override final; + virtual glm::mat4 getHeadPose() const override final; + +protected: + virtual void preRender() override final; + virtual void display(GLuint finalTexture, const glm::uvec2& sceneSize) override; + +protected: + ovrPosef _eyePoses[2]; + + mat4 _eyeProjections[3]; + mat4 _compositeEyeProjections[2]; + uvec2 _desiredFramebufferSize; + ovrTrackingState _trackingState; + unsigned int _frameIndex{ 0 }; + +#if (OVR_MAJOR_VERSION >= 6) + ovrHmd _hmd; + float _ipd{ OVR_DEFAULT_IPD }; + ovrEyeRenderDesc _eyeRenderDescs[2]; + ovrVector3f _eyeOffsets[2]; + ovrFovPort _eyeFovs[2]; + ovrHmdDesc _hmdDesc; + ovrLayerEyeFov _sceneLayer; +#endif +#if (OVR_MAJOR_VERSION == 7) + ovrGraphicsLuid _luid; +#endif +}; + +#if (OVR_MAJOR_VERSION == 6) +#define ovr_Create ovrHmd_Create +#define ovr_CreateSwapTextureSetGL ovrHmd_CreateSwapTextureSetGL +#define ovr_CreateMirrorTextureGL ovrHmd_CreateMirrorTextureGL +#define ovr_Destroy ovrHmd_Destroy +#define ovr_DestroySwapTextureSet ovrHmd_DestroySwapTextureSet +#define ovr_DestroyMirrorTexture ovrHmd_DestroyMirrorTexture +#define ovr_GetFloat ovrHmd_GetFloat +#define ovr_GetFovTextureSize ovrHmd_GetFovTextureSize +#define ovr_GetFrameTiming ovrHmd_GetFrameTiming +#define ovr_GetTrackingState ovrHmd_GetTrackingState +#define ovr_GetRenderDesc ovrHmd_GetRenderDesc +#define ovr_RecenterPose ovrHmd_RecenterPose +#define ovr_SubmitFrame ovrHmd_SubmitFrame +#define ovr_ConfigureTracking ovrHmd_ConfigureTracking + +#define ovr_GetHmdDesc(X) *X +#endif diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusDebugDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/oculus/OculusDebugDisplayPlugin.cpp new file mode 100644 index 0000000000..2021ce1c5a --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusDebugDisplayPlugin.cpp @@ -0,0 +1,40 @@ +// +// Created by Bradley Austin Davis on 2014/04/13. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "OculusDebugDisplayPlugin.h" +#include + +const QString OculusDebugDisplayPlugin::NAME("Oculus Rift (Simulator)"); + +const QString & OculusDebugDisplayPlugin::getName() const { + return NAME; +} + +static const QString DEBUG_FLAG("HIFI_DEBUG_OCULUS"); +static bool enableDebugOculus = QProcessEnvironment::systemEnvironment().contains("HIFI_DEBUG_OCULUS"); + +bool OculusDebugDisplayPlugin::isSupported() const { + if (!enableDebugOculus) { + return false; + } + return OculusBaseDisplayPlugin::isSupported(); +} + +void OculusDebugDisplayPlugin::customizeContext() { + WindowOpenGLDisplayPlugin::customizeContext(); + enableVsync(false); +} + +void OculusDebugDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSize) { + WindowOpenGLDisplayPlugin::display(finalTexture, sceneSize); + OculusBaseDisplayPlugin::display(finalTexture, sceneSize); +} + +void OculusDebugDisplayPlugin::finishFrame() { + swapBuffers(); + doneCurrent(); +}; diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusDebugDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/oculus/OculusDebugDisplayPlugin.h new file mode 100644 index 0000000000..d23c6ba567 --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusDebugDisplayPlugin.h @@ -0,0 +1,26 @@ +// +// Created by Bradley Austin Davis on 2015/05/29 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#pragma once + +#include "OculusBaseDisplayPlugin.h" + +class OculusDebugDisplayPlugin : public OculusBaseDisplayPlugin { +public: + virtual const QString & getName() const override; + virtual bool isSupported() const override; + +protected: + virtual void display(GLuint finalTexture, const glm::uvec2& sceneSize) override; + virtual void customizeContext() override; + // Do not perform swap in finish + virtual void finishFrame() override; + +private: + static const QString NAME; +}; + diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/oculus/OculusDisplayPlugin.cpp index 2f4a9c93cf..58675eab4d 100644 --- a/libraries/display-plugins/src/display-plugins/oculus/OculusDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusDisplayPlugin.cpp @@ -7,59 +7,10 @@ // #include "OculusDisplayPlugin.h" -#include - -#include #include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - - -#if defined(__GNUC__) && !defined(__clang__) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdouble-promotion" -#endif - -#include - -#if defined(__GNUC__) && !defined(__clang__) - #pragma GCC diagnostic pop -#endif - - -#include -#include -#include #include "OculusHelpers.h" -#if (OVR_MAJOR_VERSION == 6) -#define ovr_Create ovrHmd_Create -#define ovr_CreateSwapTextureSetGL ovrHmd_CreateSwapTextureSetGL -#define ovr_CreateMirrorTextureGL ovrHmd_CreateMirrorTextureGL -#define ovr_Destroy ovrHmd_Destroy -#define ovr_DestroySwapTextureSet ovrHmd_DestroySwapTextureSet -#define ovr_DestroyMirrorTexture ovrHmd_DestroyMirrorTexture -#define ovr_GetFloat ovrHmd_GetFloat -#define ovr_GetFovTextureSize ovrHmd_GetFovTextureSize -#define ovr_GetFrameTiming ovrHmd_GetFrameTiming -#define ovr_GetTrackingState ovrHmd_GetTrackingState -#define ovr_GetRenderDesc ovrHmd_GetRenderDesc -#define ovr_RecenterPose ovrHmd_RecenterPose -#define ovr_SubmitFrame ovrHmd_SubmitFrame -#define ovr_ConfigureTracking ovrHmd_ConfigureTracking - -#define ovr_GetHmdDesc(X) *X -#endif - #if (OVR_MAJOR_VERSION >= 6) // A base class for FBO wrappers that need to use the Oculus C @@ -180,160 +131,21 @@ private: const QString OculusDisplayPlugin::NAME("Oculus Rift"); -uvec2 OculusDisplayPlugin::getRecommendedRenderSize() const { - return _desiredFramebufferSize; -} - -void OculusDisplayPlugin::preRender() { -#if (OVR_MAJOR_VERSION >= 6) - ovrFrameTiming ftiming = ovr_GetFrameTiming(_hmd, _frameIndex); - _trackingState = ovr_GetTrackingState(_hmd, ftiming.DisplayMidpointSeconds); - ovr_CalcEyePoses(_trackingState.HeadPose.ThePose, _eyeOffsets, _eyePoses); -#endif -} - -glm::mat4 OculusDisplayPlugin::getProjection(Eye eye, const glm::mat4& baseProjection) const { - return _eyeProjections[eye]; -} - -void OculusDisplayPlugin::resetSensors() { -#if (OVR_MAJOR_VERSION >= 6) - ovr_RecenterPose(_hmd); -#endif -} - -glm::mat4 OculusDisplayPlugin::getEyePose(Eye eye) const { - return toGlm(_eyePoses[eye]); -} - -glm::mat4 OculusDisplayPlugin::getHeadPose() const { - return toGlm(_trackingState.HeadPose.ThePose); -} - const QString & OculusDisplayPlugin::getName() const { return NAME; } -bool OculusDisplayPlugin::isSupported() const { -#if (OVR_MAJOR_VERSION >= 6) - if (!OVR_SUCCESS(ovr_Initialize(nullptr))) { - return false; - } - bool result = false; - if (ovrHmd_Detect() > 0) { - result = true; - } - ovr_Shutdown(); - return result; -#else - return false; -#endif -} - -void OculusDisplayPlugin::init() { - if (!OVR_SUCCESS(ovr_Initialize(nullptr))) { - qFatal("Could not init OVR"); - } -} - -void OculusDisplayPlugin::deinit() { - ovr_Shutdown(); -} - -#if (OVR_MAJOR_VERSION >= 6) -ovrLayerEyeFov& OculusDisplayPlugin::getSceneLayer() { - return _sceneLayer; -} -#endif - -//static gpu::TexturePointer _texture; - -void OculusDisplayPlugin::activate() { -#if (OVR_MAJOR_VERSION >= 6) - if (!OVR_SUCCESS(ovr_Initialize(nullptr))) { - Q_ASSERT(false); - qFatal("Failed to Initialize SDK"); - } - -// CONTAINER->getPrimarySurface()->makeCurrent(); -#if (OVR_MAJOR_VERSION == 6) - if (!OVR_SUCCESS(ovr_Create(0, &_hmd))) { -#elif (OVR_MAJOR_VERSION == 7) - if (!OVR_SUCCESS(ovr_Create(&_hmd, &_luid))) { -#endif - Q_ASSERT(false); - qFatal("Failed to acquire HMD"); - } - - _hmdDesc = ovr_GetHmdDesc(_hmd); - - _ipd = ovr_GetFloat(_hmd, OVR_KEY_IPD, _ipd); - - glm::uvec2 eyeSizes[2]; - ovr_for_each_eye([&](ovrEyeType eye) { - _eyeFovs[eye] = _hmdDesc.DefaultEyeFov[eye]; - ovrEyeRenderDesc& erd = _eyeRenderDescs[eye] = ovr_GetRenderDesc(_hmd, eye, _eyeFovs[eye]); - ovrMatrix4f ovrPerspectiveProjection = - ovrMatrix4f_Projection(erd.Fov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded); - _eyeProjections[eye] = toGlm(ovrPerspectiveProjection); - - ovrPerspectiveProjection = - ovrMatrix4f_Projection(erd.Fov, 0.001f, 10.0f, ovrProjection_RightHanded); - _compositeEyeProjections[eye] = toGlm(ovrPerspectiveProjection); - - _eyeOffsets[eye] = erd.HmdToEyeViewOffset; - eyeSizes[eye] = toGlm(ovr_GetFovTextureSize(_hmd, eye, erd.Fov, 1.0f)); - }); - ovrFovPort combined = _eyeFovs[Left]; - combined.LeftTan = std::max(_eyeFovs[Left].LeftTan, _eyeFovs[Right].LeftTan); - combined.RightTan = std::max(_eyeFovs[Left].RightTan, _eyeFovs[Right].RightTan); - ovrMatrix4f ovrPerspectiveProjection = - ovrMatrix4f_Projection(combined, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded); - _eyeProjections[Mono] = toGlm(ovrPerspectiveProjection); - - - - _desiredFramebufferSize = uvec2( - eyeSizes[0].x + eyeSizes[1].x, - std::max(eyeSizes[0].y, eyeSizes[1].y)); - - _frameIndex = 0; - - if (!OVR_SUCCESS(ovr_ConfigureTracking(_hmd, - ovrTrackingCap_Orientation | ovrTrackingCap_Position | ovrTrackingCap_MagYawCorrection, 0))) { - qFatal("Could not attach to sensor device"); - } - - WindowOpenGLDisplayPlugin::activate(); - - // Parent class relies on our _hmd intialization, so it must come after that. - ovrLayerEyeFov& sceneLayer = getSceneLayer(); - memset(&sceneLayer, 0, sizeof(ovrLayerEyeFov)); - sceneLayer.Header.Type = ovrLayerType_EyeFov; - sceneLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft; - ovr_for_each_eye([&](ovrEyeType eye) { - ovrFovPort & fov = sceneLayer.Fov[eye] = _eyeRenderDescs[eye].Fov; - ovrSizei & size = sceneLayer.Viewport[eye].Size = ovr_GetFovTextureSize(_hmd, eye, fov, 1.0f); - sceneLayer.Viewport[eye].Pos = { eye == ovrEye_Left ? 0 : size.w, 0 }; - }); - // We're rendering both eyes to the same texture, so only one of the - // pointers is populated - sceneLayer.ColorTexture[0] = _sceneFbo->color; - // not needed since the structure was zeroed on init, but explicit - sceneLayer.ColorTexture[1] = nullptr; - - if (!OVR_SUCCESS(ovr_ConfigureTracking(_hmd, - ovrTrackingCap_Orientation | ovrTrackingCap_Position | ovrTrackingCap_MagYawCorrection, 0))) { - qFatal("Could not attach to sensor device"); - } -#endif -} - void OculusDisplayPlugin::customizeContext() { WindowOpenGLDisplayPlugin::customizeContext(); #if (OVR_MAJOR_VERSION >= 6) _sceneFbo = SwapFboPtr(new SwapFramebufferWrapper(_hmd)); _sceneFbo->Init(getRecommendedRenderSize()); + + // We're rendering both eyes to the same texture, so only one of the + // pointers is populated + _sceneLayer.ColorTexture[0] = _sceneFbo->color; + // not needed since the structure was zeroed on init, but explicit + _sceneLayer.ColorTexture[1] = nullptr; #endif enableVsync(false); // Only enable mirroring if we know vsync is disabled @@ -345,13 +157,9 @@ void OculusDisplayPlugin::deactivate() { makeCurrent(); _sceneFbo.reset(); doneCurrent(); - - WindowOpenGLDisplayPlugin::deactivate(); - - ovr_Destroy(_hmd); - _hmd = nullptr; - ovr_Shutdown(); #endif + + OculusBaseDisplayPlugin::deactivate(); } void OculusDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSize) { @@ -379,9 +187,8 @@ void OculusDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSi drawUnitQuad(); }); - ovrLayerEyeFov& sceneLayer = getSceneLayer(); ovr_for_each_eye([&](ovrEyeType eye) { - sceneLayer.RenderPose[eye] = _eyePoses[eye]; + _sceneLayer.RenderPose[eye] = _eyePoses[eye]; }); auto windowSize = toGlm(_window->size()); @@ -391,7 +198,7 @@ void OculusDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSi viewScaleDesc.HmdToEyeViewOffset[0] = _eyeOffsets[0]; viewScaleDesc.HmdToEyeViewOffset[1] = _eyeOffsets[1]; - ovrLayerHeader* layers = &sceneLayer.Header; + ovrLayerHeader* layers = &_sceneLayer.Header; ovrResult result = ovr_SubmitFrame(_hmd, 0, &viewScaleDesc, &layers, 1); if (!OVR_SUCCESS(result)) { qDebug() << result; @@ -403,11 +210,6 @@ void OculusDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSi #endif } -// Pass input events on to the application -bool OculusDisplayPlugin::eventFilter(QObject* receiver, QEvent* event) { - return WindowOpenGLDisplayPlugin::eventFilter(receiver, event); -} - /* The swapbuffer call here is only required if we want to mirror the content to the screen. However, it should only be done if we can reliably disable v-sync on the mirror surface, @@ -419,36 +221,3 @@ void OculusDisplayPlugin::finishFrame() { } doneCurrent(); }; - - -#if 0 -/* -An alternative way to render the UI is to pass it specifically as a composition layer to -the Oculus SDK which should technically result in higher quality. However, the SDK doesn't -have a mechanism to present the image as a sphere section, which is our desired look. -*/ -ovrLayerQuad& uiLayer = getUiLayer(); -if (nullptr == uiLayer.ColorTexture || overlaySize != _uiFbo->size) { - _uiFbo->Resize(overlaySize); - uiLayer.ColorTexture = _uiFbo->color; - uiLayer.Viewport.Size.w = overlaySize.x; - uiLayer.Viewport.Size.h = overlaySize.y; - float overlayAspect = aspect(overlaySize); - uiLayer.QuadSize.x = 1.0f; - uiLayer.QuadSize.y = 1.0f / overlayAspect; -} - -_uiFbo->Bound([&] { - Q_ASSERT(0 == glGetError()); - using namespace oglplus; - Context::Viewport(_uiFbo->size.x, _uiFbo->size.y); - glClearColor(0, 0, 0, 0); - Context::Clear().ColorBuffer(); - - _program->Bind(); - glBindTexture(GL_TEXTURE_2D, overlayTexture); - _plane->Use(); - _plane->Draw(); - Q_ASSERT(0 == glGetError()); -}); -#endif diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/oculus/OculusDisplayPlugin.h index d30356daa0..7db83884cd 100644 --- a/libraries/display-plugins/src/display-plugins/oculus/OculusDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusDisplayPlugin.h @@ -7,43 +7,17 @@ // #pragma once -#include "../WindowOpenGLDisplayPlugin.h" +#include "OculusBaseDisplayPlugin.h" -#include - -#include - -class OffscreenGlCanvas; struct SwapFramebufferWrapper; -struct MirrorFramebufferWrapper; - using SwapFboPtr = QSharedPointer; -using MirrorFboPtr = QSharedPointer; -class OculusDisplayPlugin : public WindowOpenGLDisplayPlugin { +class OculusDisplayPlugin : public OculusBaseDisplayPlugin { public: - virtual bool isSupported() const override; + virtual void deactivate() override; virtual const QString & getName() const override; - virtual void init() override; - virtual void deinit() override; - - virtual void activate() override; - virtual void deactivate() override; - - virtual bool eventFilter(QObject* receiver, QEvent* event) override; - - // Stereo specific methods - virtual bool isHmd() const override { return true; } - virtual glm::mat4 getProjection(Eye eye, const glm::mat4& baseProjection) const override; - virtual glm::uvec2 getRecommendedRenderSize() const override; - virtual glm::uvec2 getRecommendedUiSize() const override { return uvec2(1920, 1080); } - virtual void resetSensors() override; - virtual glm::mat4 getEyePose(Eye eye) const override; - virtual glm::mat4 getHeadPose() const override; - protected: - virtual void preRender() override; virtual void display(GLuint finalTexture, const glm::uvec2& sceneSize) override; virtual void customizeContext() override; // Do not perform swap in finish @@ -51,30 +25,10 @@ protected: private: static const QString NAME; - - ovrPosef _eyePoses[2]; - - mat4 _eyeProjections[3]; - mat4 _compositeEyeProjections[2]; - uvec2 _desiredFramebufferSize; - ovrTrackingState _trackingState; bool _enableMirror{ false }; #if (OVR_MAJOR_VERSION >= 6) - ovrHmd _hmd; - float _ipd{ OVR_DEFAULT_IPD }; - unsigned int _frameIndex; - ovrEyeRenderDesc _eyeRenderDescs[2]; - ovrVector3f _eyeOffsets[2]; - ovrFovPort _eyeFovs[2]; - - ovrLayerEyeFov& getSceneLayer(); - ovrHmdDesc _hmdDesc; SwapFboPtr _sceneFbo; - ovrLayerEyeFov _sceneLayer; -#endif -#if (OVR_MAJOR_VERSION == 7) - ovrGraphicsLuid _luid; #endif };