FreeCAD-VR: Separating FreeCAD and Coin/Rift stuff
This commit is contained in:
parent
069da65528
commit
0d2ce7073a
|
@ -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})
|
||||
|
||||
|
|
469
src/Gui/CoinRiftWidget.cpp
Normal file
469
src/Gui/CoinRiftWidget.cpp
Normal file
|
@ -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<ovrGLTextureData*>(&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<HWND>(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<ovrGLTextureData*>(&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<ovrGLTextureData*>(&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<ovrGLTextureData*>(&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
|
111
src/Gui/CoinRiftWidget.h
Normal file
111
src/Gui/CoinRiftWidget.h
Normal file
|
@ -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 <algorithm>
|
||||
#include <QApplication>
|
||||
#include <QGLWidget>
|
||||
#include <QTimer>
|
||||
#include <QDebug>
|
||||
#include <Inventor/SoDB.h>
|
||||
#include <Inventor/SoInput.h>
|
||||
#ifdef USE_SO_OFFSCREEN_RENDERER
|
||||
# include <Inventor/SoOffscreenRenderer.h>
|
||||
#endif
|
||||
#ifdef USE_FRAMEBUFFER
|
||||
# include <Inventor/SoSceneManager.h>
|
||||
#endif
|
||||
#include <Inventor/nodes/SoSeparator.h>
|
||||
#include <Inventor/nodes/SoFrustumCamera.h>
|
||||
#include <Inventor/nodes/SoDirectionalLight.h>
|
||||
|
||||
#include <OVR.h>
|
||||
#include <OVR_Kernel.h>
|
||||
#include <OVR_Version.h>
|
||||
//#include <OVR_CAPI_GL.h>
|
||||
#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
|
|
@ -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 <FreeCAD@juergen-riegel.net> *
|
||||
* *
|
||||
* 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
|
||||
#include "View3DInventorRiftViewer.h"
|
||||
|
||||
#define USE_SO_OFFSCREEN_RENDERER
|
||||
//#define USE_FRAMEBUFFER
|
||||
#define new DEBUG_CLIENTBLOCK
|
||||
|
||||
#ifdef USE_SO_OFFSCREEN_RENDERER
|
||||
# ifdef USE_FRAMEBUFFER
|
||||
# error "Mutually exclusive options defined."
|
||||
# endif
|
||||
#endif
|
||||
using namespace Gui;
|
||||
|
||||
#include <algorithm>
|
||||
#include <QApplication>
|
||||
#include <QGLWidget>
|
||||
#include <QTimer>
|
||||
#include <QDebug>
|
||||
#include <Inventor/SoDB.h>
|
||||
#include <Inventor/SoInput.h>
|
||||
#ifdef USE_SO_OFFSCREEN_RENDERER
|
||||
# include <Inventor/SoOffscreenRenderer.h>
|
||||
#endif
|
||||
#ifdef USE_FRAMEBUFFER
|
||||
# include <Inventor/SoSceneManager.h>
|
||||
#endif
|
||||
#include <Inventor/nodes/SoSeparator.h>
|
||||
#include <Inventor/nodes/SoFrustumCamera.h>
|
||||
#include <Inventor/nodes/SoDirectionalLight.h>
|
||||
|
||||
#include <OVR.h>
|
||||
#include <OVR_Kernel.h>
|
||||
#include <OVR_Version.h>
|
||||
//#include <OVR_CAPI_GL.h>
|
||||
#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<ovrGLTextureData*>(&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<HWND>(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<ovrGLTextureData*>(&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<ovrGLTextureData*>(&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<ovrGLTextureData*>(&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);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
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.
|
||||
|
|
42
src/Gui/View3DInventorRiftViewer.h
Normal file
42
src/Gui/View3DInventorRiftViewer.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2014 Juergen Riegel <FreeCAD@juergen-riegel.net> *
|
||||
* *
|
||||
* 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
|
Loading…
Reference in New Issue
Block a user