From f30e86bc4b73215b207952ceca85607118f66849 Mon Sep 17 00:00:00 2001 From: jriegel Date: Wed, 16 Jul 2014 23:08:32 +0200 Subject: [PATCH 01/18] Integrating Rift Libs in build --- CMakeLists.txt | 2 + cMake/FindRift.cmake | 100 ++++++ src/Gui/CMakeLists.txt | 20 +- src/Gui/View3DInventorRiftViewer.cpp | 470 +++++++++++++++++++++++++++ 4 files changed, 590 insertions(+), 2 deletions(-) create mode 100644 cMake/FindRift.cmake create mode 100644 src/Gui/View3DInventorRiftViewer.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ca6a5c1a89a3..807709e18ee0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -628,6 +628,8 @@ else(FREECAD_LIBPACK_USE) endif(FREECAD_LIBPACK_USE) +find_package(Rift) + # copy build convenient files for M$ if(WIN32) if (EXISTS BuildAll.bat) diff --git a/cMake/FindRift.cmake b/cMake/FindRift.cmake new file mode 100644 index 000000000000..4a77de5759a7 --- /dev/null +++ b/cMake/FindRift.cmake @@ -0,0 +1,100 @@ +# Find OCULUS +# +# This module defines +# OCULUS_FOUND +# OCULUS_INCLUDE_DIRS +# OCULUS_LIBRARIES +# +# Copyright (c) 2012 I-maginer +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 59 Temple +# Place - Suite 330, Boston, MA 02111-1307, USA, or go to +# http://www.gnu.org/copyleft/lesser.txt +# + +# On a new cmake run, we do not need to be verbose +IF(OCULUS_INCLUDE_DIR AND OCULUS_LIBRARY) + SET(OCULUS_FIND_QUIETLY FALSE) +ENDIF() + +# If OCULUS_ROOT was defined in the environment, use it. +if (NOT OCULUS_ROOT) + if(NOT "$ENV{OCULUS_ROOT}" STREQUAL "") + set(OCULUS_ROOT $ENV{OCULUS_ROOT}) + else() + set(OCULUS_ROOT $ENV{SCOL_DEPENDENCIES_PATH}/oculus/LibOVR) + endif() +endif() + +# concat all the search paths +IF(OCULUS_ROOT) + SET(OCULUS_INCLUDE_SEARCH_DIRS + ${OCULUS_INCLUDE_SEARCH_DIRS} + ${OCULUS_ROOT}/include + ) + SET(OCULUS_LIBRARY_SEARCH_RELEASE_DIRS + ${OCULUS_LIBRARY_SEARCH_DIRS} + ${OCULUS_ROOT}/lib/Win32 + ) + SET(OCULUS_LIBRARY_SEARCH_DEBUG_DIRS + ${OCULUS_LIBRARY_SEARCH_DIRS} + ${OCULUS_ROOT}/lib/Win32 + ) +ENDIF() + +# log message +IF (NOT OCULUS_FIND_QUIETLY) + MESSAGE(STATUS "Checking for OCULUS library") +ENDIF() + +# Search for header files +FIND_PATH(OCULUS_INCLUDE_DIR OVR.h + PATHS ${OCULUS_INCLUDE_SEARCH_DIRS}) + +# Search for libraries files (release mode) +FIND_LIBRARY(OCULUS_LIBRARY_RELEASE libovr + PATHS ${OCULUS_LIBRARY_SEARCH_RELEASE_DIRS}) + +# Search for libraries files (debug mode) +FIND_LIBRARY(OCULUS_LIBRARY_DEBUG libovrd + PATHS ${OCULUS_LIBRARY_SEARCH_DEBUG_DIRS}) + +# Configure libraries for debug/release +SET(OCULUS_INCLUDE_DIRS ${OCULUS_INCLUDE_DIR} CACHE PATH "Directory containing OCULUS header files") +SET(OCULUS_LIBRARY debug ${OCULUS_LIBRARY_DEBUG} optimized ${OCULUS_LIBRARY_RELEASE}) +SET(OCULUS_LIBRARIES ${OCULUS_LIBRARY} CACHE STRING "OCULUS libraries files") + +#IF(OCULUS_INCLUDE_DIR AND OCULUS_LIBRARY) + SET(OCULUS_FOUND TRUE) +#ENDIF() + +# Hide those variables in GUI +SET(OCULUS_INCLUDE_DIR ${OCULUS_INCLUDE_DIR} CACHE INTERNAL "") +SET(OCULUS_LIBRARY_RELEASE ${OCULUS_LIBRARY_RELEASE} CACHE INTERNAL "") +SET(OCULUS_LIBRARY_DEBUG ${OCULUS_LIBRARY_DEBUG} CACHE INTERNAL "") +SET(OCULUS_LIBRARY ${OCULUS_LIBRARY} CACHE INTERNAL "") + +# log find result +IF(OCULUS_FOUND) + IF(NOT OCULUS_FIND_QUIETLY) + MESSAGE(STATUS " libraries: ${OCULUS_LIBRARIES}") + MESSAGE(STATUS " includes: ${OCULUS_INCLUDE_DIRS}") + ENDIF() +ELSE(OCULUS_FOUND) + IF(NOT OCULUS_LIBRARIES) + MESSAGE(STATUS, "OCULUS library or one of it dependencies could not be found.") + ENDIF() + IF(NOT OCULUS_INCLUDE_DIRS) + MESSAGE(STATUS "OCULUS include files could not be found.") + ENDIF() +ENDIF(OCULUS_FOUND) \ No newline at end of file diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index 3a984804c1b3..9612983510fe 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -1,13 +1,17 @@ #add_subdirectory(Icons) if(WIN32) -add_definitions(-DFCGui -DQIIS_MAKEDLL) + add_definitions(-DFCGui -DQIIS_MAKEDLL -DOVR_OS_WIN32) endif(WIN32) if (FREECAD_USE_3DCONNEXION) -add_definitions(-D_USE_3DCONNEXION_SDK) + add_definitions(-D_USE_3DCONNEXION_SDK) endif(FREECAD_USE_3DCONNEXION) +if (OCULUS_FOUND) + add_definitions(-D_USE_OCULUS_RIFT_SDK ) +endif(OCULUS_FOUND) + include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} @@ -60,6 +64,17 @@ IF(SPNAV_FOUND) ) ENDIF(SPNAV_FOUND) +IF(OCULUS_FOUND) + add_definitions(-DOCULUS_FOUND) + include_directories( + ${OCULUS_INCLUDE_DIRS} + ) + set(FreeCADGui_LIBS + ${FreeCADGui_LIBS} + ${OCULUS_LIBRARIES} + ) +ENDIF(OCULUS_FOUND) + if(SHIBOKEN_INCLUDE_DIR) add_definitions(-DHAVE_SHIBOKEN) include_directories( @@ -643,6 +658,7 @@ SET(View3D_CPP_SRCS View3DInventor.cpp View3DInventorExamples.cpp View3DInventorViewer.cpp + View3DInventorRiftViewer.cpp View3DPy.cpp ) SET(View3D_SRCS diff --git a/src/Gui/View3DInventorRiftViewer.cpp b/src/Gui/View3DInventorRiftViewer.cpp new file mode 100644 index 000000000000..71d0f3ed9972 --- /dev/null +++ b/src/Gui/View3DInventorRiftViewer.cpp @@ -0,0 +1,470 @@ +/**************************************************************************\ +* Copyright (c) Bastiaan Veelo (Bastiaan a_t Veelo d_o_t net) +* All rights reserved. Contact me if the below is too restrictive for you. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* +* Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\**************************************************************************/ + +#include "PreCompiled.h" + + +//#define USE_SO_OFFSCREEN_RENDERER +#define USE_FRAMEBUFFER + +#ifdef USE_SO_OFFSCREEN_RENDERER +# ifdef USE_FRAMEBUFFER +# error "Mutually exclusive options defined." +# endif +#endif + +#include +#include +#include +#include +#include +#include +#ifdef USE_SO_OFFSCREEN_RENDERER +# include +#endif +#ifdef USE_FRAMEBUFFER +# include +#endif +#include +#include +#include +//#include +#include <../Src/OVR_CAPI_GL.h> +#include <../Src/CAPI/GL/CAPI_GL_Util.h> // For framebuffer functions. + + +class CoinRiftWidget : public QGLWidget +{ + ovrHmd hmd; + ovrHmdDesc hmdDesc; + ovrEyeType eyes[2]; + ovrEyeRenderDesc eyeRenderDesc[2]; + ovrTexture eyeTexture[2]; + +#ifdef USE_FRAMEBUFFER + GLuint frameBufferID[2], depthBufferID[2]; + // A SoSceneManager has a SoRenderManager to do the rendering -- should we not use SoRenderManager instead? + // We are probably not that interested in events. SoSceneManager::setSceneGraph() searches for the camera + // and sets it in SoRenderManager, but its is actually only used for built-in stereo rendering. We sould + // probably eliminate that search... + SoSceneManager *m_sceneManager; +#endif +#ifdef USE_SO_OFFSCREEN_RENDERER + SoOffscreenRenderer *renderer; +#endif + SoSeparator *rootScene[2]; + SoFrustumCamera *camera[2]; + SoNode *scene; +public: + explicit CoinRiftWidget(); + ~CoinRiftWidget(); + void setSceneGraph(SoNode *sceneGraph); +protected: + void initializeGL(); + void paintGL(); + void resizeGL(int width, int height) { + int side = qMin(width, height); + glViewport((width - side) / 2, (height - side) / 2, side, side); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(-1.0, 1.0, -1.0, 1.0, 0.0, 1000.0); + glMatrixMode(GL_MODELVIEW); + } +}; + + +CoinRiftWidget::CoinRiftWidget() : QGLWidget() +{ + for (int eye = 0; eye < 2; eye++) { + reinterpret_cast(&eyeTexture[eye])->TexId = 0; +#ifdef USE_FRAMEBUFFER + frameBufferID[eye] = 0; + depthBufferID[eye] = 0; +#endif + } + + // OVR will do the swapping. + setAutoBufferSwap(false); + + hmd = ovrHmd_Create(0); + if (!hmd) { + qDebug() << "Could not find Rift device."; + exit(2); + } + ovrHmd_GetDesc(hmd, &hmdDesc); + if (!ovrHmd_StartSensor(hmd, ovrHmdCap_OrientationTracked | // Capabilities we support. + ovrHmdCap_YawCorrectionTracked | + ovrHmdCap_PositionTracked | + ovrHmdCap_LowPersistenceTracked, + ovrHmdCap_OrientationTracked)) { // Capabilities we require. + qDebug() << "Could not start Rift motion sensor."; + exit(3); + } + + resize(hmdDesc.Resolution.w, hmdDesc.Resolution.h); + + // Configure stereo settings. + ovrSizei recommenedTex0Size = ovrHmd_GetFovTextureSize(hmd, ovrEye_Left, + hmdDesc.DefaultEyeFov[0], 1.0f); + ovrSizei recommenedTex1Size = ovrHmd_GetFovTextureSize(hmd, ovrEye_Right, + hmdDesc.DefaultEyeFov[1], 1.0f); + +#ifdef USE_SO_OFFSCREEN_RENDERER + renderer = new SoOffscreenRenderer(SbViewportRegion(std::max(recommenedTex0Size.w, recommenedTex0Size.w), + std::max(recommenedTex1Size.h, recommenedTex1Size.h))); + renderer->setComponents(SoOffscreenRenderer::RGB_TRANSPARENCY); + renderer->setBackgroundColor(SbColor(.0f, .0f, .8f)); +#endif +#ifdef USE_FRAMEBUFFER + m_sceneManager = new SoSceneManager(); + m_sceneManager->setViewportRegion(SbViewportRegion(std::max(recommenedTex0Size.w, recommenedTex0Size.w), + std::max(recommenedTex1Size.h, recommenedTex1Size.h))); + m_sceneManager->setBackgroundColor(SbColor(.0f, .0f, .8f)); +#endif + + scene = new SoSeparator(0); // Placeholder. + for (int eye = 0; eye < 2; eye++) { + rootScene[eye] = new SoSeparator(3); + rootScene[eye]->ref(); + camera[eye] = new SoFrustumCamera(); + camera[eye]->position.setValue(0.0f, 0.0f, 5.0f); + camera[eye]->focalDistance.setValue(5.0f); + camera[eye]->viewportMapping.setValue(SoCamera::LEAVE_ALONE); + rootScene[eye]->addChild(camera[eye]); + rootScene[eye]->addChild(new SoDirectionalLight()); // TODO Connect direction to camera. + rootScene[eye]->addChild(scene); + } + + // Populate ovrEyeDesc[2]. + eyes[0].Eye = ovrEye_Left; + eyes[1].Eye = ovrEye_Right; + eyes[0].Fov = hmdDesc.DefaultEyeFov[0]; + eyes[1].Fov = hmdDesc.DefaultEyeFov[1]; +#ifdef USE_SO_OFFSCREEN_RENDERER + eyes[0].TextureSize.w = renderer->getViewportRegion().getViewportSizePixels().getValue()[0]; + eyes[0].TextureSize.h = renderer->getViewportRegion().getViewportSizePixels().getValue()[1]; + eyes[1].TextureSize = eyes[0].TextureSize; +#endif +#ifdef USE_FRAMEBUFFER + eyes[0].TextureSize = recommenedTex0Size; + eyes[1].TextureSize = recommenedTex1Size; +#endif + eyes[0].RenderViewport.Pos.x = 0; + eyes[0].RenderViewport.Pos.y = 0; + eyes[0].RenderViewport.Size = eyes[0].TextureSize; + eyes[1].RenderViewport.Pos = eyes[0].RenderViewport.Pos; + eyes[1].RenderViewport.Size = eyes[1].TextureSize; + + const int backBufferMultisample = 0; // TODO This is a guess? + ovrGLConfig cfg; + cfg.OGL.Header.API = ovrRenderAPI_OpenGL; + cfg.OGL.Header.RTSize = hmdDesc.Resolution; + cfg.OGL.Header.Multisample = backBufferMultisample; + cfg.OGL.Window = reinterpret_cast(winId()); + makeCurrent(); + cfg.OGL.WglContext = wglGetCurrentContext(); // http://stackoverflow.com/questions/17532033/qglwidget-get-gl-contextes-for-windows + cfg.OGL.GdiDc = wglGetCurrentDC(); + qDebug() << "Window:" << cfg.OGL.Window; + qDebug() << "Context:" << cfg.OGL.WglContext; + qDebug() << "DC:" << cfg.OGL.GdiDc; + + hmdDesc.DistortionCaps = 0; + hmdDesc.DistortionCaps |= ovrDistortion_Chromatic; +// hmdDesc.DistortionCaps |= ovrDistortion_TimeWarp; // Produces black screen... + hmdDesc.DistortionCaps |= ovrDistortion_Vignette; + + bool VSyncEnabled(false); // TODO This is a guess. + if (!ovrHmd_ConfigureRendering(hmd, &cfg.Config, (VSyncEnabled ? 0 : ovrHmdCap_NoVSync), + hmdDesc.DistortionCaps, eyes, eyeRenderDesc)) { + qDebug() << "Could not configure OVR rendering."; + exit(3); + } + + for (int eye = 0; eye < 2; eye++) { + camera[eye]->aspectRatio.setValue((eyeRenderDesc[eye].Desc.Fov.LeftTan + eyeRenderDesc[eye].Desc.Fov.RightTan) / + (eyeRenderDesc[eye].Desc.Fov.UpTan + eyeRenderDesc[eye].Desc.Fov.DownTan)); + camera[eye]->nearDistance.setValue(1.0f); + camera[eye]->farDistance.setValue(100.0f); + camera[eye]->left.setValue(-eyeRenderDesc[eye].Desc.Fov.LeftTan); + camera[eye]->right.setValue(eyeRenderDesc[eye].Desc.Fov.RightTan); + camera[eye]->top.setValue(eyeRenderDesc[eye].Desc.Fov.UpTan); + camera[eye]->bottom.setValue(-eyeRenderDesc[eye].Desc.Fov.DownTan); + } +} + + +CoinRiftWidget::~CoinRiftWidget() +{ +#ifdef USE_SO_OFFSCREEN_RENDERER + delete renderer; +#endif + for (int eye = 0; eye < 2; eye++) { + rootScene[eye]->unref(); + ovrGLTextureData *texData = reinterpret_cast(&eyeTexture[eye]); + if (texData->TexId) { + glDeleteTextures(1, &texData->TexId); + texData->TexId = 0; + } +#ifdef USE_FRAMEBUFFER + if (frameBufferID[eye] != 0) { +// OVR::CAPI::GL::glDeleteFramebuffersExt(1, &frameBufferID[eye]); // TODO + frameBufferID[eye] = 0; + } + if (depthBufferID[eye] != 0) { +// OVR::CAPI::GL::glDeleteRenderbuffersExt(1, &depthBufferID[eye]); // TODO + depthBufferID[eye] = 0; + } +#endif + } + scene = 0; + ovrHmd_StopSensor(hmd); + ovrHmd_Destroy(hmd); +} + + +void CoinRiftWidget::setSceneGraph(SoNode *sceneGraph) +{ + rootScene[0]->replaceChild(scene, sceneGraph); + rootScene[1]->replaceChild(scene, sceneGraph); + scene = sceneGraph; +} + + +void CoinRiftWidget::initializeGL() +{ + makeCurrent(); + // Infer hardware capabilites. +#ifdef USE_FRAMEBUFFER + OVR::CAPI::GL::InitGLExtensions(); + if (OVR::CAPI::GL::glBindFramebufferEXT == NULL) { + qDebug() << "No GL extensions found."; + exit(4); + } + + // Store old framebuffer. + GLint oldfb; + glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &oldfb); +#endif + + // Create rendering target textures. + glEnable(GL_TEXTURE_2D); + for (int eye = 0; eye < 2; eye++) { +#ifdef USE_FRAMEBUFFER + OVR::CAPI::GL::glGenFramebuffersEXT(1, &frameBufferID[eye]); + OVR::CAPI::GL::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frameBufferID[eye]); + // Create the render buffer. + OVR::CAPI::GL::glGenRenderbuffersEXT(1, &depthBufferID[eye]); + OVR::CAPI::GL::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBufferID[eye]); + OVR::CAPI::GL::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, + GL_DEPTH_COMPONENT16, + eyes[eye].TextureSize.w, + eyes[eye].TextureSize.h); + // Attach renderbuffer to framebuffer. + OVR::CAPI::GL::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, + GL_DEPTH_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, + depthBufferID[eye]); +#endif + ovrGLTextureData *texData = reinterpret_cast(&eyeTexture[eye]); + texData->Header.API = ovrRenderAPI_OpenGL; + texData->Header.TextureSize = eyes[eye].TextureSize; + texData->Header.RenderViewport = eyes[eye].RenderViewport; + glGenTextures(1, &texData->TexId); + glBindTexture(GL_TEXTURE_2D, texData->TexId); + Q_ASSERT(!glGetError()); + // Allocate storage for the texture. + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, eyes[eye].TextureSize.w, eyes[eye].TextureSize.h, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + Q_ASSERT(!glGetError()); +#ifdef USE_FRAMEBUFFER + // Attach texture to framebuffer color object. + OVR::CAPI::GL::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_2D, texData->TexId, 0); + if (OVR::CAPI::GL::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER) != + GL_FRAMEBUFFER_COMPLETE) + qDebug() << "ERROR: FrameBuffer is not operational!"; +#endif + } + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); + +#ifdef USE_FRAMEBUFFER + // Continue rendering to the orgiginal frame buffer (likely 0, the onscreen buffer). + OVR::CAPI::GL::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, oldfb); +#endif + doneCurrent(); +} + + +void CoinRiftWidget::paintGL() +{ + const int ms(1000 / 60 /*fps*/); + QTimer::singleShot(ms, this, SLOT(updateGL())); + makeCurrent(); + + glEnable(GL_TEXTURE_2D); + + /*ovrFrameTiming hmdFrameTiming =*/ ovrHmd_BeginFrame(hmd, 0); + for (int eyeIndex = 0; eyeIndex < ovrEye_Count; eyeIndex++) { + ovrEyeType eye = hmdDesc.EyeRenderOrder[eyeIndex]; + ovrPosef eyePose = ovrHmd_BeginEyeRender(hmd, eye); + + camera[eye]->orientation.setValue(eyePose.Orientation.x, + eyePose.Orientation.y, + eyePose.Orientation.z, + eyePose.Orientation.w); + + SbVec3f originalPosition(camera[eye]->position.getValue()); + camera[eye]->position.setValue(originalPosition - SbVec3f(eyeRenderDesc[eye].ViewAdjust.x, + eyeRenderDesc[eye].ViewAdjust.y, + eyeRenderDesc[eye].ViewAdjust.z)); + +#ifdef USE_SO_OFFSCREEN_RENDERER + ovrGLTextureData *texData = reinterpret_cast(&eyeTexture[eye]); + glBindTexture(GL_TEXTURE_2D, texData->TexId); + renderer->render(rootScene[eye]); + Q_ASSERT(!glGetError()); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + eyes[eye].TextureSize.w, + eyes[eye].TextureSize.h, + 0, GL_RGBA /*GL_BGRA*/, GL_UNSIGNED_BYTE, renderer->getBuffer()); + Q_ASSERT(!glGetError()); + glBindTexture(GL_TEXTURE_2D, 0); +#endif +#ifdef USE_FRAMEBUFFER + // Clear state pollution from OVR SDK. + glBindTexture(GL_TEXTURE_2D, 0); // You need this, at least if (hmdDesc.DistortionCaps & ovrDistortion_Chromatic). + OVR::CAPI::GL::glUseProgram(0); // You need this even more. + + GLint oldfb; + glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &oldfb); + // Set up framebuffer for rendering. + OVR::CAPI::GL::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frameBufferID[eye]); + + m_sceneManager->setSceneGraph(rootScene[eye]); +// m_sceneManager->setCamera(camera[eye]); // SoSceneManager does this implicitly. + m_sceneManager->render(); + + // Continue rendering to the orgiginal frame buffer (likely 0, the onscreen buffer). + OVR::CAPI::GL::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, oldfb); + Q_ASSERT(!glGetError()); +#endif + + camera[eye]->position.setValue(originalPosition); + + // Submit the texture for distortion. + ovrHmd_EndEyeRender(hmd, eye, eyePose, &eyeTexture[eye]); + } + + // Swap buffers. + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + ovrHmd_EndFrame(hmd); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glClearDepth(1.0); + + doneCurrent(); +} + + +static void cleanup() +{ + //SoDB::finish(); + ovr_Shutdown(); +} + + +int oculusTest(void) +{ + //SoDB::init(); + + //QApplication app(argc, argv); + qAddPostRoutine(cleanup); + + // Moved here because of https://developer.oculusvr.com/forums/viewtopic.php?f=17&t=7915&p=108503#p108503 + // Init libovr. + if (!ovr_Initialize()) { + qDebug() << "Could not initialize Oculus SDK."; + exit(1); + } + + CoinRiftWidget window; + window.show(); + + // An example scene. + static const char * inlineSceneGraph[] = { + "#Inventor V2.1 ascii\n", + "\n", + "Separator {\n", + " Rotation { rotation 1 0 0 0.3 }\n", + " Cone { }\n", + " BaseColor { rgb 1 0 0 }\n", + " Scale { scaleFactor .7 .7 .7 }\n", + " Cube { }\n", + "\n", + " DrawStyle { style LINES }\n", + " ShapeHints { vertexOrdering COUNTERCLOCKWISE }\n", + " Coordinate3 {\n", + " point [\n", + " -2 -2 1.1, -2 -1 1.1, -2 1 1.1, -2 2 1.1,\n", + " -1 -2 1.1, -1 -1 1.1, -1 1 1.1, -1 2 1.1\n", + " 1 -2 1.1, 1 -1 1.1, 1 1 1.1, 1 2 1.1\n", + " 2 -2 1.1, 2 -1 1.1, 2 1 1.1, 2 2 1.1\n", + " ]\n", + " }\n", + "\n", + " Complexity { value 0.7 }\n", + " NurbsSurface {\n", + " numUControlPoints 4\n", + " numVControlPoints 4\n", + " uKnotVector [ 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0 ]\n", + " vKnotVector [ 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0 ]\n", + " }\n", + "}\n", + NULL + }; + + SoInput in; + in.setStringArray(inlineSceneGraph); + + window.setSceneGraph(SoDB::readAll(&in)); + + //return app.exec(); +} \ No newline at end of file From 6ee9466c1298a8c016b4c517e70b1e37b0808032 Mon Sep 17 00:00:00 2001 From: jriegel Date: Fri, 12 Sep 2014 20:14:15 +0200 Subject: [PATCH 02/18] Make a new Build option for building VR support and make FindRift using the 64bit libs --- CMakeLists.txt | 7 +++++-- cMake/FindRift.cmake | 8 ++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 704f04e9ff59..08c9243f320c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -151,6 +151,7 @@ OPTION(BUILD_SPREADSHEET "Build the FreeCAD spreadsheet module" ON) OPTION(BUILD_START "Build the FreeCAD start module" ON) OPTION(BUILD_TEST "Build the FreeCAD test module" ON) OPTION(BUILD_WEB "Build the FreeCAD web module" ON) +OPTION(BUILD_VR "Build the FreeCAD Oculus Rift support (need Oculus SDK 4.x or higher)" OFF) if(MSVC) OPTION(FREECAD_USE_3DCONNEXION "Use the 3D connexion SDK to support 3d mouse." ON) @@ -647,7 +648,9 @@ else(FREECAD_LIBPACK_USE) endif(FREECAD_LIBPACK_USE) -find_package(Rift) +if(BUILD_VR) + find_package(Rift) +endif(BUILD_VR) # copy build convenient files for M$ if(WIN32) @@ -682,7 +685,7 @@ IF(MSVC) SET (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /EHa") SET (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DFC_DEBUG") # set default libs - SET (CMAKE_C_STANDARD_LIBRARIES "kernel32.lib user32.lib gdi32.lib winspool.lib SHFolder.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib ") + SET (CMAKE_C_STANDARD_LIBRARIES "kernel32.lib user32.lib gdi32.lib winspool.lib SHFolder.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib winmm.lib comsupp.lib Ws2_32.lib dbghelp.lib ") set (CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_C_STANDARD_LIBRARIES}") # set linker flag /nodefaultlib set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /NODEFAULTLIB") diff --git a/cMake/FindRift.cmake b/cMake/FindRift.cmake index 4a77de5759a7..55dd21b5194b 100644 --- a/cMake/FindRift.cmake +++ b/cMake/FindRift.cmake @@ -44,11 +44,11 @@ IF(OCULUS_ROOT) ) SET(OCULUS_LIBRARY_SEARCH_RELEASE_DIRS ${OCULUS_LIBRARY_SEARCH_DIRS} - ${OCULUS_ROOT}/lib/Win32 + ${OCULUS_ROOT}/Lib/x64/VS2012 ) SET(OCULUS_LIBRARY_SEARCH_DEBUG_DIRS ${OCULUS_LIBRARY_SEARCH_DIRS} - ${OCULUS_ROOT}/lib/Win32 + ${OCULUS_ROOT}/Lib/x64/VS2012 ) ENDIF() @@ -62,11 +62,11 @@ FIND_PATH(OCULUS_INCLUDE_DIR OVR.h PATHS ${OCULUS_INCLUDE_SEARCH_DIRS}) # Search for libraries files (release mode) -FIND_LIBRARY(OCULUS_LIBRARY_RELEASE libovr +FIND_LIBRARY(OCULUS_LIBRARY_RELEASE libovr64 PATHS ${OCULUS_LIBRARY_SEARCH_RELEASE_DIRS}) # Search for libraries files (debug mode) -FIND_LIBRARY(OCULUS_LIBRARY_DEBUG libovrd +FIND_LIBRARY(OCULUS_LIBRARY_DEBUG libovr64d PATHS ${OCULUS_LIBRARY_SEARCH_DEBUG_DIRS}) # Configure libraries for debug/release From 537d7edfd84eac6024aa179e462035d6d943082f Mon Sep 17 00:00:00 2001 From: jriegel Date: Fri, 12 Sep 2014 20:15:04 +0200 Subject: [PATCH 03/18] porting the offscreen rendering version to SDK 4.2 --- src/Gui/View3DInventorRiftViewer.cpp | 119 +++++++++++++++------------ 1 file changed, 66 insertions(+), 53 deletions(-) diff --git a/src/Gui/View3DInventorRiftViewer.cpp b/src/Gui/View3DInventorRiftViewer.cpp index 71d0f3ed9972..1adb46afd3ca 100644 --- a/src/Gui/View3DInventorRiftViewer.cpp +++ b/src/Gui/View3DInventorRiftViewer.cpp @@ -33,8 +33,10 @@ #include "PreCompiled.h" -//#define USE_SO_OFFSCREEN_RENDERER -#define USE_FRAMEBUFFER +#if _USE_OCULUS_RIFT_SDK + +#define USE_SO_OFFSCREEN_RENDERER +//#define USE_FRAMEBUFFER #ifdef USE_SO_OFFSCREEN_RENDERER # ifdef USE_FRAMEBUFFER @@ -42,6 +44,7 @@ # endif #endif +#include #include #include #include @@ -57,16 +60,22 @@ #include #include #include + +#include +#include +#include //#include #include <../Src/OVR_CAPI_GL.h> #include <../Src/CAPI/GL/CAPI_GL_Util.h> // For framebuffer functions. +#undef max + class CoinRiftWidget : public QGLWidget { ovrHmd hmd; ovrHmdDesc hmdDesc; - ovrEyeType eyes[2]; + //ovrEyeType eyes[2]; ovrEyeRenderDesc eyeRenderDesc[2]; ovrTexture eyeTexture[2]; @@ -121,12 +130,10 @@ CoinRiftWidget::CoinRiftWidget() : QGLWidget() qDebug() << "Could not find Rift device."; exit(2); } - ovrHmd_GetDesc(hmd, &hmdDesc); - if (!ovrHmd_StartSensor(hmd, ovrHmdCap_OrientationTracked | // Capabilities we support. - ovrHmdCap_YawCorrectionTracked | - ovrHmdCap_PositionTracked | - ovrHmdCap_LowPersistenceTracked, - ovrHmdCap_OrientationTracked)) { // Capabilities we require. + + if (!ovrHmd_ConfigureTracking (hmd, ovrTrackingCap_Orientation | + ovrTrackingCap_Position, + ovrTrackingCap_Orientation)) { // Capabilities we require. qDebug() << "Could not start Rift motion sensor."; exit(3); } @@ -166,24 +173,24 @@ CoinRiftWidget::CoinRiftWidget() : QGLWidget() } // Populate ovrEyeDesc[2]. - eyes[0].Eye = ovrEye_Left; - eyes[1].Eye = ovrEye_Right; - eyes[0].Fov = hmdDesc.DefaultEyeFov[0]; - eyes[1].Fov = hmdDesc.DefaultEyeFov[1]; + eyeRenderDesc[0].Eye = ovrEye_Left; + eyeRenderDesc[1].Eye = ovrEye_Right; + eyeRenderDesc[0].Fov = hmdDesc.DefaultEyeFov[0]; + eyeRenderDesc[1].Fov = hmdDesc.DefaultEyeFov[1]; #ifdef USE_SO_OFFSCREEN_RENDERER - eyes[0].TextureSize.w = renderer->getViewportRegion().getViewportSizePixels().getValue()[0]; - eyes[0].TextureSize.h = renderer->getViewportRegion().getViewportSizePixels().getValue()[1]; - eyes[1].TextureSize = eyes[0].TextureSize; + eyeTexture[0].Header.TextureSize.w = renderer->getViewportRegion().getViewportSizePixels().getValue()[0]; + eyeTexture[0].Header.TextureSize.h = renderer->getViewportRegion().getViewportSizePixels().getValue()[1]; + eyeTexture[1].Header.TextureSize = eyeTexture[0].Header.TextureSize; #endif #ifdef USE_FRAMEBUFFER eyes[0].TextureSize = recommenedTex0Size; eyes[1].TextureSize = recommenedTex1Size; #endif - eyes[0].RenderViewport.Pos.x = 0; - eyes[0].RenderViewport.Pos.y = 0; - eyes[0].RenderViewport.Size = eyes[0].TextureSize; - eyes[1].RenderViewport.Pos = eyes[0].RenderViewport.Pos; - eyes[1].RenderViewport.Size = eyes[1].TextureSize; + eyeTexture[0].Header.RenderViewport.Pos.x = 0; + eyeTexture[0].Header.RenderViewport.Pos.y = 0; + eyeTexture[0].Header.RenderViewport.Size = eyeTexture[1].Header.TextureSize; + eyeTexture[0].Header.RenderViewport.Pos = eyeTexture[0].Header.RenderViewport.Pos; + eyeTexture[0].Header.RenderViewport.Size = eyeTexture[1].Header.TextureSize; const int backBufferMultisample = 0; // TODO This is a guess? ovrGLConfig cfg; @@ -192,33 +199,37 @@ CoinRiftWidget::CoinRiftWidget() : QGLWidget() cfg.OGL.Header.Multisample = backBufferMultisample; cfg.OGL.Window = reinterpret_cast(winId()); makeCurrent(); - cfg.OGL.WglContext = wglGetCurrentContext(); // http://stackoverflow.com/questions/17532033/qglwidget-get-gl-contextes-for-windows - cfg.OGL.GdiDc = wglGetCurrentDC(); + //cfg.OGL.WglContext = wglGetCurrentContext(); // http://stackoverflow.com/questions/17532033/qglwidget-get-gl-contextes-for-windows + cfg.OGL.DC = wglGetCurrentDC(); qDebug() << "Window:" << cfg.OGL.Window; - qDebug() << "Context:" << cfg.OGL.WglContext; - qDebug() << "DC:" << cfg.OGL.GdiDc; + //qDebug() << "Context:" << cfg.OGL.WglContext; + qDebug() << "DC:" << cfg.OGL.DC; hmdDesc.DistortionCaps = 0; - hmdDesc.DistortionCaps |= ovrDistortion_Chromatic; -// hmdDesc.DistortionCaps |= ovrDistortion_TimeWarp; // Produces black screen... - hmdDesc.DistortionCaps |= ovrDistortion_Vignette; + hmdDesc.DistortionCaps |= ovrDistortionCap_Chromatic; +// hmdDesc.DistortionCaps |= ovrDistortionCap_TimeWarp; // Produces black screen... + hmdDesc.DistortionCaps |= ovrDistortionCap_Vignette; bool VSyncEnabled(false); // TODO This is a guess. - if (!ovrHmd_ConfigureRendering(hmd, &cfg.Config, (VSyncEnabled ? 0 : ovrHmdCap_NoVSync), - hmdDesc.DistortionCaps, eyes, eyeRenderDesc)) { + if (!ovrHmd_ConfigureRendering( hmd, + &cfg.Config, + /*(VSyncEnabled ? 0 : ovrHmdCap_NoVSync),*/ + hmdDesc.DistortionCaps, + hmdDesc.DefaultEyeFov,//eyes, + eyeRenderDesc)) { qDebug() << "Could not configure OVR rendering."; exit(3); } for (int eye = 0; eye < 2; eye++) { - camera[eye]->aspectRatio.setValue((eyeRenderDesc[eye].Desc.Fov.LeftTan + eyeRenderDesc[eye].Desc.Fov.RightTan) / - (eyeRenderDesc[eye].Desc.Fov.UpTan + eyeRenderDesc[eye].Desc.Fov.DownTan)); + camera[eye]->aspectRatio.setValue((eyeRenderDesc[eye].Fov.LeftTan + eyeRenderDesc[eye].Fov.RightTan) / + (eyeRenderDesc[eye].Fov.UpTan + eyeRenderDesc[eye].Fov.DownTan)); camera[eye]->nearDistance.setValue(1.0f); camera[eye]->farDistance.setValue(100.0f); - camera[eye]->left.setValue(-eyeRenderDesc[eye].Desc.Fov.LeftTan); - camera[eye]->right.setValue(eyeRenderDesc[eye].Desc.Fov.RightTan); - camera[eye]->top.setValue(eyeRenderDesc[eye].Desc.Fov.UpTan); - camera[eye]->bottom.setValue(-eyeRenderDesc[eye].Desc.Fov.DownTan); + camera[eye]->left.setValue(-eyeRenderDesc[eye].Fov.LeftTan); + camera[eye]->right.setValue(eyeRenderDesc[eye].Fov.RightTan); + camera[eye]->top.setValue(eyeRenderDesc[eye].Fov.UpTan); + camera[eye]->bottom.setValue(-eyeRenderDesc[eye].Fov.DownTan); } } @@ -247,7 +258,7 @@ CoinRiftWidget::~CoinRiftWidget() #endif } scene = 0; - ovrHmd_StopSensor(hmd); + //ovrHmd_StopSensor(hmd); ovrHmd_Destroy(hmd); } @@ -280,30 +291,30 @@ void CoinRiftWidget::initializeGL() glEnable(GL_TEXTURE_2D); for (int eye = 0; eye < 2; eye++) { #ifdef USE_FRAMEBUFFER - OVR::CAPI::GL::glGenFramebuffersEXT(1, &frameBufferID[eye]); - OVR::CAPI::GL::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frameBufferID[eye]); + OVR::CAPI::GL::glGenFramebuffers(1, &frameBufferID[eye]); + OVR::CAPI::GL::glBindFramebuffer(GL_FRAMEBUFFER_EXT, frameBufferID[eye]); // Create the render buffer. - OVR::CAPI::GL::glGenRenderbuffersEXT(1, &depthBufferID[eye]); - OVR::CAPI::GL::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBufferID[eye]); - OVR::CAPI::GL::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, + OVR::CAPI::GL::glGenRenderbuffers(1, &depthBufferID[eye]); + OVR::CAPI::GL::glBindRenderbuffer(GL_RENDERBUFFER_EXT, depthBufferID[eye]); + OVR::CAPI::GL::glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, eyes[eye].TextureSize.w, eyes[eye].TextureSize.h); // Attach renderbuffer to framebuffer. - OVR::CAPI::GL::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, + OVR::CAPI::GL::glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthBufferID[eye]); #endif ovrGLTextureData *texData = reinterpret_cast(&eyeTexture[eye]); texData->Header.API = ovrRenderAPI_OpenGL; - texData->Header.TextureSize = eyes[eye].TextureSize; - texData->Header.RenderViewport = eyes[eye].RenderViewport; + texData->Header.TextureSize = eyeTexture[eye].Header.TextureSize; + texData->Header.RenderViewport = eyeTexture[eye].Header.RenderViewport; glGenTextures(1, &texData->TexId); glBindTexture(GL_TEXTURE_2D, texData->TexId); Q_ASSERT(!glGetError()); // Allocate storage for the texture. - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, eyes[eye].TextureSize.w, eyes[eye].TextureSize.h, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, eyeTexture[eye].Header.TextureSize.w, eyeTexture[eye].Header.TextureSize.h, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); @@ -343,7 +354,7 @@ void CoinRiftWidget::paintGL() /*ovrFrameTiming hmdFrameTiming =*/ ovrHmd_BeginFrame(hmd, 0); for (int eyeIndex = 0; eyeIndex < ovrEye_Count; eyeIndex++) { ovrEyeType eye = hmdDesc.EyeRenderOrder[eyeIndex]; - ovrPosef eyePose = ovrHmd_BeginEyeRender(hmd, eye); + ovrPosef eyePose = ovrHmd_GetEyePose(hmd, eye); camera[eye]->orientation.setValue(eyePose.Orientation.x, eyePose.Orientation.y, @@ -361,8 +372,8 @@ void CoinRiftWidget::paintGL() renderer->render(rootScene[eye]); Q_ASSERT(!glGetError()); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, - eyes[eye].TextureSize.w, - eyes[eye].TextureSize.h, + eyeTexture[eye].Header.TextureSize.w, + eyeTexture[eye].Header.TextureSize.h, 0, GL_RGBA /*GL_BGRA*/, GL_UNSIGNED_BYTE, renderer->getBuffer()); Q_ASSERT(!glGetError()); glBindTexture(GL_TEXTURE_2D, 0); @@ -389,13 +400,13 @@ void CoinRiftWidget::paintGL() camera[eye]->position.setValue(originalPosition); // Submit the texture for distortion. - ovrHmd_EndEyeRender(hmd, eye, eyePose, &eyeTexture[eye]); + ovrHmd_EndFrame(hmd, &eyePose, &eyeTexture[eye]); } // Swap buffers. glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); - ovrHmd_EndFrame(hmd); + //ovrHmd_EndFrame(hmd); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glClearDepth(1.0); @@ -422,7 +433,7 @@ int oculusTest(void) // Init libovr. if (!ovr_Initialize()) { qDebug() << "Could not initialize Oculus SDK."; - exit(1); + return 0; } CoinRiftWidget window; @@ -467,4 +478,6 @@ int oculusTest(void) window.setSceneGraph(SoDB::readAll(&in)); //return app.exec(); -} \ No newline at end of file +} + +#endif //_USE_OCULUS_RIFT_SDK \ No newline at end of file From c0152eeb684d8c5749668883de929afabd6d0cb5 Mon Sep 17 00:00:00 2001 From: jriegel Date: Sat, 13 Sep 2014 10:18:52 +0200 Subject: [PATCH 04/18] FreeCAD-VR: command integration --- src/Gui/CMakeLists.txt | 6 +++--- src/Gui/CommandView.cpp | 32 ++++++++++++++++++++++++++++ src/Gui/View3DInventor.cpp | 13 ++++++++++- src/Gui/View3DInventorRiftViewer.cpp | 8 +++++-- src/Gui/View3DInventorViewer.cpp | 13 +++++++++++ src/Gui/View3DInventorViewer.h | 4 ++++ src/Gui/Workbench.cpp | 6 +++++- 7 files changed, 75 insertions(+), 7 deletions(-) diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index 13214c515cc6..4a4f6e235d04 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -8,9 +8,9 @@ if (FREECAD_USE_3DCONNEXION) add_definitions(-D_USE_3DCONNEXION_SDK) endif(FREECAD_USE_3DCONNEXION) -if (OCULUS_FOUND) - add_definitions(-D_USE_OCULUS_RIFT_SDK ) -endif(OCULUS_FOUND) +if (BUILD_VR) + add_definitions(-DBUILD_VR ) +endif(BUILD_VR) include_directories( ${CMAKE_CURRENT_SOURCE_DIR} diff --git a/src/Gui/CommandView.cpp b/src/Gui/CommandView.cpp index 8afd1aa77e00..8bd70449bc3f 100644 --- a/src/Gui/CommandView.cpp +++ b/src/Gui/CommandView.cpp @@ -1408,6 +1408,37 @@ bool StdViewDockUndockFullscreen::isActive(void) return false; } + +//=========================================================================== +// Std_ViewVR +//=========================================================================== +DEF_STD_CMD_A(StdCmdViewVR); + +StdCmdViewVR::StdCmdViewVR() + : Command("Std_ViewVR") +{ + sGroup = QT_TR_NOOP("Standard-View"); + sMenuText = QT_TR_NOOP("FreeCAD-VR"); + sToolTipText = QT_TR_NOOP("Extend the FreeCAD 3D Window to a Oculus Rift"); + sWhatsThis = "Std_ViewVR"; + sStatusTip = QT_TR_NOOP("Extend the FreeCAD 3D Window to a Oculus Rift"); + sPixmap = "view-zoom-all"; + eType = Alter3DView; +} + +void StdCmdViewVR::activated(int iMsg) +{ + //doCommand(Command::Gui,"Gui.activeDocument().activeView().fitAll()"); + doCommand(Command::Gui,"Gui.SendMsgToActiveView(\"ViewVR\")"); +} + +bool StdCmdViewVR::isActive(void) +{ + return getGuiApplication()->sendHasMsgToActiveView("ViewVR"); +} + + + //=========================================================================== // Std_ViewScreenShot //=========================================================================== @@ -2453,6 +2484,7 @@ void CreateViewStdCommands(void) rcCmdMgr.addCommand(new StdCmdViewTop()); rcCmdMgr.addCommand(new StdCmdViewAxo()); rcCmdMgr.addCommand(new StdCmdViewFitAll()); + rcCmdMgr.addCommand(new StdCmdViewVR()); rcCmdMgr.addCommand(new StdCmdViewFitSelection()); rcCmdMgr.addCommand(new StdCmdViewRotateLeft()); rcCmdMgr.addCommand(new StdCmdViewRotateRight()); diff --git a/src/Gui/View3DInventor.cpp b/src/Gui/View3DInventor.cpp index 61d417f79c79..1d44f3b00a42 100644 --- a/src/Gui/View3DInventor.cpp +++ b/src/Gui/View3DInventor.cpp @@ -366,7 +366,7 @@ void View3DInventor::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::M _viewer->turnDeltaDimensionsOn(); else _viewer->turnDeltaDimensionsOff(); - } + } else{ unsigned long col1 = rGrp.GetUnsigned("BackgroundColor",3940932863UL); unsigned long col2 = rGrp.GetUnsigned("BackgroundColor2",859006463UL); // default color (dark blue) @@ -545,6 +545,11 @@ bool View3DInventor::onMsg(const char* pMsg, const char** ppReturn) _viewer->viewAll(); return true; } + else if (strcmp("ViewVR",pMsg) == 0) { + // call the VR portion of the viewer + _viewer->viewVR(); + return true; + } else if(strcmp("ViewSelection",pMsg) == 0) { _viewer->viewSelection(); return true; @@ -728,6 +733,12 @@ bool View3DInventor::onHasMsg(const char* pMsg) const return true; else if(strcmp("ViewFit",pMsg) == 0) return true; + else if(strcmp("ViewVR",pMsg) == 0) +#ifdef BUILD_VR + return true; +#elif + return false; +#endif else if(strcmp("ViewSelection",pMsg) == 0) return true; else if(strcmp("ViewBottom",pMsg) == 0) diff --git a/src/Gui/View3DInventorRiftViewer.cpp b/src/Gui/View3DInventorRiftViewer.cpp index 1adb46afd3ca..6e8725557aac 100644 --- a/src/Gui/View3DInventorRiftViewer.cpp +++ b/src/Gui/View3DInventorRiftViewer.cpp @@ -33,7 +33,11 @@ #include "PreCompiled.h" -#if _USE_OCULUS_RIFT_SDK +#if BUILD_VR + +#ifndef OCULUS_FOUND +# error "Build VR without the Oculus SDK makes no sense at all" +#endif #define USE_SO_OFFSCREEN_RENDERER //#define USE_FRAMEBUFFER @@ -480,4 +484,4 @@ int oculusTest(void) //return app.exec(); } -#endif //_USE_OCULUS_RIFT_SDK \ No newline at end of file +#endif //BUILD_VR \ No newline at end of file diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index e7563f3c41d0..af3325c722f7 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -1636,6 +1636,19 @@ void View3DInventorViewer::animatedViewAll(int steps, int ms) } } +#if BUILD_VR +extern int oculusTest(void); +#endif + +void View3DInventorViewer::viewVR(void) +{ +#if BUILD_VR + oculusTest(); +#endif +} + + + void View3DInventorViewer::boxZoom(const SbBox2s& box) { navigation->boxZoom(box); diff --git a/src/Gui/View3DInventorViewer.h b/src/Gui/View3DInventorViewer.h index 1fe23218ca96..733059a387d1 100644 --- a/src/Gui/View3DInventorViewer.h +++ b/src/Gui/View3DInventorViewer.h @@ -310,6 +310,10 @@ class GuiExport View3DInventorViewer : public SoQtViewer, public Gui::SelectionS */ void viewAll(); void viewAll(float factor); + + /// Breaks out a VR window for a Rift + void viewVR(void); + /** * Reposition the current camera so we can see all selected objects * of the scene. Therefore we search for all SOFCSelection nodes, if diff --git a/src/Gui/Workbench.cpp b/src/Gui/Workbench.cpp index fa9c70c2f5b8..df1906121b05 100644 --- a/src/Gui/Workbench.cpp +++ b/src/Gui/Workbench.cpp @@ -487,7 +487,11 @@ MenuItem* StdWorkbench::setupMenuBar() const *view << "Std_ViewCreate" << "Std_OrthographicCamera" << "Std_PerspectiveCamera" << "Separator" << stdviews << "Std_FreezeViews" << "Std_DrawStyle" << "Separator" << view3d << zoom << "Std_ViewDockUndockFullscreen" << "Std_AxisCross" << "Std_ToggleClipPlane" - << "Std_TextureMapping" << "Separator" << visu + << "Std_TextureMapping" +#ifdef BUILD_VR + << "Std_ViewVR" +#endif + << "Separator" << visu << "Std_ToggleVisibility" << "Std_ToggleNavigation" << "Std_SetAppearance" << "Std_RandomColor" << "Separator" << "Std_MeasureDistance" << "Separator" From ad2406a76350f495ec1ccc21524eec1f3a7ed9dd Mon Sep 17 00:00:00 2001 From: jriegel Date: Sat, 13 Sep 2014 20:03:57 +0200 Subject: [PATCH 05/18] FreeCAD-VR: First succesfull render on the Rift! --- src/Gui/View3DInventorRiftViewer.cpp | 83 +++++++++++++++++----------- src/Gui/View3DInventorViewer.cpp | 9 ++- 2 files changed, 57 insertions(+), 35 deletions(-) diff --git a/src/Gui/View3DInventorRiftViewer.cpp b/src/Gui/View3DInventorRiftViewer.cpp index 6e8725557aac..23d9277c272c 100644 --- a/src/Gui/View3DInventorRiftViewer.cpp +++ b/src/Gui/View3DInventorRiftViewer.cpp @@ -78,7 +78,7 @@ class CoinRiftWidget : public QGLWidget { ovrHmd hmd; - ovrHmdDesc hmdDesc; + //ovrHmdDesc hmdDesc; //ovrEyeType eyes[2]; ovrEyeRenderDesc eyeRenderDesc[2]; ovrTexture eyeTexture[2]; @@ -132,23 +132,24 @@ CoinRiftWidget::CoinRiftWidget() : QGLWidget() hmd = ovrHmd_Create(0); if (!hmd) { qDebug() << "Could not find Rift device."; - exit(2); + throw; } if (!ovrHmd_ConfigureTracking (hmd, ovrTrackingCap_Orientation | + ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Position, ovrTrackingCap_Orientation)) { // Capabilities we require. qDebug() << "Could not start Rift motion sensor."; - exit(3); + throw; } - resize(hmdDesc.Resolution.w, hmdDesc.Resolution.h); + resize(hmd->Resolution.w, hmd->Resolution.h); // Configure stereo settings. ovrSizei recommenedTex0Size = ovrHmd_GetFovTextureSize(hmd, ovrEye_Left, - hmdDesc.DefaultEyeFov[0], 1.0f); + hmd->DefaultEyeFov[0], 1.0f); ovrSizei recommenedTex1Size = ovrHmd_GetFovTextureSize(hmd, ovrEye_Right, - hmdDesc.DefaultEyeFov[1], 1.0f); + hmd->DefaultEyeFov[1], 1.0f); #ifdef USE_SO_OFFSCREEN_RENDERER renderer = new SoOffscreenRenderer(SbViewportRegion(std::max(recommenedTex0Size.w, recommenedTex0Size.w), @@ -179,8 +180,8 @@ CoinRiftWidget::CoinRiftWidget() : QGLWidget() // Populate ovrEyeDesc[2]. eyeRenderDesc[0].Eye = ovrEye_Left; eyeRenderDesc[1].Eye = ovrEye_Right; - eyeRenderDesc[0].Fov = hmdDesc.DefaultEyeFov[0]; - eyeRenderDesc[1].Fov = hmdDesc.DefaultEyeFov[1]; + eyeRenderDesc[0].Fov = hmd->DefaultEyeFov[0]; + eyeRenderDesc[1].Fov = hmd->DefaultEyeFov[1]; #ifdef USE_SO_OFFSCREEN_RENDERER eyeTexture[0].Header.TextureSize.w = renderer->getViewportRegion().getViewportSizePixels().getValue()[0]; eyeTexture[0].Header.TextureSize.h = renderer->getViewportRegion().getViewportSizePixels().getValue()[1]; @@ -192,14 +193,14 @@ CoinRiftWidget::CoinRiftWidget() : QGLWidget() #endif eyeTexture[0].Header.RenderViewport.Pos.x = 0; eyeTexture[0].Header.RenderViewport.Pos.y = 0; - eyeTexture[0].Header.RenderViewport.Size = eyeTexture[1].Header.TextureSize; - eyeTexture[0].Header.RenderViewport.Pos = eyeTexture[0].Header.RenderViewport.Pos; - eyeTexture[0].Header.RenderViewport.Size = eyeTexture[1].Header.TextureSize; + eyeTexture[0].Header.RenderViewport.Size = eyeTexture[0].Header.TextureSize; + eyeTexture[1].Header.RenderViewport.Pos = eyeTexture[0].Header.RenderViewport.Pos; + eyeTexture[1].Header.RenderViewport.Size = eyeTexture[1].Header.TextureSize; const int backBufferMultisample = 0; // TODO This is a guess? ovrGLConfig cfg; cfg.OGL.Header.API = ovrRenderAPI_OpenGL; - cfg.OGL.Header.RTSize = hmdDesc.Resolution; + cfg.OGL.Header.RTSize = hmd->Resolution; cfg.OGL.Header.Multisample = backBufferMultisample; cfg.OGL.Window = reinterpret_cast(winId()); makeCurrent(); @@ -209,17 +210,17 @@ CoinRiftWidget::CoinRiftWidget() : QGLWidget() //qDebug() << "Context:" << cfg.OGL.WglContext; qDebug() << "DC:" << cfg.OGL.DC; - hmdDesc.DistortionCaps = 0; - hmdDesc.DistortionCaps |= ovrDistortionCap_Chromatic; -// hmdDesc.DistortionCaps |= ovrDistortionCap_TimeWarp; // Produces black screen... - hmdDesc.DistortionCaps |= ovrDistortionCap_Vignette; + int DistortionCaps = 0; + DistortionCaps |= ovrDistortionCap_Chromatic; +// DistortionCaps |= ovrDistortionCap_TimeWarp; // Produces black screen... + DistortionCaps |= ovrDistortionCap_Vignette; bool VSyncEnabled(false); // TODO This is a guess. if (!ovrHmd_ConfigureRendering( hmd, &cfg.Config, /*(VSyncEnabled ? 0 : ovrHmdCap_NoVSync),*/ - hmdDesc.DistortionCaps, - hmdDesc.DefaultEyeFov,//eyes, + DistortionCaps, + hmd->DefaultEyeFov,//eyes, eyeRenderDesc)) { qDebug() << "Could not configure OVR rendering."; exit(3); @@ -348,22 +349,24 @@ void CoinRiftWidget::initializeGL() void CoinRiftWidget::paintGL() -{ +{ const int ms(1000 / 60 /*fps*/); QTimer::singleShot(ms, this, SLOT(updateGL())); makeCurrent(); + ovrPosef eyePose[2]; + glEnable(GL_TEXTURE_2D); /*ovrFrameTiming hmdFrameTiming =*/ ovrHmd_BeginFrame(hmd, 0); for (int eyeIndex = 0; eyeIndex < ovrEye_Count; eyeIndex++) { - ovrEyeType eye = hmdDesc.EyeRenderOrder[eyeIndex]; - ovrPosef eyePose = ovrHmd_GetEyePose(hmd, eye); + ovrEyeType eye = hmd->EyeRenderOrder[eyeIndex]; + eyePose[eye] = ovrHmd_GetEyePose(hmd, eye); - camera[eye]->orientation.setValue(eyePose.Orientation.x, - eyePose.Orientation.y, - eyePose.Orientation.z, - eyePose.Orientation.w); + camera[eye]->orientation.setValue(eyePose[eye].Orientation.x, + eyePose[eye].Orientation.y, + eyePose[eye].Orientation.z, + eyePose[eye].Orientation.w); SbVec3f originalPosition(camera[eye]->position.getValue()); camera[eye]->position.setValue(originalPosition - SbVec3f(eyeRenderDesc[eye].ViewAdjust.x, @@ -403,9 +406,10 @@ void CoinRiftWidget::paintGL() camera[eye]->position.setValue(originalPosition); - // Submit the texture for distortion. - ovrHmd_EndFrame(hmd, &eyePose, &eyeTexture[eye]); } + + // Submit the texture for distortion. + ovrHmd_EndFrame(hmd, eyePose, eyeTexture); // Swap buffers. glDisable(GL_CULL_FACE); @@ -419,19 +423,31 @@ void CoinRiftWidget::paintGL() } -static void cleanup() + static CoinRiftWidget *window=0; + + +void oculusStop() { //SoDB::finish(); + if(window){ + delete window; + window = 0; + } + ovr_Shutdown(); } +bool oculusUp(void) +{ + return window!=0; +} -int oculusTest(void) +int oculusStart(void) { //SoDB::init(); //QApplication app(argc, argv); - qAddPostRoutine(cleanup); + //qAddPostRoutine(cleanup); // Moved here because of https://developer.oculusvr.com/forums/viewtopic.php?f=17&t=7915&p=108503#p108503 // Init libovr. @@ -440,8 +456,8 @@ int oculusTest(void) return 0; } - CoinRiftWidget window; - window.show(); + window = new CoinRiftWidget; + window->show(); // An example scene. static const char * inlineSceneGraph[] = { @@ -479,8 +495,9 @@ int oculusTest(void) SoInput in; in.setStringArray(inlineSceneGraph); - window.setSceneGraph(SoDB::readAll(&in)); + window->setSceneGraph(SoDB::readAll(&in)); + return 1; //return app.exec(); } diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index af3325c722f7..8f78ea210188 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -1637,13 +1637,18 @@ void View3DInventorViewer::animatedViewAll(int steps, int ms) } #if BUILD_VR -extern int oculusTest(void); +extern int oculusStart(void); +extern bool oculusUp (void); +extern void oculusStop (void); #endif void View3DInventorViewer::viewVR(void) { #if BUILD_VR - oculusTest(); + if(oculusUp()) + oculusStop(); + else + oculusStart(); #endif } From 250426f7922d43f9d4a6d2feadacf6996fe41572 Mon Sep 17 00:00:00 2001 From: jriegel Date: Sun, 14 Sep 2014 13:54:02 +0200 Subject: [PATCH 06/18] FreeCAD-VR: Handling the safety warning --- src/Gui/View3DInventorRiftViewer.cpp | 37 +++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/Gui/View3DInventorRiftViewer.cpp b/src/Gui/View3DInventorRiftViewer.cpp index 23d9277c272c..a0289d2f8986 100644 --- a/src/Gui/View3DInventorRiftViewer.cpp +++ b/src/Gui/View3DInventorRiftViewer.cpp @@ -102,6 +102,7 @@ class CoinRiftWidget : public QGLWidget ~CoinRiftWidget(); void setSceneGraph(SoNode *sceneGraph); protected: + void handlingSafetyWarning(void); void initializeGL(); void paintGL(); void resizeGL(int width, int height) { @@ -350,8 +351,12 @@ void CoinRiftWidget::initializeGL() void CoinRiftWidget::paintGL() { - const int ms(1000 / 60 /*fps*/); + const int ms(1000 / 75 /*fps*/); QTimer::singleShot(ms, this, SLOT(updateGL())); + + // handling the sfety warning + handlingSafetyWarning(); + makeCurrent(); ovrPosef eyePose[2]; @@ -422,6 +427,36 @@ void CoinRiftWidget::paintGL() doneCurrent(); } +void CoinRiftWidget::handlingSafetyWarning(void) +{ + // Health and Safety Warning display state. + ovrHSWDisplayState hswDisplayState; + ovrHmd_GetHSWDisplayState(hmd, &hswDisplayState); + if (hswDisplayState.Displayed) + { + // Dismiss the warning if the user pressed the appropriate key or if the user + // is tapping the side of the HMD. + // If the user has requested to dismiss the warning via keyboard or controller input... + //if (Util_GetAndResetHSWDismissedState()) + ovrHmd_DismissHSWDisplay(hmd); + //else + //{ + // // Detect a moderate tap on the side of the HMD. + // ovrTrackingState ts = ovrHmd_GetTrackingState(hmd, ovr_GetTimeInSeconds()); + // if (ts.StatusFlags & ovrStatus_OrientationTracked) + // { + // const OVR::Vector3f v(ts.RawSensorData.Accelerometer.x, + // ts.RawSensorData.Accelerometer.y, + // ts.RawSensorData.Accelerometer.z); + // // Arbitrary value and representing moderate tap on the side of the DK2 Rift. + // if (v.LengthSq() > 250.f) + // ovrHmd_DismissHSWDisplay(hmd); + // } + //} + } + +} + static CoinRiftWidget *window=0; From 66a58c40ad3852d5267a6ae4d4b617268baabdba Mon Sep 17 00:00:00 2001 From: jriegel Date: Sun, 14 Sep 2014 14:57:07 +0200 Subject: [PATCH 07/18] FreeCAD-VR: Some fixes... --- src/Gui/View3DInventorRiftViewer.cpp | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/Gui/View3DInventorRiftViewer.cpp b/src/Gui/View3DInventorRiftViewer.cpp index a0289d2f8986..c62bee398812 100644 --- a/src/Gui/View3DInventorRiftViewer.cpp +++ b/src/Gui/View3DInventorRiftViewer.cpp @@ -114,6 +114,8 @@ class CoinRiftWidget : public QGLWidget glOrtho(-1.0, 1.0, -1.0, 1.0, 0.0, 1000.0); glMatrixMode(GL_MODELVIEW); } + + SbVec3f basePosition; }; @@ -139,7 +141,10 @@ CoinRiftWidget::CoinRiftWidget() : QGLWidget() if (!ovrHmd_ConfigureTracking (hmd, ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Position, - ovrTrackingCap_Orientation)) { // Capabilities we require. + ovrTrackingCap_Orientation | + ovrTrackingCap_MagYawCorrection | + ovrTrackingCap_Position + )) { // Capabilities we require. qDebug() << "Could not start Rift motion sensor."; throw; } @@ -164,13 +169,14 @@ CoinRiftWidget::CoinRiftWidget() : QGLWidget() std::max(recommenedTex1Size.h, recommenedTex1Size.h))); m_sceneManager->setBackgroundColor(SbColor(.0f, .0f, .8f)); #endif + basePosition = SbVec3f(0.0f, 0.0f, 5.0f); scene = new SoSeparator(0); // Placeholder. for (int eye = 0; eye < 2; eye++) { rootScene[eye] = new SoSeparator(3); rootScene[eye]->ref(); camera[eye] = new SoFrustumCamera(); - camera[eye]->position.setValue(0.0f, 0.0f, 5.0f); + camera[eye]->position.setValue(basePosition); camera[eye]->focalDistance.setValue(5.0f); camera[eye]->viewportMapping.setValue(SoCamera::LEAVE_ALONE); rootScene[eye]->addChild(camera[eye]); @@ -215,6 +221,7 @@ CoinRiftWidget::CoinRiftWidget() : QGLWidget() DistortionCaps |= ovrDistortionCap_Chromatic; // DistortionCaps |= ovrDistortionCap_TimeWarp; // Produces black screen... DistortionCaps |= ovrDistortionCap_Vignette; + DistortionCaps |= ovrDistortionCap_HqDistortion; bool VSyncEnabled(false); // TODO This is a guess. if (!ovrHmd_ConfigureRendering( hmd, @@ -363,7 +370,7 @@ void CoinRiftWidget::paintGL() glEnable(GL_TEXTURE_2D); - /*ovrFrameTiming hmdFrameTiming =*/ ovrHmd_BeginFrame(hmd, 0); + ovrFrameTiming hmdFrameTiming = ovrHmd_BeginFrame(hmd, 0); for (int eyeIndex = 0; eyeIndex < ovrEye_Count; eyeIndex++) { ovrEyeType eye = hmd->EyeRenderOrder[eyeIndex]; eyePose[eye] = ovrHmd_GetEyePose(hmd, eye); @@ -373,10 +380,15 @@ void CoinRiftWidget::paintGL() eyePose[eye].Orientation.z, eyePose[eye].Orientation.w); - SbVec3f originalPosition(camera[eye]->position.getValue()); - camera[eye]->position.setValue(originalPosition - SbVec3f(eyeRenderDesc[eye].ViewAdjust.x, + SbVec3f riftPosition = SbVec3f(eyePose[eye].Position.x, + eyePose[eye].Position.y, + eyePose[eye].Position.z); + + //SbVec3f originalPosition(camera[eye]->position.getValue()); + + camera[eye]->position.setValue(basePosition - SbVec3f(eyeRenderDesc[eye].ViewAdjust.x, eyeRenderDesc[eye].ViewAdjust.y, - eyeRenderDesc[eye].ViewAdjust.z)); + eyeRenderDesc[eye].ViewAdjust.z) + riftPosition); #ifdef USE_SO_OFFSCREEN_RENDERER ovrGLTextureData *texData = reinterpret_cast(&eyeTexture[eye]); @@ -409,7 +421,7 @@ void CoinRiftWidget::paintGL() Q_ASSERT(!glGetError()); #endif - camera[eye]->position.setValue(originalPosition); + //camera[eye]->position.setValue(originalPosition); } From 069da655282ffa3b421c234324b9a30fd9193a11 Mon Sep 17 00:00:00 2001 From: jriegel Date: Mon, 15 Sep 2014 16:27:40 +0200 Subject: [PATCH 08/18] FreeCAD-VR: some fixes on FrameBuffer rendering portion --- src/Gui/View3DInventorRiftViewer.cpp | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/Gui/View3DInventorRiftViewer.cpp b/src/Gui/View3DInventorRiftViewer.cpp index c62bee398812..ef59bacf8562 100644 --- a/src/Gui/View3DInventorRiftViewer.cpp +++ b/src/Gui/View3DInventorRiftViewer.cpp @@ -195,8 +195,8 @@ CoinRiftWidget::CoinRiftWidget() : QGLWidget() eyeTexture[1].Header.TextureSize = eyeTexture[0].Header.TextureSize; #endif #ifdef USE_FRAMEBUFFER - eyes[0].TextureSize = recommenedTex0Size; - eyes[1].TextureSize = recommenedTex1Size; + eyeTexture[0].Header.TextureSize = recommenedTex0Size; + eyeTexture[1].Header.TextureSize = recommenedTex1Size; #endif eyeTexture[0].Header.RenderViewport.Pos.x = 0; eyeTexture[0].Header.RenderViewport.Pos.y = 0; @@ -290,7 +290,7 @@ void CoinRiftWidget::initializeGL() // Infer hardware capabilites. #ifdef USE_FRAMEBUFFER OVR::CAPI::GL::InitGLExtensions(); - if (OVR::CAPI::GL::glBindFramebufferEXT == NULL) { + if (OVR::CAPI::GL::glBindFramebuffer == NULL) { qDebug() << "No GL extensions found."; exit(4); } @@ -307,12 +307,13 @@ void CoinRiftWidget::initializeGL() OVR::CAPI::GL::glGenFramebuffers(1, &frameBufferID[eye]); OVR::CAPI::GL::glBindFramebuffer(GL_FRAMEBUFFER_EXT, frameBufferID[eye]); // Create the render buffer. - OVR::CAPI::GL::glGenRenderbuffers(1, &depthBufferID[eye]); - OVR::CAPI::GL::glBindRenderbuffer(GL_RENDERBUFFER_EXT, depthBufferID[eye]); - OVR::CAPI::GL::glRenderbufferStorage(GL_RENDERBUFFER_EXT, + // TODO: need to check for OpenGl 3 or higher and load the functions JR 2014 + /*OVR::CAPI::GL::*/glGenRenderbuffers(1, &depthBufferID[eye]); + /*OVR::CAPI::GL::*/glBindRenderbuffer(GL_RENDERBUFFER_EXT, depthBufferID[eye]); + /*OVR::CAPI::GL::*/glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, - eyes[eye].TextureSize.w, - eyes[eye].TextureSize.h); + eyeTexture[eye].Header.TextureSize.w, + eyeTexture[eye].Header.TextureSize.h); // Attach renderbuffer to framebuffer. OVR::CAPI::GL::glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, @@ -337,10 +338,10 @@ void CoinRiftWidget::initializeGL() Q_ASSERT(!glGetError()); #ifdef USE_FRAMEBUFFER // Attach texture to framebuffer color object. - OVR::CAPI::GL::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, + OVR::CAPI::GL::glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texData->TexId, 0); - if (OVR::CAPI::GL::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER) != + if (OVR::CAPI::GL::glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) qDebug() << "ERROR: FrameBuffer is not operational!"; #endif @@ -350,7 +351,7 @@ void CoinRiftWidget::initializeGL() #ifdef USE_FRAMEBUFFER // Continue rendering to the orgiginal frame buffer (likely 0, the onscreen buffer). - OVR::CAPI::GL::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, oldfb); + OVR::CAPI::GL::glBindFramebuffer(GL_FRAMEBUFFER_EXT, oldfb); #endif doneCurrent(); } @@ -410,14 +411,14 @@ void CoinRiftWidget::paintGL() GLint oldfb; glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &oldfb); // Set up framebuffer for rendering. - OVR::CAPI::GL::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frameBufferID[eye]); + OVR::CAPI::GL::glBindFramebuffer(GL_FRAMEBUFFER_EXT, frameBufferID[eye]); m_sceneManager->setSceneGraph(rootScene[eye]); // m_sceneManager->setCamera(camera[eye]); // SoSceneManager does this implicitly. m_sceneManager->render(); // Continue rendering to the orgiginal frame buffer (likely 0, the onscreen buffer). - OVR::CAPI::GL::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, oldfb); + OVR::CAPI::GL::glBindFramebuffer(GL_FRAMEBUFFER_EXT, oldfb); Q_ASSERT(!glGetError()); #endif From 0d2ce7073aeb7cdfd95feca4143c867f80676136 Mon Sep 17 00:00:00 2001 From: jriegel Date: Mon, 15 Sep 2014 17:14:44 +0200 Subject: [PATCH 09/18] FreeCAD-VR: Separating FreeCAD and Coin/Rift stuff --- src/Gui/CMakeLists.txt | 4 + src/Gui/CoinRiftWidget.cpp | 469 +++++++++++++++++++++++++ src/Gui/CoinRiftWidget.h | 111 ++++++ src/Gui/View3DInventorRiftViewer.cpp | 493 ++------------------------- src/Gui/View3DInventorRiftViewer.h | 42 +++ 5 files changed, 653 insertions(+), 466 deletions(-) create mode 100644 src/Gui/CoinRiftWidget.cpp create mode 100644 src/Gui/CoinRiftWidget.h create mode 100644 src/Gui/View3DInventorRiftViewer.h diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index 4a4f6e235d04..722e875dd1f7 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -661,6 +661,7 @@ SET(View3D_CPP_SRCS View3DInventorExamples.cpp View3DInventorViewer.cpp View3DInventorRiftViewer.cpp + CoinRiftWidget.cpp View3DPy.cpp ) SET(View3D_SRCS @@ -675,6 +676,9 @@ SET(View3D_SRCS View3DInventorExamples.h View3DInventorViewer.h View3DPy.h + View3DInventorRiftViewer.h + CoinRiftWidget.h + ) SOURCE_GROUP("View3D" FILES ${View3D_SRCS}) diff --git a/src/Gui/CoinRiftWidget.cpp b/src/Gui/CoinRiftWidget.cpp new file mode 100644 index 000000000000..fa4602406978 --- /dev/null +++ b/src/Gui/CoinRiftWidget.cpp @@ -0,0 +1,469 @@ +/**************************************************************************\ +* Copyright (c) Bastiaan Veelo (Bastiaan a_t Veelo d_o_t net) +* All rights reserved. Contact me if the below is too restrictive for you. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* +* Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\**************************************************************************/ + +#include "PreCompiled.h" +#include "CoinRiftWidget.h" + +#if BUILD_VR + + + +#undef max + + + + +CoinRiftWidget::CoinRiftWidget() : QGLWidget() +{ + for (int eye = 0; eye < 2; eye++) { + reinterpret_cast(&eyeTexture[eye])->TexId = 0; +#ifdef USE_FRAMEBUFFER + frameBufferID[eye] = 0; + depthBufferID[eye] = 0; +#endif + } + + // OVR will do the swapping. + setAutoBufferSwap(false); + + hmd = ovrHmd_Create(0); + if (!hmd) { + qDebug() << "Could not find Rift device."; + throw; + } + + if (!ovrHmd_ConfigureTracking (hmd, ovrTrackingCap_Orientation | + ovrTrackingCap_MagYawCorrection | + ovrTrackingCap_Position, + ovrTrackingCap_Orientation | + ovrTrackingCap_MagYawCorrection | + ovrTrackingCap_Position + )) { // Capabilities we require. + qDebug() << "Could not start Rift motion sensor."; + throw; + } + + resize(hmd->Resolution.w, hmd->Resolution.h); + + // Configure stereo settings. + ovrSizei recommenedTex0Size = ovrHmd_GetFovTextureSize(hmd, ovrEye_Left, + hmd->DefaultEyeFov[0], 1.0f); + ovrSizei recommenedTex1Size = ovrHmd_GetFovTextureSize(hmd, ovrEye_Right, + hmd->DefaultEyeFov[1], 1.0f); + +#ifdef USE_SO_OFFSCREEN_RENDERER + renderer = new SoOffscreenRenderer(SbViewportRegion(std::max(recommenedTex0Size.w, recommenedTex0Size.w), + std::max(recommenedTex1Size.h, recommenedTex1Size.h))); + renderer->setComponents(SoOffscreenRenderer::RGB_TRANSPARENCY); + renderer->setBackgroundColor(SbColor(.0f, .0f, .8f)); +#endif +#ifdef USE_FRAMEBUFFER + m_sceneManager = new SoSceneManager(); + m_sceneManager->setViewportRegion(SbViewportRegion(std::max(recommenedTex0Size.w, recommenedTex0Size.w), + std::max(recommenedTex1Size.h, recommenedTex1Size.h))); + m_sceneManager->setBackgroundColor(SbColor(.0f, .0f, .8f)); +#endif + basePosition = SbVec3f(0.0f, 0.0f, 5.0f); + + scene = new SoSeparator(0); // Placeholder. + for (int eye = 0; eye < 2; eye++) { + rootScene[eye] = new SoSeparator(3); + rootScene[eye]->ref(); + camera[eye] = new SoFrustumCamera(); + camera[eye]->position.setValue(basePosition); + camera[eye]->focalDistance.setValue(5.0f); + camera[eye]->viewportMapping.setValue(SoCamera::LEAVE_ALONE); + rootScene[eye]->addChild(camera[eye]); + rootScene[eye]->addChild(new SoDirectionalLight()); // TODO Connect direction to camera. + rootScene[eye]->addChild(scene); + } + + // Populate ovrEyeDesc[2]. + eyeRenderDesc[0].Eye = ovrEye_Left; + eyeRenderDesc[1].Eye = ovrEye_Right; + eyeRenderDesc[0].Fov = hmd->DefaultEyeFov[0]; + eyeRenderDesc[1].Fov = hmd->DefaultEyeFov[1]; +#ifdef USE_SO_OFFSCREEN_RENDERER + eyeTexture[0].Header.TextureSize.w = renderer->getViewportRegion().getViewportSizePixels().getValue()[0]; + eyeTexture[0].Header.TextureSize.h = renderer->getViewportRegion().getViewportSizePixels().getValue()[1]; + eyeTexture[1].Header.TextureSize = eyeTexture[0].Header.TextureSize; +#endif +#ifdef USE_FRAMEBUFFER + eyeTexture[0].Header.TextureSize = recommenedTex0Size; + eyeTexture[1].Header.TextureSize = recommenedTex1Size; +#endif + eyeTexture[0].Header.RenderViewport.Pos.x = 0; + eyeTexture[0].Header.RenderViewport.Pos.y = 0; + eyeTexture[0].Header.RenderViewport.Size = eyeTexture[0].Header.TextureSize; + eyeTexture[1].Header.RenderViewport.Pos = eyeTexture[0].Header.RenderViewport.Pos; + eyeTexture[1].Header.RenderViewport.Size = eyeTexture[1].Header.TextureSize; + + const int backBufferMultisample = 0; // TODO This is a guess? + ovrGLConfig cfg; + cfg.OGL.Header.API = ovrRenderAPI_OpenGL; + cfg.OGL.Header.RTSize = hmd->Resolution; + cfg.OGL.Header.Multisample = backBufferMultisample; + cfg.OGL.Window = reinterpret_cast(winId()); + makeCurrent(); + //cfg.OGL.WglContext = wglGetCurrentContext(); // http://stackoverflow.com/questions/17532033/qglwidget-get-gl-contextes-for-windows + cfg.OGL.DC = wglGetCurrentDC(); + qDebug() << "Window:" << cfg.OGL.Window; + //qDebug() << "Context:" << cfg.OGL.WglContext; + qDebug() << "DC:" << cfg.OGL.DC; + + int DistortionCaps = 0; + DistortionCaps |= ovrDistortionCap_Chromatic; +// DistortionCaps |= ovrDistortionCap_TimeWarp; // Produces black screen... + DistortionCaps |= ovrDistortionCap_Vignette; + DistortionCaps |= ovrDistortionCap_HqDistortion; + + bool VSyncEnabled(false); // TODO This is a guess. + if (!ovrHmd_ConfigureRendering( hmd, + &cfg.Config, + /*(VSyncEnabled ? 0 : ovrHmdCap_NoVSync),*/ + DistortionCaps, + hmd->DefaultEyeFov,//eyes, + eyeRenderDesc)) { + qDebug() << "Could not configure OVR rendering."; + exit(3); + } + + for (int eye = 0; eye < 2; eye++) { + camera[eye]->aspectRatio.setValue((eyeRenderDesc[eye].Fov.LeftTan + eyeRenderDesc[eye].Fov.RightTan) / + (eyeRenderDesc[eye].Fov.UpTan + eyeRenderDesc[eye].Fov.DownTan)); + camera[eye]->nearDistance.setValue(1.0f); + camera[eye]->farDistance.setValue(100.0f); + camera[eye]->left.setValue(-eyeRenderDesc[eye].Fov.LeftTan); + camera[eye]->right.setValue(eyeRenderDesc[eye].Fov.RightTan); + camera[eye]->top.setValue(eyeRenderDesc[eye].Fov.UpTan); + camera[eye]->bottom.setValue(-eyeRenderDesc[eye].Fov.DownTan); + } +} + + +CoinRiftWidget::~CoinRiftWidget() +{ +#ifdef USE_SO_OFFSCREEN_RENDERER + delete renderer; +#endif + for (int eye = 0; eye < 2; eye++) { + rootScene[eye]->unref(); + ovrGLTextureData *texData = reinterpret_cast(&eyeTexture[eye]); + if (texData->TexId) { + glDeleteTextures(1, &texData->TexId); + texData->TexId = 0; + } +#ifdef USE_FRAMEBUFFER + if (frameBufferID[eye] != 0) { +// OVR::CAPI::GL::glDeleteFramebuffersExt(1, &frameBufferID[eye]); // TODO + frameBufferID[eye] = 0; + } + if (depthBufferID[eye] != 0) { +// OVR::CAPI::GL::glDeleteRenderbuffersExt(1, &depthBufferID[eye]); // TODO + depthBufferID[eye] = 0; + } +#endif + } + scene = 0; + //ovrHmd_StopSensor(hmd); + ovrHmd_Destroy(hmd); +} + + +void CoinRiftWidget::setSceneGraph(SoNode *sceneGraph) +{ + rootScene[0]->replaceChild(scene, sceneGraph); + rootScene[1]->replaceChild(scene, sceneGraph); + scene = sceneGraph; +} + + +void CoinRiftWidget::resizeGL(int width, int height) { + int side = qMin(width, height); + glViewport((width - side) / 2, (height - side) / 2, side, side); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(-1.0, 1.0, -1.0, 1.0, 0.0, 1000.0); + glMatrixMode(GL_MODELVIEW); +} + +void CoinRiftWidget::initializeGL() +{ + makeCurrent(); + // Infer hardware capabilites. +#ifdef USE_FRAMEBUFFER + OVR::CAPI::GL::InitGLExtensions(); + if (OVR::CAPI::GL::glBindFramebuffer == NULL) { + qDebug() << "No GL extensions found."; + exit(4); + } + + // Store old framebuffer. + GLint oldfb; + glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &oldfb); +#endif + + // Create rendering target textures. + glEnable(GL_TEXTURE_2D); + for (int eye = 0; eye < 2; eye++) { +#ifdef USE_FRAMEBUFFER + OVR::CAPI::GL::glGenFramebuffers(1, &frameBufferID[eye]); + OVR::CAPI::GL::glBindFramebuffer(GL_FRAMEBUFFER_EXT, frameBufferID[eye]); + // Create the render buffer. + // TODO: need to check for OpenGl 3 or higher and load the functions JR 2014 + /*OVR::CAPI::GL::*/glGenRenderbuffers(1, &depthBufferID[eye]); + /*OVR::CAPI::GL::*/glBindRenderbuffer(GL_RENDERBUFFER_EXT, depthBufferID[eye]); + /*OVR::CAPI::GL::*/glRenderbufferStorage(GL_RENDERBUFFER_EXT, + GL_DEPTH_COMPONENT16, + eyeTexture[eye].Header.TextureSize.w, + eyeTexture[eye].Header.TextureSize.h); + // Attach renderbuffer to framebuffer. + OVR::CAPI::GL::glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, + GL_DEPTH_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, + depthBufferID[eye]); +#endif + ovrGLTextureData *texData = reinterpret_cast(&eyeTexture[eye]); + texData->Header.API = ovrRenderAPI_OpenGL; + texData->Header.TextureSize = eyeTexture[eye].Header.TextureSize; + texData->Header.RenderViewport = eyeTexture[eye].Header.RenderViewport; + glGenTextures(1, &texData->TexId); + glBindTexture(GL_TEXTURE_2D, texData->TexId); + Q_ASSERT(!glGetError()); + // Allocate storage for the texture. + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, eyeTexture[eye].Header.TextureSize.w, eyeTexture[eye].Header.TextureSize.h, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + Q_ASSERT(!glGetError()); +#ifdef USE_FRAMEBUFFER + // Attach texture to framebuffer color object. + OVR::CAPI::GL::glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_2D, texData->TexId, 0); + if (OVR::CAPI::GL::glCheckFramebufferStatus(GL_FRAMEBUFFER) != + GL_FRAMEBUFFER_COMPLETE) + qDebug() << "ERROR: FrameBuffer is not operational!"; +#endif + } + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); + +#ifdef USE_FRAMEBUFFER + // Continue rendering to the orgiginal frame buffer (likely 0, the onscreen buffer). + OVR::CAPI::GL::glBindFramebuffer(GL_FRAMEBUFFER_EXT, oldfb); +#endif + doneCurrent(); +} + + +void CoinRiftWidget::paintGL() +{ + const int ms(1000 / 75 /*fps*/); + QTimer::singleShot(ms, this, SLOT(updateGL())); + + // handling the sfety warning + handlingSafetyWarning(); + + makeCurrent(); + + ovrPosef eyePose[2]; + + glEnable(GL_TEXTURE_2D); + + ovrFrameTiming hmdFrameTiming = ovrHmd_BeginFrame(hmd, 0); + for (int eyeIndex = 0; eyeIndex < ovrEye_Count; eyeIndex++) { + ovrEyeType eye = hmd->EyeRenderOrder[eyeIndex]; + eyePose[eye] = ovrHmd_GetEyePose(hmd, eye); + + camera[eye]->orientation.setValue(eyePose[eye].Orientation.x, + eyePose[eye].Orientation.y, + eyePose[eye].Orientation.z, + eyePose[eye].Orientation.w); + + SbVec3f riftPosition = SbVec3f(eyePose[eye].Position.x, + eyePose[eye].Position.y, + eyePose[eye].Position.z); + + //SbVec3f originalPosition(camera[eye]->position.getValue()); + + camera[eye]->position.setValue(basePosition - SbVec3f(eyeRenderDesc[eye].ViewAdjust.x, + eyeRenderDesc[eye].ViewAdjust.y, + eyeRenderDesc[eye].ViewAdjust.z) + riftPosition); + +#ifdef USE_SO_OFFSCREEN_RENDERER + ovrGLTextureData *texData = reinterpret_cast(&eyeTexture[eye]); + glBindTexture(GL_TEXTURE_2D, texData->TexId); + renderer->render(rootScene[eye]); + Q_ASSERT(!glGetError()); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + eyeTexture[eye].Header.TextureSize.w, + eyeTexture[eye].Header.TextureSize.h, + 0, GL_RGBA /*GL_BGRA*/, GL_UNSIGNED_BYTE, renderer->getBuffer()); + Q_ASSERT(!glGetError()); + glBindTexture(GL_TEXTURE_2D, 0); +#endif +#ifdef USE_FRAMEBUFFER + // Clear state pollution from OVR SDK. + glBindTexture(GL_TEXTURE_2D, 0); // You need this, at least if (hmdDesc.DistortionCaps & ovrDistortion_Chromatic). + OVR::CAPI::GL::glUseProgram(0); // You need this even more. + + GLint oldfb; + glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &oldfb); + // Set up framebuffer for rendering. + OVR::CAPI::GL::glBindFramebuffer(GL_FRAMEBUFFER_EXT, frameBufferID[eye]); + + m_sceneManager->setSceneGraph(rootScene[eye]); +// m_sceneManager->setCamera(camera[eye]); // SoSceneManager does this implicitly. + m_sceneManager->render(); + + // Continue rendering to the orgiginal frame buffer (likely 0, the onscreen buffer). + OVR::CAPI::GL::glBindFramebuffer(GL_FRAMEBUFFER_EXT, oldfb); + Q_ASSERT(!glGetError()); +#endif + + //camera[eye]->position.setValue(originalPosition); + + } + + // Submit the texture for distortion. + ovrHmd_EndFrame(hmd, eyePose, eyeTexture); + + // Swap buffers. + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + //ovrHmd_EndFrame(hmd); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glClearDepth(1.0); + + doneCurrent(); +} + +void CoinRiftWidget::handlingSafetyWarning(void) +{ + // Health and Safety Warning display state. + ovrHSWDisplayState hswDisplayState; + ovrHmd_GetHSWDisplayState(hmd, &hswDisplayState); + if (hswDisplayState.Displayed) + { + // Dismiss the warning if the user pressed the appropriate key or if the user + // is tapping the side of the HMD. + // If the user has requested to dismiss the warning via keyboard or controller input... + //if (Util_GetAndResetHSWDismissedState()) + ovrHmd_DismissHSWDisplay(hmd); + //else + //{ + // // Detect a moderate tap on the side of the HMD. + // ovrTrackingState ts = ovrHmd_GetTrackingState(hmd, ovr_GetTimeInSeconds()); + // if (ts.StatusFlags & ovrStatus_OrientationTracked) + // { + // const OVR::Vector3f v(ts.RawSensorData.Accelerometer.x, + // ts.RawSensorData.Accelerometer.y, + // ts.RawSensorData.Accelerometer.z); + // // Arbitrary value and representing moderate tap on the side of the DK2 Rift. + // if (v.LengthSq() > 250.f) + // ovrHmd_DismissHSWDisplay(hmd); + // } + //} + } + +} + + +#ifdef BUILD_RIFT_TEST_MAIN + +int main(int argc, char *argv[]) +{ + SoDB::init(); + + QApplication app(argc, argv); + qAddPostRoutine(cleanup); + + // Moved here because of https://developer.oculusvr.com/forums/viewtopic.php?f=17&t=7915&p=108503#p108503 + // Init libovr. + if (!ovr_Initialize()) { + qDebug() << "Could not initialize Oculus SDK."; + exit(1); + } + + CoinRiftWidget window; + window.show(); + + // An example scene. + static const char * inlineSceneGraph[] = { + "#Inventor V2.1 ascii\n", + "\n", + "Separator {\n", + " Rotation { rotation 1 0 0 0.3 }\n", + " Cone { }\n", + " BaseColor { rgb 1 0 0 }\n", + " Scale { scaleFactor .7 .7 .7 }\n", + " Cube { }\n", + "\n", + " DrawStyle { style LINES }\n", + " ShapeHints { vertexOrdering COUNTERCLOCKWISE }\n", + " Coordinate3 {\n", + " point [\n", + " -2 -2 1.1, -2 -1 1.1, -2 1 1.1, -2 2 1.1,\n", + " -1 -2 1.1, -1 -1 1.1, -1 1 1.1, -1 2 1.1\n", + " 1 -2 1.1, 1 -1 1.1, 1 1 1.1, 1 2 1.1\n", + " 2 -2 1.1, 2 -1 1.1, 2 1 1.1, 2 2 1.1\n", + " ]\n", + " }\n", + "\n", + " Complexity { value 0.7 }\n", + " NurbsSurface {\n", + " numUControlPoints 4\n", + " numVControlPoints 4\n", + " uKnotVector [ 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0 ]\n", + " vKnotVector [ 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0 ]\n", + " }\n", + "}\n", + NULL + }; + + SoInput in; + in.setStringArray(inlineSceneGraph); + + window.setSceneGraph(SoDB::readAll(&in)); + + return app.exec(); +} + +#endif //BUILD_RIFT_TEST_MAIN + +#endif //BUILD_VR \ No newline at end of file diff --git a/src/Gui/CoinRiftWidget.h b/src/Gui/CoinRiftWidget.h new file mode 100644 index 000000000000..ace577be917a --- /dev/null +++ b/src/Gui/CoinRiftWidget.h @@ -0,0 +1,111 @@ +/**************************************************************************\ +* Copyright (c) Bastiaan Veelo (Bastiaan a_t Veelo d_o_t net) & Juergen Riegel (FreeCAD@juergen-riegel.net) +* All rights reserved. Contact me if the below is too restrictive for you. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* +* Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\**************************************************************************/ +#ifndef GUI_CoinRiftWidget +#define GUI_CoinRiftWidget + +#if BUILD_VR + +// defines which methode to use to render +#define USE_SO_OFFSCREEN_RENDERER +//#define USE_FRAMEBUFFER + +#ifdef USE_SO_OFFSCREEN_RENDERER +# ifdef USE_FRAMEBUFFER +# error "Mutually exclusive options defined." +# endif +#endif + +#include +#include +#include +#include +#include +#include +#include +#ifdef USE_SO_OFFSCREEN_RENDERER +# include +#endif +#ifdef USE_FRAMEBUFFER +# include +#endif +#include +#include +#include + +#include +#include +#include +//#include +#include <../Src/OVR_CAPI_GL.h> +#include <../Src/CAPI/GL/CAPI_GL_Util.h> // For framebuffer functions. + + + +class CoinRiftWidget : public QGLWidget +{ + ovrHmd hmd; + //ovrHmdDesc hmdDesc; + //ovrEyeType eyes[2]; + ovrEyeRenderDesc eyeRenderDesc[2]; + ovrTexture eyeTexture[2]; + +#ifdef USE_FRAMEBUFFER + GLuint frameBufferID[2], depthBufferID[2]; + // A SoSceneManager has a SoRenderManager to do the rendering -- should we not use SoRenderManager instead? + // We are probably not that interested in events. SoSceneManager::setSceneGraph() searches for the camera + // and sets it in SoRenderManager, but its is actually only used for built-in stereo rendering. We sould + // probably eliminate that search... + SoSceneManager *m_sceneManager; +#endif +#ifdef USE_SO_OFFSCREEN_RENDERER + SoOffscreenRenderer *renderer; +#endif + SoSeparator *rootScene[2]; + SoFrustumCamera *camera[2]; + SoNode *scene; +public: + explicit CoinRiftWidget(); + ~CoinRiftWidget(); + void setSceneGraph(SoNode *sceneGraph); +protected: + void handlingSafetyWarning(void); + void initializeGL(); + void paintGL(); + void resizeGL(int width, int height); + + SbVec3f basePosition; +}; + + +#endif //BUILD_VR + +#endif GUI_CoinRiftWidget \ No newline at end of file diff --git a/src/Gui/View3DInventorRiftViewer.cpp b/src/Gui/View3DInventorRiftViewer.cpp index ef59bacf8562..18971b9e7746 100644 --- a/src/Gui/View3DInventorRiftViewer.cpp +++ b/src/Gui/View3DInventorRiftViewer.cpp @@ -1,477 +1,38 @@ -/**************************************************************************\ -* Copyright (c) Bastiaan Veelo (Bastiaan a_t Veelo d_o_t net) -* All rights reserved. Contact me if the below is too restrictive for you. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are -* met: -* -* Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* -* Neither the name of the copyright holder nor the names of its -* contributors may be used to endorse or promote products derived from -* this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -\**************************************************************************/ +/*************************************************************************** + * Copyright (c) 2014 Juergen Riegel * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + #include "PreCompiled.h" #if BUILD_VR -#ifndef OCULUS_FOUND -# error "Build VR without the Oculus SDK makes no sense at all" -#endif - -#define USE_SO_OFFSCREEN_RENDERER -//#define USE_FRAMEBUFFER - -#ifdef USE_SO_OFFSCREEN_RENDERER -# ifdef USE_FRAMEBUFFER -# error "Mutually exclusive options defined." -# endif -#endif - -#include -#include -#include -#include -#include -#include -#include -#ifdef USE_SO_OFFSCREEN_RENDERER -# include -#endif -#ifdef USE_FRAMEBUFFER -# include -#endif -#include -#include -#include - -#include -#include -#include -//#include -#include <../Src/OVR_CAPI_GL.h> -#include <../Src/CAPI/GL/CAPI_GL_Util.h> // For framebuffer functions. - -#undef max - - -class CoinRiftWidget : public QGLWidget -{ - ovrHmd hmd; - //ovrHmdDesc hmdDesc; - //ovrEyeType eyes[2]; - ovrEyeRenderDesc eyeRenderDesc[2]; - ovrTexture eyeTexture[2]; - -#ifdef USE_FRAMEBUFFER - GLuint frameBufferID[2], depthBufferID[2]; - // A SoSceneManager has a SoRenderManager to do the rendering -- should we not use SoRenderManager instead? - // We are probably not that interested in events. SoSceneManager::setSceneGraph() searches for the camera - // and sets it in SoRenderManager, but its is actually only used for built-in stereo rendering. We sould - // probably eliminate that search... - SoSceneManager *m_sceneManager; -#endif -#ifdef USE_SO_OFFSCREEN_RENDERER - SoOffscreenRenderer *renderer; -#endif - SoSeparator *rootScene[2]; - SoFrustumCamera *camera[2]; - SoNode *scene; -public: - explicit CoinRiftWidget(); - ~CoinRiftWidget(); - void setSceneGraph(SoNode *sceneGraph); -protected: - void handlingSafetyWarning(void); - void initializeGL(); - void paintGL(); - void resizeGL(int width, int height) { - int side = qMin(width, height); - glViewport((width - side) / 2, (height - side) / 2, side, side); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(-1.0, 1.0, -1.0, 1.0, 0.0, 1000.0); - glMatrixMode(GL_MODELVIEW); - } - - SbVec3f basePosition; -}; - - -CoinRiftWidget::CoinRiftWidget() : QGLWidget() -{ - for (int eye = 0; eye < 2; eye++) { - reinterpret_cast(&eyeTexture[eye])->TexId = 0; -#ifdef USE_FRAMEBUFFER - frameBufferID[eye] = 0; - depthBufferID[eye] = 0; -#endif - } - - // OVR will do the swapping. - setAutoBufferSwap(false); - - hmd = ovrHmd_Create(0); - if (!hmd) { - qDebug() << "Could not find Rift device."; - throw; - } +#include "View3DInventorRiftViewer.h" - if (!ovrHmd_ConfigureTracking (hmd, ovrTrackingCap_Orientation | - ovrTrackingCap_MagYawCorrection | - ovrTrackingCap_Position, - ovrTrackingCap_Orientation | - ovrTrackingCap_MagYawCorrection | - ovrTrackingCap_Position - )) { // Capabilities we require. - qDebug() << "Could not start Rift motion sensor."; - throw; - } - - resize(hmd->Resolution.w, hmd->Resolution.h); - - // Configure stereo settings. - ovrSizei recommenedTex0Size = ovrHmd_GetFovTextureSize(hmd, ovrEye_Left, - hmd->DefaultEyeFov[0], 1.0f); - ovrSizei recommenedTex1Size = ovrHmd_GetFovTextureSize(hmd, ovrEye_Right, - hmd->DefaultEyeFov[1], 1.0f); - -#ifdef USE_SO_OFFSCREEN_RENDERER - renderer = new SoOffscreenRenderer(SbViewportRegion(std::max(recommenedTex0Size.w, recommenedTex0Size.w), - std::max(recommenedTex1Size.h, recommenedTex1Size.h))); - renderer->setComponents(SoOffscreenRenderer::RGB_TRANSPARENCY); - renderer->setBackgroundColor(SbColor(.0f, .0f, .8f)); -#endif -#ifdef USE_FRAMEBUFFER - m_sceneManager = new SoSceneManager(); - m_sceneManager->setViewportRegion(SbViewportRegion(std::max(recommenedTex0Size.w, recommenedTex0Size.w), - std::max(recommenedTex1Size.h, recommenedTex1Size.h))); - m_sceneManager->setBackgroundColor(SbColor(.0f, .0f, .8f)); -#endif - basePosition = SbVec3f(0.0f, 0.0f, 5.0f); - - scene = new SoSeparator(0); // Placeholder. - for (int eye = 0; eye < 2; eye++) { - rootScene[eye] = new SoSeparator(3); - rootScene[eye]->ref(); - camera[eye] = new SoFrustumCamera(); - camera[eye]->position.setValue(basePosition); - camera[eye]->focalDistance.setValue(5.0f); - camera[eye]->viewportMapping.setValue(SoCamera::LEAVE_ALONE); - rootScene[eye]->addChild(camera[eye]); - rootScene[eye]->addChild(new SoDirectionalLight()); // TODO Connect direction to camera. - rootScene[eye]->addChild(scene); - } - - // Populate ovrEyeDesc[2]. - eyeRenderDesc[0].Eye = ovrEye_Left; - eyeRenderDesc[1].Eye = ovrEye_Right; - eyeRenderDesc[0].Fov = hmd->DefaultEyeFov[0]; - eyeRenderDesc[1].Fov = hmd->DefaultEyeFov[1]; -#ifdef USE_SO_OFFSCREEN_RENDERER - eyeTexture[0].Header.TextureSize.w = renderer->getViewportRegion().getViewportSizePixels().getValue()[0]; - eyeTexture[0].Header.TextureSize.h = renderer->getViewportRegion().getViewportSizePixels().getValue()[1]; - eyeTexture[1].Header.TextureSize = eyeTexture[0].Header.TextureSize; -#endif -#ifdef USE_FRAMEBUFFER - eyeTexture[0].Header.TextureSize = recommenedTex0Size; - eyeTexture[1].Header.TextureSize = recommenedTex1Size; -#endif - eyeTexture[0].Header.RenderViewport.Pos.x = 0; - eyeTexture[0].Header.RenderViewport.Pos.y = 0; - eyeTexture[0].Header.RenderViewport.Size = eyeTexture[0].Header.TextureSize; - eyeTexture[1].Header.RenderViewport.Pos = eyeTexture[0].Header.RenderViewport.Pos; - eyeTexture[1].Header.RenderViewport.Size = eyeTexture[1].Header.TextureSize; - - const int backBufferMultisample = 0; // TODO This is a guess? - ovrGLConfig cfg; - cfg.OGL.Header.API = ovrRenderAPI_OpenGL; - cfg.OGL.Header.RTSize = hmd->Resolution; - cfg.OGL.Header.Multisample = backBufferMultisample; - cfg.OGL.Window = reinterpret_cast(winId()); - makeCurrent(); - //cfg.OGL.WglContext = wglGetCurrentContext(); // http://stackoverflow.com/questions/17532033/qglwidget-get-gl-contextes-for-windows - cfg.OGL.DC = wglGetCurrentDC(); - qDebug() << "Window:" << cfg.OGL.Window; - //qDebug() << "Context:" << cfg.OGL.WglContext; - qDebug() << "DC:" << cfg.OGL.DC; - - int DistortionCaps = 0; - DistortionCaps |= ovrDistortionCap_Chromatic; -// DistortionCaps |= ovrDistortionCap_TimeWarp; // Produces black screen... - DistortionCaps |= ovrDistortionCap_Vignette; - DistortionCaps |= ovrDistortionCap_HqDistortion; - - bool VSyncEnabled(false); // TODO This is a guess. - if (!ovrHmd_ConfigureRendering( hmd, - &cfg.Config, - /*(VSyncEnabled ? 0 : ovrHmdCap_NoVSync),*/ - DistortionCaps, - hmd->DefaultEyeFov,//eyes, - eyeRenderDesc)) { - qDebug() << "Could not configure OVR rendering."; - exit(3); - } - - for (int eye = 0; eye < 2; eye++) { - camera[eye]->aspectRatio.setValue((eyeRenderDesc[eye].Fov.LeftTan + eyeRenderDesc[eye].Fov.RightTan) / - (eyeRenderDesc[eye].Fov.UpTan + eyeRenderDesc[eye].Fov.DownTan)); - camera[eye]->nearDistance.setValue(1.0f); - camera[eye]->farDistance.setValue(100.0f); - camera[eye]->left.setValue(-eyeRenderDesc[eye].Fov.LeftTan); - camera[eye]->right.setValue(eyeRenderDesc[eye].Fov.RightTan); - camera[eye]->top.setValue(eyeRenderDesc[eye].Fov.UpTan); - camera[eye]->bottom.setValue(-eyeRenderDesc[eye].Fov.DownTan); - } -} - - -CoinRiftWidget::~CoinRiftWidget() -{ -#ifdef USE_SO_OFFSCREEN_RENDERER - delete renderer; -#endif - for (int eye = 0; eye < 2; eye++) { - rootScene[eye]->unref(); - ovrGLTextureData *texData = reinterpret_cast(&eyeTexture[eye]); - if (texData->TexId) { - glDeleteTextures(1, &texData->TexId); - texData->TexId = 0; - } -#ifdef USE_FRAMEBUFFER - if (frameBufferID[eye] != 0) { -// OVR::CAPI::GL::glDeleteFramebuffersExt(1, &frameBufferID[eye]); // TODO - frameBufferID[eye] = 0; - } - if (depthBufferID[eye] != 0) { -// OVR::CAPI::GL::glDeleteRenderbuffersExt(1, &depthBufferID[eye]); // TODO - depthBufferID[eye] = 0; - } -#endif - } - scene = 0; - //ovrHmd_StopSensor(hmd); - ovrHmd_Destroy(hmd); -} - - -void CoinRiftWidget::setSceneGraph(SoNode *sceneGraph) -{ - rootScene[0]->replaceChild(scene, sceneGraph); - rootScene[1]->replaceChild(scene, sceneGraph); - scene = sceneGraph; -} - - -void CoinRiftWidget::initializeGL() -{ - makeCurrent(); - // Infer hardware capabilites. -#ifdef USE_FRAMEBUFFER - OVR::CAPI::GL::InitGLExtensions(); - if (OVR::CAPI::GL::glBindFramebuffer == NULL) { - qDebug() << "No GL extensions found."; - exit(4); - } - - // Store old framebuffer. - GLint oldfb; - glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &oldfb); -#endif - - // Create rendering target textures. - glEnable(GL_TEXTURE_2D); - for (int eye = 0; eye < 2; eye++) { -#ifdef USE_FRAMEBUFFER - OVR::CAPI::GL::glGenFramebuffers(1, &frameBufferID[eye]); - OVR::CAPI::GL::glBindFramebuffer(GL_FRAMEBUFFER_EXT, frameBufferID[eye]); - // Create the render buffer. - // TODO: need to check for OpenGl 3 or higher and load the functions JR 2014 - /*OVR::CAPI::GL::*/glGenRenderbuffers(1, &depthBufferID[eye]); - /*OVR::CAPI::GL::*/glBindRenderbuffer(GL_RENDERBUFFER_EXT, depthBufferID[eye]); - /*OVR::CAPI::GL::*/glRenderbufferStorage(GL_RENDERBUFFER_EXT, - GL_DEPTH_COMPONENT16, - eyeTexture[eye].Header.TextureSize.w, - eyeTexture[eye].Header.TextureSize.h); - // Attach renderbuffer to framebuffer. - OVR::CAPI::GL::glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, - GL_DEPTH_ATTACHMENT_EXT, - GL_RENDERBUFFER_EXT, - depthBufferID[eye]); -#endif - ovrGLTextureData *texData = reinterpret_cast(&eyeTexture[eye]); - texData->Header.API = ovrRenderAPI_OpenGL; - texData->Header.TextureSize = eyeTexture[eye].Header.TextureSize; - texData->Header.RenderViewport = eyeTexture[eye].Header.RenderViewport; - glGenTextures(1, &texData->TexId); - glBindTexture(GL_TEXTURE_2D, texData->TexId); - Q_ASSERT(!glGetError()); - // Allocate storage for the texture. - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, eyeTexture[eye].Header.TextureSize.w, eyeTexture[eye].Header.TextureSize.h, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL); -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - Q_ASSERT(!glGetError()); -#ifdef USE_FRAMEBUFFER - // Attach texture to framebuffer color object. - OVR::CAPI::GL::glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, - GL_COLOR_ATTACHMENT0_EXT, - GL_TEXTURE_2D, texData->TexId, 0); - if (OVR::CAPI::GL::glCheckFramebufferStatus(GL_FRAMEBUFFER) != - GL_FRAMEBUFFER_COMPLETE) - qDebug() << "ERROR: FrameBuffer is not operational!"; -#endif - } - glBindTexture(GL_TEXTURE_2D, 0); - glDisable(GL_TEXTURE_2D); - -#ifdef USE_FRAMEBUFFER - // Continue rendering to the orgiginal frame buffer (likely 0, the onscreen buffer). - OVR::CAPI::GL::glBindFramebuffer(GL_FRAMEBUFFER_EXT, oldfb); -#endif - doneCurrent(); -} - - -void CoinRiftWidget::paintGL() -{ - const int ms(1000 / 75 /*fps*/); - QTimer::singleShot(ms, this, SLOT(updateGL())); - - // handling the sfety warning - handlingSafetyWarning(); - - makeCurrent(); - - ovrPosef eyePose[2]; - - glEnable(GL_TEXTURE_2D); - - ovrFrameTiming hmdFrameTiming = ovrHmd_BeginFrame(hmd, 0); - for (int eyeIndex = 0; eyeIndex < ovrEye_Count; eyeIndex++) { - ovrEyeType eye = hmd->EyeRenderOrder[eyeIndex]; - eyePose[eye] = ovrHmd_GetEyePose(hmd, eye); - - camera[eye]->orientation.setValue(eyePose[eye].Orientation.x, - eyePose[eye].Orientation.y, - eyePose[eye].Orientation.z, - eyePose[eye].Orientation.w); - - SbVec3f riftPosition = SbVec3f(eyePose[eye].Position.x, - eyePose[eye].Position.y, - eyePose[eye].Position.z); - - //SbVec3f originalPosition(camera[eye]->position.getValue()); - - camera[eye]->position.setValue(basePosition - SbVec3f(eyeRenderDesc[eye].ViewAdjust.x, - eyeRenderDesc[eye].ViewAdjust.y, - eyeRenderDesc[eye].ViewAdjust.z) + riftPosition); - -#ifdef USE_SO_OFFSCREEN_RENDERER - ovrGLTextureData *texData = reinterpret_cast(&eyeTexture[eye]); - glBindTexture(GL_TEXTURE_2D, texData->TexId); - renderer->render(rootScene[eye]); - Q_ASSERT(!glGetError()); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, - eyeTexture[eye].Header.TextureSize.w, - eyeTexture[eye].Header.TextureSize.h, - 0, GL_RGBA /*GL_BGRA*/, GL_UNSIGNED_BYTE, renderer->getBuffer()); - Q_ASSERT(!glGetError()); - glBindTexture(GL_TEXTURE_2D, 0); -#endif -#ifdef USE_FRAMEBUFFER - // Clear state pollution from OVR SDK. - glBindTexture(GL_TEXTURE_2D, 0); // You need this, at least if (hmdDesc.DistortionCaps & ovrDistortion_Chromatic). - OVR::CAPI::GL::glUseProgram(0); // You need this even more. - - GLint oldfb; - glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &oldfb); - // Set up framebuffer for rendering. - OVR::CAPI::GL::glBindFramebuffer(GL_FRAMEBUFFER_EXT, frameBufferID[eye]); - - m_sceneManager->setSceneGraph(rootScene[eye]); -// m_sceneManager->setCamera(camera[eye]); // SoSceneManager does this implicitly. - m_sceneManager->render(); - - // Continue rendering to the orgiginal frame buffer (likely 0, the onscreen buffer). - OVR::CAPI::GL::glBindFramebuffer(GL_FRAMEBUFFER_EXT, oldfb); - Q_ASSERT(!glGetError()); -#endif - - //camera[eye]->position.setValue(originalPosition); - - } - - // Submit the texture for distortion. - ovrHmd_EndFrame(hmd, eyePose, eyeTexture); - - // Swap buffers. - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - //ovrHmd_EndFrame(hmd); - glEnable(GL_CULL_FACE); - glEnable(GL_DEPTH_TEST); - glClearDepth(1.0); - - doneCurrent(); -} - -void CoinRiftWidget::handlingSafetyWarning(void) -{ - // Health and Safety Warning display state. - ovrHSWDisplayState hswDisplayState; - ovrHmd_GetHSWDisplayState(hmd, &hswDisplayState); - if (hswDisplayState.Displayed) - { - // Dismiss the warning if the user pressed the appropriate key or if the user - // is tapping the side of the HMD. - // If the user has requested to dismiss the warning via keyboard or controller input... - //if (Util_GetAndResetHSWDismissedState()) - ovrHmd_DismissHSWDisplay(hmd); - //else - //{ - // // Detect a moderate tap on the side of the HMD. - // ovrTrackingState ts = ovrHmd_GetTrackingState(hmd, ovr_GetTimeInSeconds()); - // if (ts.StatusFlags & ovrStatus_OrientationTracked) - // { - // const OVR::Vector3f v(ts.RawSensorData.Accelerometer.x, - // ts.RawSensorData.Accelerometer.y, - // ts.RawSensorData.Accelerometer.z); - // // Arbitrary value and representing moderate tap on the side of the DK2 Rift. - // if (v.LengthSq() > 250.f) - // ovrHmd_DismissHSWDisplay(hmd); - // } - //} - } - -} +#define new DEBUG_CLIENTBLOCK +using namespace Gui; - static CoinRiftWidget *window=0; +static View3DInventorRiftViewer *window=0; void oculusStop() @@ -504,7 +65,7 @@ int oculusStart(void) return 0; } - window = new CoinRiftWidget; + window = new View3DInventorRiftViewer; window->show(); // An example scene. diff --git a/src/Gui/View3DInventorRiftViewer.h b/src/Gui/View3DInventorRiftViewer.h new file mode 100644 index 000000000000..3f08b720c632 --- /dev/null +++ b/src/Gui/View3DInventorRiftViewer.h @@ -0,0 +1,42 @@ +/*************************************************************************** + * Copyright (c) 2014 Juergen Riegel * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef GUI_View3DInventorRiftViewer_H +#define GUI_View3DInventorRiftViewer_H + +#if BUILD_VR + +#include "CoinRiftWidget.h" + +namespace Gui { + +class View3DInventorRiftViewer : public CoinRiftWidget +{ + +}; + + +} //namespace Gui + +#endif //BUILD_VR + +#endif //GUI_View3DInventorRiftViewer_H \ No newline at end of file From 2a4626d27ad2c7e2a35e7001b65826a70fc2a6cb Mon Sep 17 00:00:00 2001 From: jriegel Date: Mon, 15 Sep 2014 19:50:55 +0200 Subject: [PATCH 10/18] FreeCAD-VR: Render the FreeCAD scene graph --- src/Gui/CoinRiftWidget.cpp | 5 +- src/Gui/CoinRiftWidget.h | 4 ++ src/Gui/View3DInventorRiftViewer.cpp | 77 ++++++++++++++++------------ src/Gui/View3DInventorViewer.cpp | 17 ++++-- 4 files changed, 64 insertions(+), 39 deletions(-) diff --git a/src/Gui/CoinRiftWidget.cpp b/src/Gui/CoinRiftWidget.cpp index fa4602406978..ac3c1d8ef224 100644 --- a/src/Gui/CoinRiftWidget.cpp +++ b/src/Gui/CoinRiftWidget.cpp @@ -84,7 +84,8 @@ CoinRiftWidget::CoinRiftWidget() : QGLWidget() renderer = new SoOffscreenRenderer(SbViewportRegion(std::max(recommenedTex0Size.w, recommenedTex0Size.w), std::max(recommenedTex1Size.h, recommenedTex1Size.h))); renderer->setComponents(SoOffscreenRenderer::RGB_TRANSPARENCY); - renderer->setBackgroundColor(SbColor(.0f, .0f, .8f)); + BackgroundColor = SbColor(.0f, .0f, .8f); + renderer->setBackgroundColor(BackgroundColor); #endif #ifdef USE_FRAMEBUFFER m_sceneManager = new SoSceneManager(); @@ -154,7 +155,7 @@ CoinRiftWidget::CoinRiftWidget() : QGLWidget() hmd->DefaultEyeFov,//eyes, eyeRenderDesc)) { qDebug() << "Could not configure OVR rendering."; - exit(3); + throw; } for (int eye = 0; eye < 2; eye++) { diff --git a/src/Gui/CoinRiftWidget.h b/src/Gui/CoinRiftWidget.h index ace577be917a..a96e9280256f 100644 --- a/src/Gui/CoinRiftWidget.h +++ b/src/Gui/CoinRiftWidget.h @@ -96,6 +96,9 @@ class CoinRiftWidget : public QGLWidget explicit CoinRiftWidget(); ~CoinRiftWidget(); void setSceneGraph(SoNode *sceneGraph); + void setBase(const SbVec3f &pos){basePosition=pos;} + void setBackgoundColor(const SbColor &Col){BackgroundColor = Col;} + protected: void handlingSafetyWarning(void); void initializeGL(); @@ -103,6 +106,7 @@ class CoinRiftWidget : public QGLWidget void resizeGL(int width, int height); SbVec3f basePosition; + SbColor BackgroundColor; }; diff --git a/src/Gui/View3DInventorRiftViewer.cpp b/src/Gui/View3DInventorRiftViewer.cpp index 18971b9e7746..06a2cc9f44ff 100644 --- a/src/Gui/View3DInventorRiftViewer.cpp +++ b/src/Gui/View3DInventorRiftViewer.cpp @@ -34,40 +34,9 @@ using namespace Gui; static View3DInventorRiftViewer *window=0; - -void oculusStop() -{ - //SoDB::finish(); - if(window){ - delete window; - window = 0; - } - - ovr_Shutdown(); -} - -bool oculusUp(void) +void oculusSetTestScene(View3DInventorRiftViewer *window) { - return window!=0; -} - -int oculusStart(void) -{ - //SoDB::init(); - - //QApplication app(argc, argv); - //qAddPostRoutine(cleanup); - - // Moved here because of https://developer.oculusvr.com/forums/viewtopic.php?f=17&t=7915&p=108503#p108503 - // Init libovr. - if (!ovr_Initialize()) { - qDebug() << "Could not initialize Oculus SDK."; - return 0; - } - - window = new View3DInventorRiftViewer; - window->show(); - + assert(window); // An example scene. static const char * inlineSceneGraph[] = { "#Inventor V2.1 ascii\n", @@ -105,9 +74,49 @@ int oculusStart(void) in.setStringArray(inlineSceneGraph); window->setSceneGraph(SoDB::readAll(&in)); +} - return 1; + +void oculusStop() +{ + //SoDB::finish(); + if(window){ + delete window; + window = 0; + } + + ovr_Shutdown(); +} + +bool oculusUp(void) +{ + return window!=0; +} + +View3DInventorRiftViewer* oculusStart(void) +{ + //SoDB::init(); + + //QApplication app(argc, argv); + //qAddPostRoutine(cleanup); + + // Moved here because of https://developer.oculusvr.com/forums/viewtopic.php?f=17&t=7915&p=108503#p108503 + // Init libovr. + if (!ovr_Initialize()) { + qDebug() << "Could not initialize Oculus SDK."; + return 0; + } + if(window) + return window; + + window = new View3DInventorRiftViewer; + window->show(); + + + return window; //return app.exec(); } + + #endif //BUILD_VR \ No newline at end of file diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index 8f78ea210188..1a98287ed4a8 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -103,6 +103,7 @@ #include "SoFCInteractiveElement.h" #include "SoFCBoundingBox.h" #include "SoAxisCrossKit.h" +#include "View3DInventorRiftViewer.h" #include "Selection.h" #include "SoFCSelectionAction.h" @@ -1637,9 +1638,10 @@ void View3DInventorViewer::animatedViewAll(int steps, int ms) } #if BUILD_VR -extern int oculusStart(void); +extern View3DInventorRiftViewer* oculusStart(void); extern bool oculusUp (void); extern void oculusStop (void); +void oculusSetTestScene(View3DInventorRiftViewer *window); #endif void View3DInventorViewer::viewVR(void) @@ -1647,8 +1649,17 @@ void View3DInventorViewer::viewVR(void) #if BUILD_VR if(oculusUp()) oculusStop(); - else - oculusStart(); + else{ +#if 0 + // start and load the simple test scene: + oculusSetTestScene(oculusStart()); +#else + View3DInventorRiftViewer* riftWin = oculusStart(); + riftWin->setSceneGraph(pcViewProviderRoot); + +#endif + + } #endif } From 0d6ccb76543508da575f0a67000384a36e76aa83 Mon Sep 17 00:00:00 2001 From: jriegel Date: Tue, 16 Sep 2014 18:14:42 +0200 Subject: [PATCH 11/18] FreeCAD-VR: Some fixes --- src/Gui/CoinRiftWidget.cpp | 6 ++++++ src/Gui/CoinRiftWidget.h | 3 ++- src/Gui/View3DInventorViewer.cpp | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Gui/CoinRiftWidget.cpp b/src/Gui/CoinRiftWidget.cpp index ac3c1d8ef224..0a9e894de8bc 100644 --- a/src/Gui/CoinRiftWidget.cpp +++ b/src/Gui/CoinRiftWidget.cpp @@ -33,6 +33,8 @@ #include "PreCompiled.h" #include "CoinRiftWidget.h" +#include + #if BUILD_VR @@ -319,6 +321,10 @@ void CoinRiftWidget::paintGL() eyePose[eye].Position.y, eyePose[eye].Position.z); + //Base::Console().Log("Pos: (%d) %f, %f, %f \n",eye, eyePose[eye].Position.x, + // eyePose[eye].Position.y, + // eyePose[eye].Position.z); + //SbVec3f originalPosition(camera[eye]->position.getValue()); camera[eye]->position.setValue(basePosition - SbVec3f(eyeRenderDesc[eye].ViewAdjust.x, diff --git a/src/Gui/CoinRiftWidget.h b/src/Gui/CoinRiftWidget.h index a96e9280256f..bb348c40e78f 100644 --- a/src/Gui/CoinRiftWidget.h +++ b/src/Gui/CoinRiftWidget.h @@ -99,13 +99,14 @@ class CoinRiftWidget : public QGLWidget void setBase(const SbVec3f &pos){basePosition=pos;} void setBackgoundColor(const SbColor &Col){BackgroundColor = Col;} + SbVec3f basePosition; + protected: void handlingSafetyWarning(void); void initializeGL(); void paintGL(); void resizeGL(int width, int height); - SbVec3f basePosition; SbColor BackgroundColor; }; diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index 1a98287ed4a8..82df6e8b37ab 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -1650,7 +1650,7 @@ void View3DInventorViewer::viewVR(void) if(oculusUp()) oculusStop(); else{ -#if 0 +#if 1 // start and load the simple test scene: oculusSetTestScene(oculusStart()); #else From 1c741b6e0d87e23fcd7ae5f40fac62c8c714de92 Mon Sep 17 00:00:00 2001 From: jriegel Date: Wed, 17 Sep 2014 13:49:44 +0200 Subject: [PATCH 12/18] FreeCAD-VR: Remove Tabs and add orientation for viewer position --- src/Gui/CoinRiftWidget.cpp | 117 +++++++++++++++++++------------------ src/Gui/CoinRiftWidget.h | 13 +++-- 2 files changed, 67 insertions(+), 63 deletions(-) diff --git a/src/Gui/CoinRiftWidget.cpp b/src/Gui/CoinRiftWidget.cpp index 0a9e894de8bc..428d88d1b67a 100644 --- a/src/Gui/CoinRiftWidget.cpp +++ b/src/Gui/CoinRiftWidget.cpp @@ -63,13 +63,13 @@ CoinRiftWidget::CoinRiftWidget() : QGLWidget() throw; } - if (!ovrHmd_ConfigureTracking (hmd, ovrTrackingCap_Orientation | - ovrTrackingCap_MagYawCorrection | - ovrTrackingCap_Position, - ovrTrackingCap_Orientation | - ovrTrackingCap_MagYawCorrection | - ovrTrackingCap_Position - )) { // Capabilities we require. + if (!ovrHmd_ConfigureTracking (hmd, ovrTrackingCap_Orientation | + ovrTrackingCap_MagYawCorrection | + ovrTrackingCap_Position, + ovrTrackingCap_Orientation | + ovrTrackingCap_MagYawCorrection | + ovrTrackingCap_Position + )) { // Capabilities we require. qDebug() << "Could not start Rift motion sensor."; throw; } @@ -86,7 +86,7 @@ CoinRiftWidget::CoinRiftWidget() : QGLWidget() renderer = new SoOffscreenRenderer(SbViewportRegion(std::max(recommenedTex0Size.w, recommenedTex0Size.w), std::max(recommenedTex1Size.h, recommenedTex1Size.h))); renderer->setComponents(SoOffscreenRenderer::RGB_TRANSPARENCY); - BackgroundColor = SbColor(.0f, .0f, .8f); + BackgroundColor = SbColor(.0f, .0f, .8f); renderer->setBackgroundColor(BackgroundColor); #endif #ifdef USE_FRAMEBUFFER @@ -95,7 +95,7 @@ CoinRiftWidget::CoinRiftWidget() : QGLWidget() std::max(recommenedTex1Size.h, recommenedTex1Size.h))); m_sceneManager->setBackgroundColor(SbColor(.0f, .0f, .8f)); #endif - basePosition = SbVec3f(0.0f, 0.0f, 5.0f); + basePosition = SbVec3f(0.0f, 0.0f, 5.0f); scene = new SoSeparator(0); // Placeholder. for (int eye = 0; eye < 2; eye++) { @@ -151,11 +151,11 @@ CoinRiftWidget::CoinRiftWidget() : QGLWidget() bool VSyncEnabled(false); // TODO This is a guess. if (!ovrHmd_ConfigureRendering( hmd, - &cfg.Config, - /*(VSyncEnabled ? 0 : ovrHmdCap_NoVSync),*/ + &cfg.Config, + /*(VSyncEnabled ? 0 : ovrHmdCap_NoVSync),*/ DistortionCaps, - hmd->DefaultEyeFov,//eyes, - eyeRenderDesc)) { + hmd->DefaultEyeFov,//eyes, + eyeRenderDesc)) { qDebug() << "Could not configure OVR rendering."; throw; } @@ -243,7 +243,7 @@ void CoinRiftWidget::initializeGL() OVR::CAPI::GL::glGenFramebuffers(1, &frameBufferID[eye]); OVR::CAPI::GL::glBindFramebuffer(GL_FRAMEBUFFER_EXT, frameBufferID[eye]); // Create the render buffer. - // TODO: need to check for OpenGl 3 or higher and load the functions JR 2014 + // TODO: need to check for OpenGl 3 or higher and load the functions JR 2014 /*OVR::CAPI::GL::*/glGenRenderbuffers(1, &depthBufferID[eye]); /*OVR::CAPI::GL::*/glBindRenderbuffer(GL_RENDERBUFFER_EXT, depthBufferID[eye]); /*OVR::CAPI::GL::*/glRenderbufferStorage(GL_RENDERBUFFER_EXT, @@ -298,12 +298,12 @@ void CoinRiftWidget::paintGL() const int ms(1000 / 75 /*fps*/); QTimer::singleShot(ms, this, SLOT(updateGL())); - // handling the sfety warning - handlingSafetyWarning(); + // handling the sfety warning + handlingSafetyWarning(); makeCurrent(); - ovrPosef eyePose[2]; + ovrPosef eyePose[2]; glEnable(GL_TEXTURE_2D); @@ -312,18 +312,21 @@ void CoinRiftWidget::paintGL() ovrEyeType eye = hmd->EyeRenderOrder[eyeIndex]; eyePose[eye] = ovrHmd_GetEyePose(hmd, eye); - camera[eye]->orientation.setValue(eyePose[eye].Orientation.x, - eyePose[eye].Orientation.y, - eyePose[eye].Orientation.z, - eyePose[eye].Orientation.w); - SbVec3f riftPosition = SbVec3f(eyePose[eye].Position.x, - eyePose[eye].Position.y, - eyePose[eye].Position.z); + SbRotation riftOrientation( eyePose[eye].Orientation.x, + eyePose[eye].Orientation.y, + eyePose[eye].Orientation.z, + eyePose[eye].Orientation.w); - //Base::Console().Log("Pos: (%d) %f, %f, %f \n",eye, eyePose[eye].Position.x, - // eyePose[eye].Position.y, - // eyePose[eye].Position.z); + camera[eye]->orientation.setValue(riftOrientation); + + SbVec3f riftPosition = SbVec3f(eyePose[eye].Position.x, + eyePose[eye].Position.y, + eyePose[eye].Position.z); + + //Base::Console().Log("Pos: (%d) %f, %f, %f \n",eye, eyePose[eye].Position.x, + // eyePose[eye].Position.y, + // eyePose[eye].Position.z); //SbVec3f originalPosition(camera[eye]->position.getValue()); @@ -337,8 +340,8 @@ void CoinRiftWidget::paintGL() renderer->render(rootScene[eye]); Q_ASSERT(!glGetError()); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, - eyeTexture[eye].Header.TextureSize.w, - eyeTexture[eye].Header.TextureSize.h, + eyeTexture[eye].Header.TextureSize.w, + eyeTexture[eye].Header.TextureSize.h, 0, GL_RGBA /*GL_BGRA*/, GL_UNSIGNED_BYTE, renderer->getBuffer()); Q_ASSERT(!glGetError()); glBindTexture(GL_TEXTURE_2D, 0); @@ -366,8 +369,8 @@ void CoinRiftWidget::paintGL() } - // Submit the texture for distortion. - ovrHmd_EndFrame(hmd, eyePose, eyeTexture); + // Submit the texture for distortion. + ovrHmd_EndFrame(hmd, eyePose, eyeTexture); // Swap buffers. glDisable(GL_CULL_FACE); @@ -382,32 +385,32 @@ void CoinRiftWidget::paintGL() void CoinRiftWidget::handlingSafetyWarning(void) { - // Health and Safety Warning display state. - ovrHSWDisplayState hswDisplayState; - ovrHmd_GetHSWDisplayState(hmd, &hswDisplayState); - if (hswDisplayState.Displayed) - { - // Dismiss the warning if the user pressed the appropriate key or if the user - // is tapping the side of the HMD. - // If the user has requested to dismiss the warning via keyboard or controller input... - //if (Util_GetAndResetHSWDismissedState()) - ovrHmd_DismissHSWDisplay(hmd); - //else - //{ - // // Detect a moderate tap on the side of the HMD. - // ovrTrackingState ts = ovrHmd_GetTrackingState(hmd, ovr_GetTimeInSeconds()); - // if (ts.StatusFlags & ovrStatus_OrientationTracked) - // { - // const OVR::Vector3f v(ts.RawSensorData.Accelerometer.x, - // ts.RawSensorData.Accelerometer.y, - // ts.RawSensorData.Accelerometer.z); - // // Arbitrary value and representing moderate tap on the side of the DK2 Rift. - // if (v.LengthSq() > 250.f) - // ovrHmd_DismissHSWDisplay(hmd); - // } - //} - } - + // Health and Safety Warning display state. + ovrHSWDisplayState hswDisplayState; + ovrHmd_GetHSWDisplayState(hmd, &hswDisplayState); + if (hswDisplayState.Displayed) + { + // Dismiss the warning if the user pressed the appropriate key or if the user + // is tapping the side of the HMD. + // If the user has requested to dismiss the warning via keyboard or controller input... + //if (Util_GetAndResetHSWDismissedState()) + ovrHmd_DismissHSWDisplay(hmd); + //else + //{ + // // Detect a moderate tap on the side of the HMD. + // ovrTrackingState ts = ovrHmd_GetTrackingState(hmd, ovr_GetTimeInSeconds()); + // if (ts.StatusFlags & ovrStatus_OrientationTracked) + // { + // const OVR::Vector3f v(ts.RawSensorData.Accelerometer.x, + // ts.RawSensorData.Accelerometer.y, + // ts.RawSensorData.Accelerometer.z); + // // Arbitrary value and representing moderate tap on the side of the DK2 Rift. + // if (v.LengthSq() > 250.f) + // ovrHmd_DismissHSWDisplay(hmd); + // } + //} + } + } diff --git a/src/Gui/CoinRiftWidget.h b/src/Gui/CoinRiftWidget.h index bb348c40e78f..77016da954ba 100644 --- a/src/Gui/CoinRiftWidget.h +++ b/src/Gui/CoinRiftWidget.h @@ -95,19 +95,20 @@ class CoinRiftWidget : public QGLWidget public: explicit CoinRiftWidget(); ~CoinRiftWidget(); - void setSceneGraph(SoNode *sceneGraph); - void setBase(const SbVec3f &pos){basePosition=pos;} - void setBackgoundColor(const SbColor &Col){BackgroundColor = Col;} + virtual void setSceneGraph(SoNode *sceneGraph); + void setBase(const SbVec3f &pos){basePosition=pos;} + void setBackgoundColor(const SbColor &Col){BackgroundColor = Col;} - SbVec3f basePosition; + SbVec3f basePosition; + SbRotation baseOrientation; protected: - void handlingSafetyWarning(void); + void handlingSafetyWarning(void); void initializeGL(); void paintGL(); void resizeGL(int width, int height); - SbColor BackgroundColor; + SbColor BackgroundColor; }; From 4c7fb2d0f0d9687aa7ee5547c3a771b50d7ff253 Mon Sep 17 00:00:00 2001 From: jriegel Date: Wed, 17 Sep 2014 15:01:28 +0200 Subject: [PATCH 13/18] FreeCAD-VR: Upright position and remembering render window position --- src/Gui/View3DInventorRiftViewer.cpp | 73 ++++++++++++++++++++++++++++ src/Gui/View3DInventorRiftViewer.h | 15 +++++- src/Gui/View3DInventorViewer.cpp | 2 +- 3 files changed, 88 insertions(+), 2 deletions(-) diff --git a/src/Gui/View3DInventorRiftViewer.cpp b/src/Gui/View3DInventorRiftViewer.cpp index 06a2cc9f44ff..f4f647ba66a5 100644 --- a/src/Gui/View3DInventorRiftViewer.cpp +++ b/src/Gui/View3DInventorRiftViewer.cpp @@ -26,12 +26,85 @@ #if BUILD_VR +#include #include "View3DInventorRiftViewer.h" +#include #define new DEBUG_CLIENTBLOCK using namespace Gui; +View3DInventorRiftViewer::View3DInventorRiftViewer() : CoinRiftWidget() +{ + workplace = new SoGroup(); + translation = new SoTranslation ; + rotation = new SoRotationXYZ ; + rotation->axis.setValue(SoRotationXYZ::X); + rotation->angle.setValue(M_PI/4); + workplace->addChild(rotation); + + + scale = new SoScale ; + scale->scaleFactor.setValue(0.01f,0.01f,0.01f); // scale from mm to m as neede by the Rift + workplace->addChild(scale); + + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Oculus"); + + this->setGeometry( hGrp->GetInt("RenderWindowPosX",100) , + hGrp->GetInt("RenderWindowPosY",100) , + hGrp->GetInt("RenderWindowSizeW",1920) , + hGrp->GetInt("RenderWindowSizeH",1080) + ); + + +} + +//void saveWinPostion(void) +//{ +// +// +// +//} + +View3DInventorRiftViewer::~View3DInventorRiftViewer() +{ + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Oculus"); + + // remeber last postion on close + hGrp->SetInt("RenderWindowPosX",pos().x()); + hGrp->SetInt("RenderWindowPosY",pos().y()); + hGrp->SetInt("RenderWindowSizeW",size().width()); + hGrp->SetInt("RenderWindowSizeH",size().height()); + + Base::Console().Log("pos: %d %d size: %d %d \n",pos().x(),pos().y(), + size().width(),size().height()); +} + +void View3DInventorRiftViewer::setSceneGraph(SoNode *sceneGraph) +{ + + workplace->addChild(sceneGraph); + + CoinRiftWidget::setSceneGraph(workplace); +} + + + + +void View3DInventorRiftViewer::keyPressEvent(QKeyEvent *event) +{ + if ((event->key() == Qt::Key_Delete + || event->key() == Qt::Key_Backspace)) { + ; // TODO + } else { + CoinRiftWidget::keyPressEvent(event); + } +} + + + + +// static test code ================================================================================ static View3DInventorRiftViewer *window=0; void oculusSetTestScene(View3DInventorRiftViewer *window) diff --git a/src/Gui/View3DInventorRiftViewer.h b/src/Gui/View3DInventorRiftViewer.h index 3f08b720c632..6c33ec235bd0 100644 --- a/src/Gui/View3DInventorRiftViewer.h +++ b/src/Gui/View3DInventorRiftViewer.h @@ -31,7 +31,20 @@ namespace Gui { class View3DInventorRiftViewer : public CoinRiftWidget { - +public: + View3DInventorRiftViewer(); + ~View3DInventorRiftViewer(); + + virtual void setSceneGraph(SoNode *sceneGraph); + +protected: + SoGroup *workplace; + SoTranslation *translation; + SoRotationXYZ *rotation; + SoScale *scale; + +protected: + void keyPressEvent(QKeyEvent *); }; diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index 82df6e8b37ab..1a98287ed4a8 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -1650,7 +1650,7 @@ void View3DInventorViewer::viewVR(void) if(oculusUp()) oculusStop(); else{ -#if 1 +#if 0 // start and load the simple test scene: oculusSetTestScene(oculusStart()); #else From 9a19baa8f5831343269d73fc95990c7d7833a66a Mon Sep 17 00:00:00 2001 From: jriegel Date: Wed, 17 Sep 2014 18:35:11 +0200 Subject: [PATCH 14/18] FreeCAD-VR: Positional light and fix in camera positioning --- src/Gui/CoinRiftWidget.cpp | 61 +++++++++++++++++++++------- src/Gui/CoinRiftWidget.h | 3 +- src/Gui/View3DInventorRiftViewer.cpp | 55 ++++++++++++++++++++----- src/Gui/View3DInventorRiftViewer.h | 3 +- 4 files changed, 95 insertions(+), 27 deletions(-) diff --git a/src/Gui/CoinRiftWidget.cpp b/src/Gui/CoinRiftWidget.cpp index 428d88d1b67a..6b72ef511038 100644 --- a/src/Gui/CoinRiftWidget.cpp +++ b/src/Gui/CoinRiftWidget.cpp @@ -95,7 +95,24 @@ CoinRiftWidget::CoinRiftWidget() : QGLWidget() std::max(recommenedTex1Size.h, recommenedTex1Size.h))); m_sceneManager->setBackgroundColor(SbColor(.0f, .0f, .8f)); #endif - basePosition = SbVec3f(0.0f, 0.0f, 5.0f); + basePosition = SbVec3f(0.0f, 0.0f, -2.0f); + // light handling + SoGroup *lightGroup = new SoGroup; + + SoTranslation *lightTranslation1 = new SoTranslation; + lightTranslation1->translation.setValue(0,1,1); + lightGroup->addChild (lightTranslation1); + + SoDirectionalLight *light = new SoDirectionalLight(); + lightGroup->addChild (light); + + SoTranslation *lightTranslation2 = new SoTranslation; + lightTranslation2->translation.setValue(0,-1,-1); + lightGroup->addChild (lightTranslation2); + + + //translation->translation.setValue(0,-1,0); + //workplace->addChild(translation); scene = new SoSeparator(0); // Placeholder. for (int eye = 0; eye < 2; eye++) { @@ -106,7 +123,7 @@ CoinRiftWidget::CoinRiftWidget() : QGLWidget() camera[eye]->focalDistance.setValue(5.0f); camera[eye]->viewportMapping.setValue(SoCamera::LEAVE_ALONE); rootScene[eye]->addChild(camera[eye]); - rootScene[eye]->addChild(new SoDirectionalLight()); // TODO Connect direction to camera. + rootScene[eye]->addChild(lightGroup); // TODO Connect direction to camera. rootScene[eye]->addChild(scene); } @@ -159,16 +176,17 @@ CoinRiftWidget::CoinRiftWidget() : QGLWidget() qDebug() << "Could not configure OVR rendering."; throw; } + static const float nearPlane = 0.01; for (int eye = 0; eye < 2; eye++) { camera[eye]->aspectRatio.setValue((eyeRenderDesc[eye].Fov.LeftTan + eyeRenderDesc[eye].Fov.RightTan) / (eyeRenderDesc[eye].Fov.UpTan + eyeRenderDesc[eye].Fov.DownTan)); - camera[eye]->nearDistance.setValue(1.0f); - camera[eye]->farDistance.setValue(100.0f); - camera[eye]->left.setValue(-eyeRenderDesc[eye].Fov.LeftTan); - camera[eye]->right.setValue(eyeRenderDesc[eye].Fov.RightTan); - camera[eye]->top.setValue(eyeRenderDesc[eye].Fov.UpTan); - camera[eye]->bottom.setValue(-eyeRenderDesc[eye].Fov.DownTan); + camera[eye]->nearDistance.setValue(nearPlane); + camera[eye]->farDistance.setValue(10000.0f); + camera[eye]->left.setValue(-eyeRenderDesc[eye].Fov.LeftTan * nearPlane); + camera[eye]->right.setValue(eyeRenderDesc[eye].Fov.RightTan * nearPlane); + camera[eye]->top.setValue(eyeRenderDesc[eye].Fov.UpTan * nearPlane); + camera[eye]->bottom.setValue(-eyeRenderDesc[eye].Fov.DownTan * nearPlane); } } @@ -202,6 +220,13 @@ CoinRiftWidget::~CoinRiftWidget() } +void CoinRiftWidget::setBackgroundColor(const SbColor &Col) +{ + BackgroundColor = Col; + renderer->setBackgroundColor(BackgroundColor); +} + + void CoinRiftWidget::setSceneGraph(SoNode *sceneGraph) { rootScene[0]->replaceChild(scene, sceneGraph); @@ -324,15 +349,23 @@ void CoinRiftWidget::paintGL() eyePose[eye].Position.y, eyePose[eye].Position.z); - //Base::Console().Log("Pos: (%d) %f, %f, %f \n",eye, eyePose[eye].Position.x, - // eyePose[eye].Position.y, - // eyePose[eye].Position.z); //SbVec3f originalPosition(camera[eye]->position.getValue()); + SbVec3f viewAdjust(eyeRenderDesc[eye].ViewAdjust.x, + eyeRenderDesc[eye].ViewAdjust.y, + eyeRenderDesc[eye].ViewAdjust.z); + + riftOrientation.multVec(viewAdjust,viewAdjust); + + camera[eye]->position.setValue(basePosition - viewAdjust + riftPosition); + //camera[eye]->position.setValue(basePosition - riftPosition); - camera[eye]->position.setValue(basePosition - SbVec3f(eyeRenderDesc[eye].ViewAdjust.x, - eyeRenderDesc[eye].ViewAdjust.y, - eyeRenderDesc[eye].ViewAdjust.z) + riftPosition); + //Base::Console().Log("Eye(%d) Pos: %f, %f, %f ViewAdjust: %f, %f, %f \n",eye, eyePose[eye].Position.x, + // eyePose[eye].Position.y, + // eyePose[eye].Position.z, + // eyeRenderDesc[eye].ViewAdjust.x, + // eyeRenderDesc[eye].ViewAdjust.y, + // eyeRenderDesc[eye].ViewAdjust.z); #ifdef USE_SO_OFFSCREEN_RENDERER ovrGLTextureData *texData = reinterpret_cast(&eyeTexture[eye]); diff --git a/src/Gui/CoinRiftWidget.h b/src/Gui/CoinRiftWidget.h index 77016da954ba..343d58775980 100644 --- a/src/Gui/CoinRiftWidget.h +++ b/src/Gui/CoinRiftWidget.h @@ -97,7 +97,7 @@ class CoinRiftWidget : public QGLWidget ~CoinRiftWidget(); virtual void setSceneGraph(SoNode *sceneGraph); void setBase(const SbVec3f &pos){basePosition=pos;} - void setBackgoundColor(const SbColor &Col){BackgroundColor = Col;} + void setBackgroundColor(const SbColor &Col); SbVec3f basePosition; SbRotation baseOrientation; @@ -109,6 +109,7 @@ class CoinRiftWidget : public QGLWidget void resizeGL(int width, int height); SbColor BackgroundColor; + SoTranslation *lightTranslation; }; diff --git a/src/Gui/View3DInventorRiftViewer.cpp b/src/Gui/View3DInventorRiftViewer.cpp index f4f647ba66a5..15efbf901c82 100644 --- a/src/Gui/View3DInventorRiftViewer.cpp +++ b/src/Gui/View3DInventorRiftViewer.cpp @@ -37,15 +37,24 @@ using namespace Gui; View3DInventorRiftViewer::View3DInventorRiftViewer() : CoinRiftWidget() { workplace = new SoGroup(); - translation = new SoTranslation ; - rotation = new SoRotationXYZ ; - rotation->axis.setValue(SoRotationXYZ::X); - rotation->angle.setValue(M_PI/4); - workplace->addChild(rotation); + + //translation = new SoTranslation ; + //translation->translation.setValue(0,-1,0); + //workplace->addChild(translation); + + rotation1 = new SoRotationXYZ ; + rotation1->axis.setValue(SoRotationXYZ::X); + rotation1->angle.setValue(M_PI/2); + workplace->addChild(rotation1); + + rotation2 = new SoRotationXYZ ; + rotation2->axis.setValue(SoRotationXYZ::Z); + rotation2->angle.setValue(0); + workplace->addChild(rotation2); scale = new SoScale ; - scale->scaleFactor.setValue(0.01f,0.01f,0.01f); // scale from mm to m as neede by the Rift + scale->scaleFactor.setValue(0.001f,0.001f,0.001f); // scale from mm to m as neede by the Rift workplace->addChild(scale); ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Oculus"); @@ -56,7 +65,9 @@ View3DInventorRiftViewer::View3DInventorRiftViewer() : CoinRiftWidget() hGrp->GetInt("RenderWindowSizeH",1080) ); - + + setBackgroundColor(SbColor(51,51,101)); + basePosition = SbVec3f(0.0f, 0.5f, 0.5f); } //void saveWinPostion(void) @@ -93,10 +104,32 @@ void View3DInventorRiftViewer::setSceneGraph(SoNode *sceneGraph) void View3DInventorRiftViewer::keyPressEvent(QKeyEvent *event) { - if ((event->key() == Qt::Key_Delete - || event->key() == Qt::Key_Backspace)) { - ; // TODO + static const float increment = 0.02; // move two centimeter per key + static const float rotIncrement = M_PI/4; // move two 90° per key + + + if (event->key() == Qt::Key_Plus) { + scale->scaleFactor.setValue(scale->scaleFactor.getValue() * 2.0f) ; + } else if (event->key() == Qt::Key_Minus) { + scale->scaleFactor.setValue(scale->scaleFactor.getValue() * 0.2f) ; + } else if (event->key() == Qt::Key_S) { + basePosition += SbVec3f(0,0,increment) ; + } else if (event->key() == Qt::Key_W) { + basePosition += SbVec3f(0,0,-increment) ; + } else if (event->key() == Qt::Key_Up) { + basePosition += SbVec3f(0,-increment,0) ; + } else if (event->key() == Qt::Key_Down) { + basePosition += SbVec3f(0,increment,0) ; + } else if (event->key() == Qt::Key_Left) { + rotation2->angle.setValue( rotation2->angle.getValue() + rotIncrement); + } else if (event->key() == Qt::Key_Right) { + rotation2->angle.setValue( rotation2->angle.getValue() - rotIncrement); + } else if (event->key() == Qt::Key_A) { + basePosition += SbVec3f(-increment,0,0) ; + } else if (event->key() == Qt::Key_D) { + basePosition += SbVec3f(increment,0,0) ; } else { + CoinRiftWidget::keyPressEvent(event); } } @@ -156,9 +189,9 @@ void oculusStop() if(window){ delete window; window = 0; + ovr_Shutdown(); } - ovr_Shutdown(); } bool oculusUp(void) diff --git a/src/Gui/View3DInventorRiftViewer.h b/src/Gui/View3DInventorRiftViewer.h index 6c33ec235bd0..146684ab504d 100644 --- a/src/Gui/View3DInventorRiftViewer.h +++ b/src/Gui/View3DInventorRiftViewer.h @@ -40,7 +40,8 @@ class View3DInventorRiftViewer : public CoinRiftWidget protected: SoGroup *workplace; SoTranslation *translation; - SoRotationXYZ *rotation; + SoRotationXYZ *rotation1; + SoRotationXYZ *rotation2; SoScale *scale; protected: From b5c25543780994759c14e1a5e43574013120f1e2 Mon Sep 17 00:00:00 2001 From: jriegel Date: Wed, 17 Sep 2014 18:55:51 +0200 Subject: [PATCH 15/18] FreeCAD-VR: Proper light handling --- src/Gui/CoinRiftWidget.cpp | 27 ++++++++++----------------- src/Gui/View3DInventorRiftViewer.cpp | 2 +- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/src/Gui/CoinRiftWidget.cpp b/src/Gui/CoinRiftWidget.cpp index 6b72ef511038..0d23de72766b 100644 --- a/src/Gui/CoinRiftWidget.cpp +++ b/src/Gui/CoinRiftWidget.cpp @@ -96,34 +96,28 @@ CoinRiftWidget::CoinRiftWidget() : QGLWidget() m_sceneManager->setBackgroundColor(SbColor(.0f, .0f, .8f)); #endif basePosition = SbVec3f(0.0f, 0.0f, -2.0f); - // light handling - SoGroup *lightGroup = new SoGroup; - SoTranslation *lightTranslation1 = new SoTranslation; - lightTranslation1->translation.setValue(0,1,1); - lightGroup->addChild (lightTranslation1); - - SoDirectionalLight *light = new SoDirectionalLight(); - lightGroup->addChild (light); - - SoTranslation *lightTranslation2 = new SoTranslation; - lightTranslation2->translation.setValue(0,-1,-1); - lightGroup->addChild (lightTranslation2); + // light handling + SoDirectionalLight *light = new SoDirectionalLight(); + light->direction.setValue(1,-1,-1); + SoDirectionalLight *light2 = new SoDirectionalLight(); + light2->direction.setValue(-1,-1,-1); + light2->intensity.setValue(0.6); + light2->color.setValue(0.8,0.8,1); - //translation->translation.setValue(0,-1,0); - //workplace->addChild(translation); scene = new SoSeparator(0); // Placeholder. for (int eye = 0; eye < 2; eye++) { - rootScene[eye] = new SoSeparator(3); + rootScene[eye] = new SoSeparator(); rootScene[eye]->ref(); camera[eye] = new SoFrustumCamera(); camera[eye]->position.setValue(basePosition); camera[eye]->focalDistance.setValue(5.0f); camera[eye]->viewportMapping.setValue(SoCamera::LEAVE_ALONE); rootScene[eye]->addChild(camera[eye]); - rootScene[eye]->addChild(lightGroup); // TODO Connect direction to camera. + rootScene[eye]->addChild(light); + rootScene[eye]->addChild(light2); rootScene[eye]->addChild(scene); } @@ -358,7 +352,6 @@ void CoinRiftWidget::paintGL() riftOrientation.multVec(viewAdjust,viewAdjust); camera[eye]->position.setValue(basePosition - viewAdjust + riftPosition); - //camera[eye]->position.setValue(basePosition - riftPosition); //Base::Console().Log("Eye(%d) Pos: %f, %f, %f ViewAdjust: %f, %f, %f \n",eye, eyePose[eye].Position.x, // eyePose[eye].Position.y, diff --git a/src/Gui/View3DInventorRiftViewer.cpp b/src/Gui/View3DInventorRiftViewer.cpp index 15efbf901c82..b4857efffc1b 100644 --- a/src/Gui/View3DInventorRiftViewer.cpp +++ b/src/Gui/View3DInventorRiftViewer.cpp @@ -67,7 +67,7 @@ View3DInventorRiftViewer::View3DInventorRiftViewer() : CoinRiftWidget() setBackgroundColor(SbColor(51,51,101)); - basePosition = SbVec3f(0.0f, 0.5f, 0.5f); + basePosition = SbVec3f(0.0f, 0.5f, 0.8f); } //void saveWinPostion(void) From 719c6e9425b63a82d8d81b892186b0eef861f1f5 Mon Sep 17 00:00:00 2001 From: jriegel Date: Wed, 17 Sep 2014 19:13:48 +0200 Subject: [PATCH 16/18] FreeCAD-VR: fix Z direction --- src/Gui/View3DInventorRiftViewer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gui/View3DInventorRiftViewer.cpp b/src/Gui/View3DInventorRiftViewer.cpp index b4857efffc1b..5d86134119dd 100644 --- a/src/Gui/View3DInventorRiftViewer.cpp +++ b/src/Gui/View3DInventorRiftViewer.cpp @@ -44,7 +44,7 @@ View3DInventorRiftViewer::View3DInventorRiftViewer() : CoinRiftWidget() rotation1 = new SoRotationXYZ ; rotation1->axis.setValue(SoRotationXYZ::X); - rotation1->angle.setValue(M_PI/2); + rotation1->angle.setValue(-M_PI/2); workplace->addChild(rotation1); rotation2 = new SoRotationXYZ ; From a81308ab577852eccc0686a221b47c255f879f9c Mon Sep 17 00:00:00 2001 From: jriegel Date: Thu, 18 Sep 2014 10:25:28 +0200 Subject: [PATCH 17/18] FreeCAD-VR: Small cleanups --- src/Gui/CoinRiftWidget.cpp | 2 +- src/Gui/View3DInventorViewer.cpp | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/Gui/CoinRiftWidget.cpp b/src/Gui/CoinRiftWidget.cpp index 0d23de72766b..ba1b89ffd839 100644 --- a/src/Gui/CoinRiftWidget.cpp +++ b/src/Gui/CoinRiftWidget.cpp @@ -1,5 +1,5 @@ /**************************************************************************\ -* Copyright (c) Bastiaan Veelo (Bastiaan a_t Veelo d_o_t net) +* Copyright (c) Bastiaan Veelo (Bastiaan a_t Veelo d_o_t net) & Juergen Riegel (FreeCAD@juergen-riegel.net) * All rights reserved. Contact me if the below is too restrictive for you. * * Redistribution and use in source and binary forms, with or without diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index 1a98287ed4a8..be958c4cf2fc 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -1650,15 +1650,8 @@ void View3DInventorViewer::viewVR(void) if(oculusUp()) oculusStop(); else{ -#if 0 - // start and load the simple test scene: - oculusSetTestScene(oculusStart()); -#else View3DInventorRiftViewer* riftWin = oculusStart(); riftWin->setSceneGraph(pcViewProviderRoot); - -#endif - } #endif } From 3d00535d5770ee3e4de9514ad2564286f49a597d Mon Sep 17 00:00:00 2001 From: jriegel Date: Fri, 19 Sep 2014 11:03:35 +0200 Subject: [PATCH 18/18] FreeCAD-VR: Small fix for older compilers --- src/Gui/View3DInventor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gui/View3DInventor.cpp b/src/Gui/View3DInventor.cpp index 1d44f3b00a42..153cf340248a 100644 --- a/src/Gui/View3DInventor.cpp +++ b/src/Gui/View3DInventor.cpp @@ -736,7 +736,7 @@ bool View3DInventor::onHasMsg(const char* pMsg) const else if(strcmp("ViewVR",pMsg) == 0) #ifdef BUILD_VR return true; -#elif +#else return false; #endif else if(strcmp("ViewSelection",pMsg) == 0)