diff --git a/Engine/source/gui/3d/guiTSControl.cpp b/Engine/source/gui/3d/guiTSControl.cpp index 1b7f9f556..1a8046dd2 100644 --- a/Engine/source/gui/3d/guiTSControl.cpp +++ b/Engine/source/gui/3d/guiTSControl.cpp @@ -538,6 +538,47 @@ void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect) return; } + // jamesu - currently a little bit of a hack. Ideally we need to ditch the viewports in the query data and just rely on the display device + if (mLastCameraQuery.displayDevice) + { + if (mRenderStyle == RenderStyleStereoSideBySide) + { + mLastCameraQuery.displayDevice->setDrawMode(GFXDevice::RS_StereoSideBySide); + } + else if (mRenderStyle == RenderStyleStereoSeparate) + { + mLastCameraQuery.displayDevice->setDrawMode(GFXDevice::RS_StereoSeparate); + } + else + { + mLastCameraQuery.displayDevice->setDrawMode(GFXDevice::RS_Standard); + } + + // The connection's display device may want to set the projection offset + if (mLastCameraQuery.displayDevice->providesProjectionOffset()) + { + mLastCameraQuery.projectionOffset = mLastCameraQuery.displayDevice->getProjectionOffset(); + } + + // The connection's display device may want to set the eye offset + if (mLastCameraQuery.displayDevice->providesEyeOffsets()) + { + mLastCameraQuery.displayDevice->getEyeOffsets(mLastCameraQuery.eyeOffset); + } + + // Grab field of view for both eyes + if (mLastCameraQuery.displayDevice->providesFovPorts()) + { + mLastCameraQuery.displayDevice->getFovPorts(mLastCameraQuery.fovPort); + mLastCameraQuery.hasFovPort = true; + } + + mLastCameraQuery.displayDevice->getStereoViewports(mLastCameraQuery.stereoViewports); + mLastCameraQuery.displayDevice->getStereoTargets(mLastCameraQuery.stereoTargets); + + mLastCameraQuery.hasStereoTargets = mLastCameraQuery.stereoTargets[0]; + } + GFXTargetRef origTarget = GFX->getActiveRenderTarget(); U32 origStyle = GFX->getCurrentRenderStyle(); @@ -612,6 +653,9 @@ void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect) GFX->activateStereoTarget(-1); _internalRender(RectI(updateRect.point, updateRect.extent), frustum); + + // Notify device we've rendered the right, thus the last stereo frame. + GFX->getDeviceEventSignal().trigger(GFXDevice::deRightStereoFrameRendered); // Render preview if (mLastCameraQuery.displayDevice) @@ -626,7 +670,7 @@ void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect) } } } - else if (mRenderStyle == RenderStyleStereoSeparate && mLastCameraQuery.stereoTargets[0]) + else if (mRenderStyle == RenderStyleStereoSeparate && mLastCameraQuery.displayDevice) { // In this case we render the scene twice to different render targets, then // render the final composite view @@ -699,7 +743,6 @@ void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect) Point2I screensize = getRoot()->getWindowSize(); tempRect.point.y = screensize.y - (tempRect.point.y + tempRect.extent.y); #endif - GFX->setCurrentRenderStyle(GFXDevice::RS_Standard); // set up the camera and viewport stuff: F32 wwidth; diff --git a/Engine/source/platform/input/openVR/openVROverlay.cpp b/Engine/source/platform/input/openVR/openVROverlay.cpp new file mode 100644 index 000000000..d22abbd51 --- /dev/null +++ b/Engine/source/platform/input/openVR/openVROverlay.cpp @@ -0,0 +1,161 @@ +#include "platform/input/openVR/openVROverlay.h" + +ImplementEnumType(OpenVROverlayType, + "Desired overlay type for OpenVROverlay. .\n\n" + "@ingroup OpenVR") +{ OpenVROverlay::OVERLAYTYPE_OVERLAY, "Overlay" }, +{ OpenVROverlay::OVERLAYTYPE_DASHBOARD, "Dashboard" }, +EndImplementEnumType; + +OpenVROverlay::OpenVROverlay() +{ + +} + +OpenVROverlay::~OpenVROverlay() +{ + +} + +void OpenVROverlay::initPersistFields() +{ + Parent::initPersistFields(); +} + +bool OpenVROverlay::onAdd() +{ + if (Parent::onAdd()) + { + mOverlayTypeDirty = true; + mOverlayDirty = true; + return true; + } + + return false; +} + +void OpenVROverlay::onRemove() +{ + if (mOverlayHandle) + { + vr::VROverlay()->DestroyOverlay(mOverlayHandle); + mOverlayHandle = NULL; + } +} + +void OpenVROverlay::resetOverlay() +{ + mOverlayTypeDirty = false; +} + +void OpenVROverlay::updateOverlay() +{ + if (mOverlayTypeDirty) + resetOverlay(); + + // Update params TODO + mOverlayDirty = false; +} + +void OpenVROverlay::showOverlay() +{ + if (mOverlayHandle == NULL) + return; + + vr::VROverlay()->ShowOverlay(mOverlayHandle); +} + +void OpenVROverlay::hideOverlay() +{ + if (mOverlayHandle == NULL) + return; + + vr::VROverlay()->HideOverlay(mOverlayHandle); +} + + +bool OpenVROverlay::isOverlayVisible() +{ + if (mOverlayHandle == NULL) + return false; + + return vr::VROverlay()->IsOverlayVisible(mOverlayHandle); +} + +bool OpenVROverlay::isOverlayHoverTarget() +{ + if (mOverlayHandle == NULL) + return false; + + return vr::VROverlay()->IsHoverTargetOverlay(mOverlayHandle); +} + + +bool OpenVROverlay::isGamepadFocussed() +{ + if (mOverlayHandle == NULL) + return false; + + return vr::VROverlay()->GetGamepadFocusOverlay() == mOverlayHandle; +} + +bool OpenVROverlay::isActiveDashboardOverlay() +{ + return false; // TODO WHERE DID I GET THIS FROM +} + +MatrixF OpenVROverlay::getTransformForOverlayCoordinates(const vr::ETrackingUniverseOrigin trackingOrigin, const Point2F &pos) +{ + if (mOverlayHandle == NULL) + return MatrixF::Identity; + + vr::HmdVector2_t vec; + vec.v[0] = pos.x; + vec.v[1] = pos.y; + vr::HmdMatrix34_t outMat; + MatrixF outTorqueMat; + if (vr::VROverlay()->GetTransformForOverlayCoordinates(mOverlayHandle, trackingOrigin, vec, &outMat) != vr::VROverlayError_None) + return MatrixF::Identity; + + MatrixF vrMat(1); + vrMat = OpenVRUtil::convertSteamVRAffineMatrixToMatrixFPlain(outMat); + OpenVRUtil::convertTransformFromOVR(vrMat, outTorqueMat); + return outTorqueMat; +} + +bool OpenVROverlay::castRay(const vr::ETrackingUniverseOrigin trackingOrigin, const Point3F &origin, const Point3F &direction, RayInfo *info) +{ + if (mOverlayHandle == NULL) + return false; + + vr::VROverlayIntersectionParams_t params; + vr::VROverlayIntersectionResults_t result; + + params.eOrigin = trackingOrigin; + params.vSource.v[0] = origin.x; + params.vSource.v[1] = origin.y; + params.vSource.v[2] = origin.z; + params.vDirection.v[0] = direction.x; // TODO: need to transform this to vr-space + params.vDirection.v[1] = direction.y; + params.vDirection.v[2] = direction.z; + + bool rayHit = vr::VROverlay()->ComputeOverlayIntersection(mOverlayHandle, ¶ms, &result); + + if (rayHit && info) + { + info->t = result.fDistance; + info->point = Point3F(result.vPoint.v[0], result.vPoint.v[1], result.vPoint.v[2]); // TODO: need to transform this FROM vr-space + info->normal = Point3F(result.vNormal.v[0], result.vNormal.v[1], result.vNormal.v[2]); + info->texCoord = Point2F(result.vUVs.v[0], result.vUVs.v[1]); + info->object = NULL; + info->userData = this; + } + + return rayHit; +} + +void OpenVROverlay::moveGamepadFocusToNeighbour() +{ + +} + diff --git a/Engine/source/platform/input/openVR/openVROverlay.h b/Engine/source/platform/input/openVR/openVROverlay.h new file mode 100644 index 000000000..8a5a82f17 --- /dev/null +++ b/Engine/source/platform/input/openVR/openVROverlay.h @@ -0,0 +1,89 @@ +#ifndef _OPENVROVERLAY_H_ +#define _OPENVROVERLAY_H_ + +#ifndef _GUIOFFSCREENCANVAS_H_ +#include "gui/core/guiOffscreenCanvas.h" +#endif +#ifndef _OPENVRDEVICE_H_ +#include "platform/input/openVR/openVRProvider.h" +#endif +#ifndef _COLLISION_H_ +#include "collision/collision.h" +#endif + + +typedef vr::VROverlayInputMethod OpenVROverlayInputMethod; +typedef vr::VROverlayTransformType OpenVROverlayTransformType; +typedef vr::EGamepadTextInputMode OpenVRGamepadTextInputMode; +typedef vr::EGamepadTextInputLineMode OpenVRGamepadTextInputLineMode; +typedef vr::ETrackingResult OpenVRTrackingResult; +typedef vr::ETrackingUniverseOrigin OpenVRTrackingUniverseOrigin; +typedef vr::EOverlayDirection OpenVROverlayDirection; +typedef vr::EVRState OpenVRState; + +class OpenVROverlay : public GuiOffscreenCanvas +{ +public: + typedef GuiOffscreenCanvas Parent; + + enum OverlayType + { + OVERLAYTYPE_OVERLAY, + OVERLAYTYPE_DASHBOARD, + }; + + vr::VROverlayHandle_t mOverlayHandle; + + // Desired OpenVR state + U32 mOverlayFlags; + F32 mOverlayWidth; + + vr::VROverlayTransformType mOverlayTransformType; + MatrixF mTransform; + vr::TrackedDeviceIndex_t mTransformDeviceIndex; + const char* mTransformDeviceComponent; + + + vr::VROverlayInputMethod mInputMethod; + Point2F mMouseScale; + + MatrixF mTrackingOrigin; + vr::TrackedDeviceIndex_t mControllerDeviceIndex; + + bool mOverlayTypeDirty; ///< Overlay type is dirty + bool mOverlayDirty; ///< Overlay properties are dirty + OverlayType mOverlayType; + + // + + OpenVROverlay(); + virtual ~OpenVROverlay(); + + static void initPersistFields(); + + bool onAdd(); + void onRemove(); + + void resetOverlay(); + void updateOverlay(); + + void showOverlay(); + void hideOverlay(); + + bool isOverlayVisible(); + bool isOverlayHoverTarget(); + + bool isGamepadFocussed(); + bool isActiveDashboardOverlay(); + + MatrixF getTransformForOverlayCoordinates(const vr::ETrackingUniverseOrigin trackingOrigin, const Point2F &pos); + bool castRay(const vr::ETrackingUniverseOrigin trackingOrigin, const Point3F &origin, const Point3F &direction, RayInfo *info); + + void moveGamepadFocusToNeighbour(); +}; + +typedef OpenVROverlay::OverlayType OpenVROverlayType; +DefineEnumType(OpenVROverlayType); + + +#endif diff --git a/Engine/source/platform/input/openVR/openVRProvider.cpp b/Engine/source/platform/input/openVR/openVRProvider.cpp index 4ef916bcf..2f8524221 100644 --- a/Engine/source/platform/input/openVR/openVRProvider.cpp +++ b/Engine/source/platform/input/openVR/openVRProvider.cpp @@ -16,17 +16,21 @@ #include "gfx/D3D9/gfxD3D9TextureObject.h" #include "gfx/D3D9/gfxD3D9EnumTranslate.h" -/* +#ifdef TORQUE_OPENGL #include "gfx/gl/gfxGLDevice.h" #include "gfx/gl/gfxGLTextureObject.h" #include "gfx/gl/gfxGLEnumTranslate.h" -*/ +#endif namespace OpenVRUtil { - /// Convert an OVR sensor's rotation to a Torque 3D matrix - void convertRotation(const F32 inRotMat[4][4], MatrixF& outRotation) - { + void convertTransformFromOVR(const MatrixF &inRotTMat, MatrixF& outRotation) + { + Point4F col0; inRotTMat.getColumn(0, &col0); + Point4F col1; inRotTMat.getColumn(1, &col1); + Point4F col2; inRotTMat.getColumn(2, &col2); + Point4F col3; inRotTMat.getColumn(3, &col3); + // Set rotation. We need to convert from sensor coordinates to // Torque coordinates. The sensor matrix is stored row-major. // The conversion is: @@ -35,15 +39,158 @@ namespace OpenVRUtil // a b c a b c a -c b // d e f --> -g -h -i --> -g i -h // g h i d e f d -f e - outRotation.setColumn(0, Point4F( inRotMat[0][0], -inRotMat[2][0], inRotMat[1][0], 0.0f)); - outRotation.setColumn(1, Point4F(-inRotMat[0][2], inRotMat[2][2], -inRotMat[1][2], 0.0f)); - outRotation.setColumn(2, Point4F( inRotMat[0][1], -inRotMat[2][1], inRotMat[1][1], 0.0f)); - outRotation.setPosition(Point3F::Zero); + outRotation.setColumn(0, Point4F( col0.x, -col2.x, col1.x, 0.0f)); + outRotation.setColumn(1, Point4F(-col0.z, col2.z, -col1.z, 0.0f)); + outRotation.setColumn(2, Point4F( col0.y, -col2.y, col1.y, 0.0f)); + outRotation.setColumn(3, Point4F(-col3.x, col3.z, -col3.y, 1.0f)); + } + + void convertTransformToOVR(const MatrixF& inRotation, MatrixF& outRotation) + { + Point4F col0; inRotation.getColumn(0, &col0); + Point4F col1; inRotation.getColumn(1, &col1); + Point4F col2; inRotation.getColumn(2, &col2); + Point4F col3; inRotation.getColumn(3, &col3); + + // This is basically a reverse of what is in convertTransformFromOVR + outRotation.setColumn(0, Point4F(col0.x, col2.x, -col1.x, 0.0f)); + outRotation.setColumn(1, Point4F(col0.z, col2.z, -col1.z, 0.0f)); + outRotation.setColumn(2, Point4F(-col0.y, -col2.y, col1.y, 0.0f)); + outRotation.setColumn(3, Point4F(-col3.x, -col3.z, col3.y, 1.0f)); + } + + MatrixF convertSteamVRAffineMatrixToMatrixFPlain(const vr::HmdMatrix34_t &mat) + { + MatrixF outMat(1); + + outMat.setColumn(0, Point4F(mat.m[0][0], mat.m[1][0], mat.m[2][0], 0.0)); + outMat.setColumn(1, Point4F(mat.m[0][1], mat.m[1][1], mat.m[2][1], 0.0)); + outMat.setColumn(2, Point4F(mat.m[0][2], mat.m[1][2], mat.m[2][2], 0.0)); + outMat.setColumn(3, Point4F(mat.m[0][3], mat.m[1][3], mat.m[2][3], 1.0f)); // pos + + return outMat; + } + + void convertMatrixFPlainToSteamVRAffineMatrix(const MatrixF &inMat, vr::HmdMatrix34_t &outMat) + { + Point4F row0; inMat.getRow(0, &row0); + Point4F row1; inMat.getRow(1, &row1); + Point4F row2; inMat.getRow(2, &row2); + + outMat.m[0][0] = row0.x; + outMat.m[0][1] = row0.y; + outMat.m[0][2] = row0.z; + outMat.m[0][3] = row0.w; + + outMat.m[1][0] = row1.x; + outMat.m[1][1] = row1.y; + outMat.m[1][2] = row1.z; + outMat.m[1][3] = row1.w; + + outMat.m[2][0] = row2.x; + outMat.m[2][1] = row2.y; + outMat.m[2][2] = row2.z; + outMat.m[2][3] = row2.w; + } + + + vr::VRTextureBounds_t TorqueRectToBounds(const RectI &rect, const Point2I &widthHeight) + { + vr::VRTextureBounds_t bounds; + F32 xRatio = 1.0 / (F32)widthHeight.x; + F32 yRatio = 1.0 / (F32)widthHeight.y; + bounds.uMin = rect.point.x * xRatio; + bounds.vMin = rect.point.y * yRatio; + bounds.uMax = (rect.point.x + rect.extent.x) * xRatio; + bounds.vMax = (rect.point.y + rect.extent.y) * yRatio; + return bounds; } } +//------------------------------------------------------------ + +DECLARE_SCOPE(OpenVR); +IMPLEMENT_SCOPE(OpenVR, OpenVRProvider, , ""); +ConsoleDoc( + "@class OpenVRProvider\n" + "@brief This class is the interface between TorqueScript and OpenVR.\n\n" + "@ingroup OpenVR\n" + ); + +// Enum impls + +ImplementEnumType(OpenVROverlayInputMethod, + "Types of input supported by VR Overlays. .\n\n" + "@ingroup OpenVR") +{ vr::VROverlayInputMethod_None, "None" }, +{ vr::VROverlayInputMethod_Mouse, "Mouse" }, +EndImplementEnumType; + +ImplementEnumType(OpenVROverlayTransformType, + "Allows the caller to figure out which overlay transform getter to call. .\n\n" + "@ingroup OpenVR") +{ vr::VROverlayTransform_Absolute, "Absolute" }, +{ vr::VROverlayTransform_TrackedDeviceRelative, "TrackedDeviceRelative" }, +{ vr::VROverlayTransform_SystemOverlay, "SystemOverlay" }, +{ vr::VROverlayTransform_TrackedComponent, "TrackedComponent" }, +EndImplementEnumType; + +ImplementEnumType(OpenVRGamepadTextInputMode, + "Types of input supported by VR Overlays. .\n\n" + "@ingroup OpenVR") +{ vr::k_EGamepadTextInputModeNormal, "Normal", }, +{ vr::k_EGamepadTextInputModePassword, "Password", }, +{ vr::k_EGamepadTextInputModeSubmit, "Submit" }, +EndImplementEnumType; + +ImplementEnumType(OpenVRGamepadTextInputLineMode, + "Types of input supported by VR Overlays. .\n\n" + "@ingroup OpenVR") +{ vr::k_EGamepadTextInputLineModeSingleLine, "SingleLine" }, +{ vr::k_EGamepadTextInputLineModeMultipleLines, "MultipleLines" }, +EndImplementEnumType; + +ImplementEnumType(OpenVRTrackingResult, + ". .\n\n" + "@ingroup OpenVR") +{ vr::TrackingResult_Uninitialized, "None" }, +{ vr::TrackingResult_Calibrating_InProgress, "Calibrating_InProgress" }, +{ vr::TrackingResult_Calibrating_OutOfRange, "Calibrating_OutOfRange" }, +{ vr::TrackingResult_Running_OK, "Running_Ok" }, +{ vr::TrackingResult_Running_OutOfRange, "Running_OutOfRange" }, +EndImplementEnumType; + +ImplementEnumType(OpenVRTrackingUniverseOrigin, + "Identifies which style of tracking origin the application wants to use for the poses it is requesting. .\n\n" + "@ingroup OpenVR") +{ vr::TrackingUniverseSeated, "Seated" }, +{ vr::TrackingUniverseStanding, "Standing" }, +{ vr::TrackingUniverseRawAndUncalibrated, "RawAndUncalibrated" }, +EndImplementEnumType; + +ImplementEnumType(OpenVROverlayDirection, + "Directions for changing focus between overlays with the gamepad. .\n\n" + "@ingroup OpenVR") +{ vr::OverlayDirection_Up, "Up" }, +{ vr::OverlayDirection_Down, "Down" }, +{ vr::OverlayDirection_Left, "Left" }, +{ vr::OverlayDirection_Right, "Right" }, +EndImplementEnumType; + +ImplementEnumType(OpenVRState, + "Status of the overall system or tracked objects. .\n\n" + "@ingroup OpenVR") +{ vr::VRState_Undefined, "Undefined" }, +{ vr::VRState_Off, "Off" }, +{ vr::VRState_Searching, "Searching" }, +{ vr::VRState_Searching_Alert, "Searching_Alert" }, +{ vr::VRState_Ready, "Ready" }, +{ vr::VRState_Ready_Alert, "Ready_Alert" }, +{ vr::VRState_NotReady, "NotReady" }, +EndImplementEnumType; + //------------------------------------------------------------ U32 OpenVRProvider::OVR_SENSORROT[vr::k_unMaxTrackedDeviceCount] = { 0 }; @@ -74,18 +221,6 @@ static String GetTrackedDeviceString(vr::IVRSystem *pHmd, vr::TrackedDeviceIndex return sResult; } -static MatrixF ConvertSteamVRAffineMatrixToMatrixFPlain(const vr::HmdMatrix34_t &mat) -{ - MatrixF outMat(1); - - outMat.setColumn(0, Point4F(mat.m[0][0], mat.m[1][0], mat.m[2][0], 0.0)); - outMat.setColumn(1, Point4F(mat.m[0][1], mat.m[1][1], mat.m[2][1], 0.0)); - outMat.setColumn(2, Point4F(mat.m[0][2], mat.m[1][2], mat.m[2][2], 0.0)); - outMat.setColumn(3, Point4F(mat.m[0][3], mat.m[1][3], mat.m[2][3], 1.0f)); // pos - - return outMat; -} - MODULE_BEGIN(OpenVRProvider) MODULE_INIT_AFTER(InputEventManager) @@ -105,184 +240,60 @@ MODULE_SHUTDOWN MODULE_END; -bool OpenVRRenderState::setupRenderTargets(U32 mode) +bool OpenVRRenderState::setupRenderTargets(GFXDevice::GFXDeviceRenderStyles mode) { if (!mHMD) return false; + if (mRenderMode == mode) + return true; + + mRenderMode = mode; + + if (mode == GFXDevice::RS_Standard) + { + reset(mHMD); + return true; + } + U32 sizeX, sizeY; Point2I newRTSize; mHMD->GetRecommendedRenderTargetSize(&sizeX, &sizeY); - mEyeViewport[0] = RectI(Point2I(0, 0), Point2I(sizeX, sizeY)); - mEyeViewport[1] = RectI(Point2I(0, 0), Point2I(sizeX, sizeY)); + if (mode == GFXDevice::RS_StereoSeparate) + { + mEyeViewport[0] = RectI(Point2I(0, 0), Point2I(sizeX, sizeY)); + mEyeViewport[1] = RectI(Point2I(0, 0), Point2I(sizeX, sizeY)); - newRTSize.x = sizeX; - newRTSize.y = sizeY; + newRTSize.x = sizeX; + newRTSize.y = sizeY; + } + else + { + mEyeViewport[0] = RectI(Point2I(0, 0), Point2I(sizeX, sizeY)); + mEyeViewport[1] = RectI(Point2I(sizeX, 0), Point2I(sizeX, sizeY)); + + newRTSize.x = sizeX * 2; + newRTSize.y = sizeY; + } GFXTexHandle stereoTexture; stereoTexture.set(newRTSize.x, newRTSize.y, GFXFormatR8G8B8A8, &VRTextureProfile, "OpenVR Stereo RT Color"); - mStereoRenderTextures[0] = mStereoRenderTextures[1] = stereoTexture; + mStereoRenderTexture = stereoTexture; GFXTexHandle stereoDepthTexture; stereoDepthTexture.set(newRTSize.x, newRTSize.y, GFXFormatD24S8, &VRDepthProfile, "OpenVR Depth"); - mStereoDepthTextures[0] = mStereoDepthTextures[1] = stereoDepthTexture; + mStereoDepthTexture = stereoDepthTexture; mStereoRT = GFX->allocRenderToTextureTarget(); mStereoRT->attachTexture(GFXTextureTarget::Color0, stereoTexture); mStereoRT->attachTexture(GFXTextureTarget::DepthStencil, stereoDepthTexture); - mEyeRT[0] = mEyeRT[1] = mStereoRT; - - mOutputEyeTextures[0].init(newRTSize.x, newRTSize.y, GFXFormatR8G8B8A8, &VRTextureProfile, "OpenVR Stereo RT Color OUTPUT"); - mOutputEyeTextures[1].init(newRTSize.x, newRTSize.y, GFXFormatR8G8B8A8, &VRTextureProfile, "OpenVR Stereo RT Color OUTPUT"); + mOutputEyeTextures.init(newRTSize.x, newRTSize.y, GFXFormatR8G8B8A8, &VRTextureProfile, "OpenVR Stereo RT Color OUTPUT"); return true; } -void OpenVRRenderState::setupDistortion() -{ - if (!mHMD) - return; - - U16 m_iLensGridSegmentCountH = 43; - U16 m_iLensGridSegmentCountV = 43; - - float w = (float)(1.0 / float(m_iLensGridSegmentCountH - 1)); - float h = (float)(1.0 / float(m_iLensGridSegmentCountV - 1)); - - float u, v = 0; - - Vector vVerts(0); - GFXVertexPTTT *vert; - - vVerts.reserve((m_iLensGridSegmentCountV * m_iLensGridSegmentCountH) * 2); - - mDistortionVerts.set(GFX, (m_iLensGridSegmentCountV * m_iLensGridSegmentCountH) * 2, GFXBufferTypeStatic); - - vert = mDistortionVerts.lock(); - - //left eye distortion verts - float Xoffset = -1; - for (int y = 0; y < m_iLensGridSegmentCountV; y++) - { - for (int x = 0; x < m_iLensGridSegmentCountH; x++) - { - u = x*w; v = 1 - y*h; - vert->point = Point3F(Xoffset + u, -1 + 2 * y*h, 0.0f); - - vr::DistortionCoordinates_t dc0 = mHMD->ComputeDistortion(vr::Eye_Left, u, v); - - vert->texCoord1 = Point2F(dc0.rfRed[0], 1 - dc0.rfRed[1]); // r - vert->texCoord2 = Point2F(dc0.rfGreen[0], 1 - dc0.rfGreen[1]); // g - vert->texCoord3 = Point2F(dc0.rfBlue[0], 1 - dc0.rfBlue[1]); // b - - vert++; - } - } - - //right eye distortion verts - Xoffset = 0; - for (int y = 0; y < m_iLensGridSegmentCountV; y++) - { - for (int x = 0; x < m_iLensGridSegmentCountH; x++) - { - u = x*w; v = 1 - y*h; - vert->point = Point3F(Xoffset + u, -1 + 2 * y*h, 0.0f); - - vr::DistortionCoordinates_t dc0 = mHMD->ComputeDistortion(vr::Eye_Right, u, v); - - vert->texCoord1 = Point2F(dc0.rfRed[0], 1 - dc0.rfRed[1]); - vert->texCoord2 = Point2F(dc0.rfGreen[0], 1 - dc0.rfGreen[1]); - vert->texCoord3 = Point2F(dc0.rfBlue[0], 1 - dc0.rfBlue[1]); - - vert++; - } - } - - mDistortionVerts.unlock(); - - mDistortionInds.set(GFX, m_iLensGridSegmentCountV * m_iLensGridSegmentCountH * 6 * 2, 0, GFXBufferTypeStatic); - - GFXPrimitive *prim; - U16 *index; - - mDistortionInds.lock(&index, &prim); - U16 a, b, c, d; - - U16 offset = 0; - for (U16 y = 0; y < m_iLensGridSegmentCountV - 1; y++) - { - for (U16 x = 0; x < m_iLensGridSegmentCountH - 1; x++) - { - a = m_iLensGridSegmentCountH*y + x + offset; - b = m_iLensGridSegmentCountH*y + x + 1 + offset; - c = (y + 1)*m_iLensGridSegmentCountH + x + 1 + offset; - d = (y + 1)*m_iLensGridSegmentCountH + x + offset; - *index++ = a; - *index++ = b; - *index++ = c; - - *index++ = a; - *index++ = c; - *index++ = d; - } - } - - offset = (m_iLensGridSegmentCountH)*(m_iLensGridSegmentCountV); - for (U16 y = 0; y < m_iLensGridSegmentCountV - 1; y++) - { - for (U16 x = 0; x < m_iLensGridSegmentCountH - 1; x++) - { - a = m_iLensGridSegmentCountH*y + x + offset; - b = m_iLensGridSegmentCountH*y + x + 1 + offset; - c = (y + 1)*m_iLensGridSegmentCountH + x + 1 + offset; - d = (y + 1)*m_iLensGridSegmentCountH + x + offset; - *index++ = a; - *index++ = b; - *index++ = c; - - *index++ = a; - *index++ = c; - *index++ = d; - } - } - - mDistortionInds.unlock(); -} - -void OpenVRRenderState::renderDistortion(U32 eye) -{ - // Updates distortion for an eye (this should only be the case for backend APIS where image should be predistorted) - /* - - glDisable(GL_DEPTH_TEST); - glViewport( 0, 0, m_nWindowWidth, m_nWindowHeight ); - - glBindVertexArray( m_unLensVAO ); - glUseProgram( m_unLensProgramID ); - - //render left lens (first half of index array ) - glBindTexture(GL_TEXTURE_2D, leftEyeDesc.m_nResolveTextureId ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); - glDrawElements( GL_TRIANGLES, m_uiIndexSize/2, GL_UNSIGNED_SHORT, 0 ); - - //render right lens (second half of index array ) - glBindTexture(GL_TEXTURE_2D, rightEyeDesc.m_nResolveTextureId ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); - glDrawElements( GL_TRIANGLES, m_uiIndexSize/2, GL_UNSIGNED_SHORT, (const void *)(m_uiIndexSize) ); - - glBindVertexArray( 0 ); - glUseProgram( 0 ); - */ -} - void OpenVRRenderState::renderPreview() { @@ -293,26 +304,21 @@ void OpenVRRenderState::reset(vr::IVRSystem* hmd) mHMD = hmd; mStereoRT = NULL; - mEyeRT[0] = mEyeRT[1] = NULL; - mStereoRenderTextures[0] = mStereoRenderTextures[1] = NULL; - mStereoDepthTextures[0] = mStereoDepthTextures[1] = NULL; + mStereoRenderTexture = NULL; + mStereoDepthTexture = NULL; - mDistortionVerts = NULL; - mDistortionInds = NULL; - - mOutputEyeTextures[0].clear(); - mOutputEyeTextures[1].clear(); + mOutputEyeTextures.clear(); if (!mHMD) return; vr::HmdMatrix34_t mat = mHMD->GetEyeToHeadTransform(vr::Eye_Left); - mEyePose[0] = ConvertSteamVRAffineMatrixToMatrixFPlain(mat); + mEyePose[0] = OpenVRUtil::convertSteamVRAffineMatrixToMatrixFPlain(mat); mEyePose[0].inverse(); mat = mHMD->GetEyeToHeadTransform(vr::Eye_Right); - mEyePose[1] = ConvertSteamVRAffineMatrixToMatrixFPlain(mat); + mEyePose[1] = OpenVRUtil::convertSteamVRAffineMatrixToMatrixFPlain(mat); mEyePose[1].inverse(); mHMD->GetProjectionRaw(vr::Eye_Left, &mEyeFov[0].leftTan, &mEyeFov[0].rightTan, &mEyeFov[0].upTan, &mEyeFov[0].downTan); @@ -336,6 +342,8 @@ OpenVRProvider::OpenVRProvider() : GFXDevice::getDeviceEventSignal().notify(this, &OpenVRProvider::_handleDeviceEvent); INPUTMGR->registerDevice(this); dMemset(&mLUID, '\0', sizeof(mLUID)); + + mTrackingSpace = vr::TrackingUniverseSeated; } OpenVRProvider::~OpenVRProvider() @@ -345,7 +353,16 @@ OpenVRProvider::~OpenVRProvider() void OpenVRProvider::staticInit() { - // TODO: Add console vars + // Overlay flags + Con::setIntVariable("$OpenVR::OverlayFlags_None", 1 << (U32)vr::VROverlayFlags_None); + Con::setIntVariable("$OpenVR::OverlayFlags_Curved", 1 << (U32)vr::VROverlayFlags_Curved); + Con::setIntVariable("$OpenVR::OverlayFlags_RGSS4X", 1 << (U32)vr::VROverlayFlags_RGSS4X); + Con::setIntVariable("$OpenVR::OverlayFlags_NoDashboardTab", 1 << (U32)vr::VROverlayFlags_NoDashboardTab); + Con::setIntVariable("$OpenVR::OverlayFlags_AcceptsGamepadEvents", 1 << (U32)vr::VROverlayFlags_AcceptsGamepadEvents); + Con::setIntVariable("$OpenVR::OverlayFlags_ShowGamepadFocus", 1 << (U32)vr::VROverlayFlags_ShowGamepadFocus); + Con::setIntVariable("$OpenVR::OverlayFlags_SendVRScrollEvents", 1 << (U32)vr::VROverlayFlags_SendVRScrollEvents); + Con::setIntVariable("$OpenVR::OverlayFlags_SendVRTouchpadEvents", 1 << (U32)vr::VROverlayFlags_SendVRTouchpadEvents); + Con::setIntVariable("$OpenVR::OverlayFlags_ShowTouchPadScrollWheel", 1 << (U32)vr::VROverlayFlags_ShowTouchPadScrollWheel); } bool OpenVRProvider::enable() @@ -558,34 +575,11 @@ void OpenVRTransformToRotPos(MatrixF mat, QuatF &outRot, Point3F &outPos) { // Directly set the rotation and position from the eye transforms MatrixF torqueMat(1); - - F32 inRotMat[4][4]; - Point4F col0; mat.getColumn(0, &col0); - Point4F col1; mat.getColumn(1, &col1); - Point4F col2; mat.getColumn(2, &col2); - Point4F col3; mat.getColumn(3, &col3); - inRotMat[0][0] = col0.x; - inRotMat[0][1] = col0.y; - inRotMat[0][2] = col0.z; - inRotMat[0][3] = col0.w; - inRotMat[1][0] = col1.x; - inRotMat[1][1] = col1.y; - inRotMat[1][2] = col1.z; - inRotMat[1][3] = col1.w; - inRotMat[2][0] = col2.x; - inRotMat[2][1] = col2.y; - inRotMat[2][2] = col2.z; - inRotMat[2][3] = col2.w; - inRotMat[3][0] = col3.x; - inRotMat[3][1] = col3.y; - inRotMat[3][2] = col3.z; - inRotMat[3][3] = col3.w; - - OpenVRUtil::convertRotation(inRotMat, torqueMat); + OpenVRUtil::convertTransformFromOVR(mat, torqueMat); Point3F pos = torqueMat.getPosition(); outRot = QuatF(torqueMat); - outPos = Point3F(-pos.x, pos.z, -pos.y); + outPos = pos;// Point3F(-pos.x, pos.z, -pos.y); } void OpenVRProvider::getFrameEyePose(IDevicePose *pose, U32 eye) const @@ -639,8 +633,8 @@ void OpenVRProvider::getStereoViewports(RectI *out) const void OpenVRProvider::getStereoTargets(GFXTextureTarget **out) const { - out[0] = mHMDRenderState.mEyeRT[0]; - out[1] = mHMDRenderState.mEyeRT[1]; + out[0] = mHMDRenderState.mStereoRT; + out[1] = mHMDRenderState.mStereoRT; } void OpenVRProvider::setDrawCanvas(GuiCanvas *canvas) @@ -655,11 +649,16 @@ void OpenVRProvider::setDrawCanvas(GuiCanvas *canvas) if (mDrawCanvas != canvas || mHMDRenderState.mHMD == NULL) { - mHMDRenderState.setupRenderTargets(0); + mHMDRenderState.setupRenderTargets(GFXDevice::RS_Standard); } mDrawCanvas = canvas; } +void OpenVRProvider::setDrawMode(GFXDevice::GFXDeviceRenderStyles style) +{ + mHMDRenderState.setupRenderTargets(style); +} + void OpenVRProvider::setCurrentConnection(GameConnection *connection) { mGameConnection = connection; @@ -672,7 +671,7 @@ GameConnection* OpenVRProvider::getCurrentConnection() GFXTexHandle OpenVRProvider::getPreviewTexture() { - return mHMDRenderState.mStereoRenderTextures[0]; // TODO: render distortion preview + return mHMDRenderState.mStereoRenderTexture; // TODO: render distortion preview } void OpenVRProvider::onStartFrame() @@ -694,31 +693,87 @@ void OpenVRProvider::onEyeRendered(U32 index) return; vr::EVRCompositorError err = vr::VRCompositorError_None; + vr::VRTextureBounds_t bounds; + U32 textureIdxToSubmit = index; - GFXTexHandle eyeTex = mHMDRenderState.mOutputEyeTextures[index].getTextureHandle(); - mHMDRenderState.mEyeRT[0]->resolveTo(eyeTex); - mHMDRenderState.mOutputEyeTextures[index].advance(); + GFXTexHandle eyeTex = mHMDRenderState.mOutputEyeTextures.getTextureHandle(); + if (mHMDRenderState.mRenderMode == GFXDevice::RS_StereoSeparate) + { + mHMDRenderState.mStereoRT->resolveTo(eyeTex); + mHMDRenderState.mOutputEyeTextures.advance(); + } + else + { + // assuming side-by-side, so the right eye will be next + if (index == 1) + { + mHMDRenderState.mStereoRT->resolveTo(eyeTex); + mHMDRenderState.mOutputEyeTextures.advance(); + } + else + { + return; + } + } if (GFX->getAdapterType() == Direct3D11) { - GFXFormat fmt1 = eyeTex->getFormat(); - vr::Texture_t eyeTexture = { (void*)static_cast(eyeTex.getPointer())->get2DTex(), vr::API_DirectX, vr::ColorSpace_Gamma }; - err = vr::VRCompositor()->Submit((vr::EVREye)(vr::Eye_Left + index), &eyeTexture); + vr::Texture_t eyeTexture; + if (mHMDRenderState.mRenderMode == GFXDevice::RS_StereoSeparate) + { + // whatever eye we are on + eyeTexture = { (void*)static_cast(eyeTex.getPointer())->get2DTex(), vr::API_DirectX, vr::ColorSpace_Gamma }; + bounds = OpenVRUtil::TorqueRectToBounds(mHMDRenderState.mEyeViewport[index], mHMDRenderState.mStereoRenderTexture.getWidthHeight()); + err = vr::VRCompositor()->Submit((vr::EVREye)(vr::Eye_Left + index), &eyeTexture, &bounds); + } + else + { + // left & right at the same time + eyeTexture = { (void*)static_cast(eyeTex.getPointer())->get2DTex(), vr::API_DirectX, vr::ColorSpace_Gamma }; + bounds = OpenVRUtil::TorqueRectToBounds(mHMDRenderState.mEyeViewport[0], mHMDRenderState.mStereoRenderTexture.getWidthHeight()); + err = vr::VRCompositor()->Submit((vr::EVREye)(vr::Eye_Left), &eyeTexture, &bounds); + bounds = OpenVRUtil::TorqueRectToBounds(mHMDRenderState.mEyeViewport[1], mHMDRenderState.mStereoRenderTexture.getWidthHeight()); + err = vr::VRCompositor()->Submit((vr::EVREye)(vr::Eye_Right), &eyeTexture, &bounds); + } } else if (GFX->getAdapterType() == Direct3D9) { //vr::Texture_t eyeTexture = { (void*)static_cast(mHMDRenderState.mStereoRenderTextures[index].getPointer())->get2DTex(), vr::API_DirectX, vr::ColorSpace_Gamma }; //err = vr::VRCompositor()->Submit((vr::EVREye)(vr::Eye_Left + index), &eyeTexture); } +#ifdef TORQUE_OPENGL else if (GFX->getAdapterType() == OpenGL) - {/* - vr::Texture_t eyeTexture = { (void*)static_cast(mHMDRenderState.mStereoRenderTextures[index].getPointer())->getHandle(), vr::API_OpenGL, vr::ColorSpace_Gamma }; - vr::VRCompositor()->Submit((vr::EVREye)(vr::Eye_Left + index), &eyeTexture);*/ + { + vr::Texture_t eyeTexture; + if (mHMDRenderState.mRenderMode == GFXDevice::RS_StereoSeparate) + { + // whatever eye we are on + eyeTexture = { (void*)static_cast(eyeTex.getPointer())->getHandle(), vr::API_OpenGL, vr::ColorSpace_Gamma }; + bounds = OpenVRUtil::TorqueRectToBounds(mHMDRenderState.mEyeViewport[index], mHMDRenderState.mStereoRenderTexture.getWidthHeight()); + err = vr::VRCompositor()->Submit((vr::EVREye)(vr::Eye_Left + index), &eyeTexture, &bounds); + } + else + { + // left & right at the same time + eyeTexture = { (void*)static_cast(eyeTex.getPointer())->getHandle(), vr::API_OpenGL, vr::ColorSpace_Gamma }; + bounds = OpenVRUtil::TorqueRectToBounds(mHMDRenderState.mEyeViewport[0], mHMDRenderState.mStereoRenderTexture.getWidthHeight()); + err = vr::VRCompositor()->Submit((vr::EVREye)(vr::Eye_Left), &eyeTexture, &bounds); + bounds = OpenVRUtil::TorqueRectToBounds(mHMDRenderState.mEyeViewport[1], mHMDRenderState.mStereoRenderTexture.getWidthHeight()); + err = vr::VRCompositor()->Submit((vr::EVREye)(vr::Eye_Right), &eyeTexture, &bounds); + } } +#endif AssertFatal(err == vr::VRCompositorError_None, "VR compositor error!"); } +void OpenVRProvider::setRoomTracking(bool room) +{ + vr::IVRCompositor* compositor = vr::VRCompositor(); + mTrackingSpace = room ? vr::TrackingUniverseStanding : vr::TrackingUniverseSeated; + if (compositor) compositor->SetTrackingSpace(mTrackingSpace); +} + bool OpenVRProvider::_handleDeviceEvent(GFXDevice::GFXDeviceEventType evt) { if (!ManagedSingleton::instanceOrNull()) @@ -770,9 +825,8 @@ bool OpenVRProvider::_handleDeviceEvent(GFXDevice::GFXDeviceEventType evt) S32 OpenVRProvider::getDisplayDeviceId() const { - return -1; -#ifdef TORQUE_OS_WIN32 - if (GFX->getAdapterType() == Direct3D11) +#if defined(TORQUE_OS_WIN64) || defined(TORQUE_OS_WIN32) + if (GFX && GFX->getAdapterType() == Direct3D11) { Vector adapterList; GFXD3D11Device::enumerateAdapters(adapterList); @@ -818,7 +872,17 @@ void OpenVRProvider::updateTrackedPoses() if (!mHMD) return; - vr::VRCompositor()->WaitGetPoses(mTrackedDevicePose, vr::k_unMaxTrackedDeviceCount, NULL, 0); + vr::IVRCompositor* compositor = vr::VRCompositor(); + + if (!compositor) + return; + + if (compositor->GetTrackingSpace() != mTrackingSpace) + { + compositor->SetTrackingSpace(mTrackingSpace); + } + + compositor->WaitGetPoses(mTrackedDevicePose, vr::k_unMaxTrackedDeviceCount, NULL, 0); mValidPoseCount = 0; @@ -828,7 +892,7 @@ void OpenVRProvider::updateTrackedPoses() if (mTrackedDevicePose[nDevice].bPoseIsValid) { mValidPoseCount++; - MatrixF mat = ConvertSteamVRAffineMatrixToMatrixFPlain(mTrackedDevicePose[nDevice].mDeviceToAbsoluteTracking); + MatrixF mat = OpenVRUtil::convertSteamVRAffineMatrixToMatrixFPlain(mTrackedDevicePose[nDevice].mDeviceToAbsoluteTracking); mat.inverse(); if (nDevice == vr::k_unTrackedDeviceIndex_Hmd) @@ -925,7 +989,43 @@ void OpenVRProvider::resetSensors() } } -DefineEngineFunction(isOpenVRDeviceActive, bool, (), , +OpenVROverlay *OpenVRProvider::getGamepadFocusOverlay() +{ + return NULL; +} + +void OpenVRProvider::setOverlayNeighbour(vr::EOverlayDirection dir, OpenVROverlay *overlay) +{ + +} + + +bool OpenVRProvider::isDashboardVisible() +{ + return false; +} + +void OpenVRProvider::showDashboard(const char *overlayToShow) +{ + +} + +vr::TrackedDeviceIndex_t OpenVRProvider::getPrimaryDashboardDevice() +{ + return -1; +} + +void OpenVRProvider::setKeyboardTransformAbsolute(const MatrixF &xfm) +{ + // mTrackingSpace +} + +void OpenVRProvider::setKeyboardPositionForOverlay(OpenVROverlay *overlay, const RectI &rect) +{ + +} + +DefineEngineStaticMethod(OpenVR, isDeviceActive, bool, (), , "@brief Used to determine if the OpenVR input device is active\n\n" "The OpenVR device is considered active when the library has been " @@ -940,11 +1040,11 @@ DefineEngineFunction(isOpenVRDeviceActive, bool, (), , return false; } - return OCULUSVRDEV->getActive(); + return OPENVR->getActive(); } -DefineEngineFunction(OpenVRSetEnabled, bool, (bool value), , +DefineEngineStaticMethod(OpenVR, setEnabled, bool, (bool value), , "@brief Used to determine if the OpenVR input device is active\n\n" "The OpenVR device is considered active when the library has been " @@ -959,12 +1059,11 @@ DefineEngineFunction(OpenVRSetEnabled, bool, (bool value), , return false; } - return value ? ManagedSingleton::instance()->enable() : ManagedSingleton::instance()->disable(); + return value ? OPENVR->enable() : OPENVR->disable(); } - -DefineEngineFunction(setOpenVRHMDAsGameConnectionDisplayDevice, bool, (GameConnection* conn), , +DefineEngineStaticMethod(OpenVR, setHMDAsGameConnectionDisplayDevice, bool, (GameConnection* conn), , "@brief Sets the first HMD to be a GameConnection's display device\n\n" "@param conn The GameConnection to set.\n" "@return True if the GameConnection display device was set.\n" @@ -982,12 +1081,12 @@ DefineEngineFunction(setOpenVRHMDAsGameConnectionDisplayDevice, bool, (GameConne return false; } - conn->setDisplayDevice(ManagedSingleton::instance()); + conn->setDisplayDevice(OPENVR); return true; } -DefineEngineFunction(OpenVRGetDisplayDeviceId, S32, (), , +DefineEngineStaticMethod(OpenVR, getDisplayDeviceId, S32, (), , "@brief MacOS display ID.\n\n" "@param index The HMD index.\n" "@return The ID of the HMD display device, if any.\n" @@ -998,10 +1097,10 @@ DefineEngineFunction(OpenVRGetDisplayDeviceId, S32, (), , return -1; } - return ManagedSingleton::instance()->getDisplayDeviceId(); + return OPENVR->getDisplayDeviceId(); } -DefineEngineFunction(OpenVRResetSensors, void, (), , +DefineEngineStaticMethod(OpenVR, resetSensors, void, (), , "@brief Resets all Oculus VR sensors.\n\n" "This resets all sensor orientations such that their 'normal' rotation " "is defined when this function is called. This defines an HMD's forwards " @@ -1013,5 +1112,7 @@ DefineEngineFunction(OpenVRResetSensors, void, (), , return; } - ManagedSingleton::instance()->resetSensors(); + OPENVR->resetSensors(); } + +// Overlay stuff diff --git a/Engine/source/platform/input/openVR/openVRProvider.h b/Engine/source/platform/input/openVR/openVRProvider.h index 206aa8799..94b43fb38 100644 --- a/Engine/source/platform/input/openVR/openVRProvider.h +++ b/Engine/source/platform/input/openVR/openVRProvider.h @@ -19,12 +19,39 @@ #include class OpenVRHMDDevice; +class OpenVROverlay; -class VRTextureSet +typedef vr::VROverlayInputMethod OpenVROverlayInputMethod; +typedef vr::VROverlayTransformType OpenVROverlayTransformType; +typedef vr::EGamepadTextInputMode OpenVRGamepadTextInputMode; +typedef vr::EGamepadTextInputLineMode OpenVRGamepadTextInputLineMode; +typedef vr::ETrackingResult OpenVRTrackingResult; +typedef vr::ETrackingUniverseOrigin OpenVRTrackingUniverseOrigin; +typedef vr::EOverlayDirection OpenVROverlayDirection; +typedef vr::EVRState OpenVRState; + +DefineEnumType(OpenVROverlayTransformType); + +namespace OpenVRUtil +{ + /// Convert a matrix in OVR space to torque space + void convertTransformFromOVR(const MatrixF &inRotTMat, MatrixF& outRotation); + + /// Convert a matrix in torque space to OVR space + void convertTransformToOVR(const MatrixF& inRotation, MatrixF& outRotation); + + /// Converts vr::HmdMatrix34_t to a MatrixF + MatrixF convertSteamVRAffineMatrixToMatrixFPlain(const vr::HmdMatrix34_t &mat); + + /// Converts a MatrixF to a vr::HmdMatrix34_t + void convertMatrixFPlainToSteamVRAffineMatrix(const MatrixF &inMat, vr::HmdMatrix34_t &outMat); +}; + +template class VRTextureSet { public: - static const int TextureCount = 2; - GFXTexHandle mTextures[2]; + static const int TextureCount = TEXSIZE; + GFXTexHandle mTextures[TEXSIZE]; U32 mIndex; VRTextureSet() : mIndex(0) @@ -68,20 +95,15 @@ struct OpenVRRenderState RectI mEyeViewport[2]; GFXTextureTargetRef mStereoRT; - GFXTextureTargetRef mEyeRT[2]; - GFXTexHandle mStereoRenderTextures[2]; - GFXTexHandle mStereoDepthTextures[2]; + GFXTexHandle mStereoRenderTexture; + GFXTexHandle mStereoDepthTexture; - GFXVertexBufferHandle mDistortionVerts; - GFXPrimitiveBufferHandle mDistortionInds; + VRTextureSet<4> mOutputEyeTextures; - VRTextureSet mOutputEyeTextures[2]; + GFXDevice::GFXDeviceRenderStyles mRenderMode; - bool setupRenderTargets(U32 mode); - void setupDistortion(); - - void renderDistortion(U32 eye); + bool setupRenderTargets(GFXDevice::GFXDeviceRenderStyles mode); void renderPreview(); @@ -142,6 +164,7 @@ public: virtual void getStereoTargets(GFXTextureTarget **out) const; virtual void setDrawCanvas(GuiCanvas *canvas); + virtual void setDrawMode(GFXDevice::GFXDeviceRenderStyles style); virtual void setCurrentConnection(GameConnection *connection); virtual GameConnection* getCurrentConnection(); @@ -153,6 +176,8 @@ public: virtual void onEyeRendered(U32 index); + virtual void setRoomTracking(bool room); + bool _handleDeviceEvent(GFXDevice::GFXDeviceEventType evt); S32 getDisplayDeviceId() const; @@ -168,6 +193,21 @@ public: void resetSensors(); /// } + + /// @name Console API + /// { + OpenVROverlay *getGamepadFocusOverlay(); + void setOverlayNeighbour(vr::EOverlayDirection dir, OpenVROverlay *overlay); + + bool isDashboardVisible(); + void showDashboard(const char *overlayToShow); + + vr::TrackedDeviceIndex_t getPrimaryDashboardDevice(); + + void setKeyboardTransformAbsolute(const MatrixF &xfm); + void setKeyboardPositionForOverlay(OpenVROverlay *overlay, const RectI &rect); + /// } + /// @name OpenVR state /// { vr::IVRSystem *mHMD; @@ -183,6 +223,8 @@ public: OpenVRRenderState mHMDRenderState; GFXAdapterLUID mLUID; + + vr::ETrackingUniverseOrigin mTrackingSpace; /// } GuiCanvas* mDrawCanvas; @@ -210,6 +252,6 @@ public: }; /// Returns the OculusVRDevice singleton. -#define OCULUSVRDEV ManagedSingleton::instance() +#define OPENVR ManagedSingleton::instance() #endif // _OCULUSVRDEVICE_H_ diff --git a/Engine/source/platform/output/IDisplayDevice.h b/Engine/source/platform/output/IDisplayDevice.h index bd372085d..9ce327a04 100644 --- a/Engine/source/platform/output/IDisplayDevice.h +++ b/Engine/source/platform/output/IDisplayDevice.h @@ -66,6 +66,7 @@ public: virtual void getStereoTargets(GFXTextureTarget **out) const = 0; virtual void setDrawCanvas(GuiCanvas *canvas) = 0; + virtual void setDrawMode(GFXDevice::GFXDeviceRenderStyles style) = 0; virtual void setCurrentConnection(GameConnection *connection) = 0; virtual GameConnection* getCurrentConnection() = 0;