From f6142686671fc14ff3e29c3a150dfa02ee81cf7a Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sat, 6 Jun 2015 23:51:37 -0700 Subject: [PATCH 01/34] Moving windows to SDK 0.6 Working on SDK 0.6 for windows Working on SDK 0.6 for windows --- cmake/externals/LibOVR/CMakeLists.txt | 4 +- cmake/externals/oglplus/CMakeLists.txt | 10 +- cmake/macros/SetupHifiOpenGL.cmake | 43 ++ interface/src/Application.cpp | 14 +- interface/src/devices/OculusManager.cpp | 613 +++++++++++------------- interface/src/devices/OculusManager.h | 66 +-- libraries/render-utils/src/Model.cpp | 2 +- libraries/shared/CMakeLists.txt | 14 +- libraries/shared/src/OglplusHelpers.cpp | 322 +++++++++++++ libraries/shared/src/OglplusHelpers.h | 166 +++++++ 10 files changed, 851 insertions(+), 403 deletions(-) create mode 100644 cmake/macros/SetupHifiOpenGL.cmake create mode 100644 libraries/shared/src/OglplusHelpers.cpp create mode 100644 libraries/shared/src/OglplusHelpers.h diff --git a/cmake/externals/LibOVR/CMakeLists.txt b/cmake/externals/LibOVR/CMakeLists.txt index 2198ed378a..d491434b5f 100644 --- a/cmake/externals/LibOVR/CMakeLists.txt +++ b/cmake/externals/LibOVR/CMakeLists.txt @@ -9,8 +9,8 @@ if (WIN32) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://static.oculus.com/sdk-downloads/ovr_sdk_win_0.5.0.1.zip - URL_MD5 d3fc4c02db9be5ff08af4ef4c97b32f9 + URL http://static.oculus.com/sdk-downloads/0.6.0.0/1431634088/ovr_sdk_win_0.6.0.0.zip + URL_MD5 a3dfdab037a854fdcf7e6033fa8d7028 CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" diff --git a/cmake/externals/oglplus/CMakeLists.txt b/cmake/externals/oglplus/CMakeLists.txt index 1413edce34..13709c1fde 100644 --- a/cmake/externals/oglplus/CMakeLists.txt +++ b/cmake/externals/oglplus/CMakeLists.txt @@ -4,11 +4,11 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://softlayer-dal.dl.sourceforge.net/project/oglplus/oglplus-0.61.x/oglplus-0.61.0.zip - URL_MD5 bb55038c36c660d2b6c7be380414fa60 - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" + GIT_REPOSITORY https://github.com/matus-chochlik/oglplus.git + GIT_TAG 9660aaaf65c5a3f47e6c54827ae28ae1ec5c5deb + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" LOG_DOWNLOAD 1 ) diff --git a/cmake/macros/SetupHifiOpenGL.cmake b/cmake/macros/SetupHifiOpenGL.cmake new file mode 100644 index 0000000000..c62e43c27e --- /dev/null +++ b/cmake/macros/SetupHifiOpenGL.cmake @@ -0,0 +1,43 @@ + + +macro(SETUP_HIFI_OPENGL) + + if (APPLE) + + # link in required OS X frameworks and include the right GL headers + find_library(OpenGL OpenGL) + target_link_libraries(${TARGET_NAME} ${OpenGL}) + + elseif (WIN32) + + add_dependency_external_projects(glew) + find_package(GLEW REQUIRED) + target_include_directories(${TARGET_NAME} PUBLIC ${GLEW_INCLUDE_DIRS}) + target_link_libraries(${TARGET_NAME} ${GLEW_LIBRARIES} opengl32.lib) + + if (USE_NSIGHT) + # try to find the Nsight package and add it to the build if we find it + find_package(NSIGHT) + if (NSIGHT_FOUND) + include_directories(${NSIGHT_INCLUDE_DIRS}) + add_definitions(-DNSIGHT_FOUND) + target_link_libraries(${TARGET_NAME} "${NSIGHT_LIBRARIES}") + endif() + endif() + + elseif(ANDROID) + + target_link_libraries(${TARGET_NAME} "-lGLESv3" "-lEGL") + + else() + + find_package(OpenGL REQUIRED) + if (${OPENGL_INCLUDE_DIR}) + include_directories(SYSTEM "${OPENGL_INCLUDE_DIR}") + endif() + target_link_libraries(${TARGET_NAME} "${OPENGL_LIBRARY}") + target_include_directories(${TARGET_NAME} PUBLIC ${OPENGL_INCLUDE_DIR}) + + endif() + +endmacro() diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index dbdcaa122a..93f6217cb9 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1860,11 +1860,13 @@ void Application::setEnableVRMode(bool enableVRMode) { // attempt to reconnect the Oculus manager - it's possible this was a workaround // for the sixense crash OculusManager::disconnect(); + _glWidget->makeCurrent(); OculusManager::connect(); } OculusManager::recalibrate(); } else { OculusManager::abandonCalibration(); + OculusManager::disconnect(); _mirrorCamera.setHmdPosition(glm::vec3()); _mirrorCamera.setHmdRotation(glm::quat()); @@ -2102,12 +2104,12 @@ void Application::init() { _mirrorCamera.setMode(CAMERA_MODE_MIRROR); - OculusManager::connect(); - if (OculusManager::isConnected()) { - QMetaObject::invokeMethod(Menu::getInstance()->getActionForOption(MenuOption::Fullscreen), - "trigger", - Qt::QueuedConnection); - } + //OculusManager::connect(); + //if (OculusManager::isConnected()) { + // QMetaObject::invokeMethod(Menu::getInstance()->getActionForOption(MenuOption::Fullscreen), + // "trigger", + // Qt::QueuedConnection); + //} TV3DManager::connect(); if (TV3DManager::isConnected()) { diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 3ceb2fd079..12b8abeb66 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include #include @@ -34,7 +36,6 @@ #include "InterfaceLogging.h" #include "Application.h" -#include template void for_each_eye(Function function) { @@ -53,27 +54,132 @@ void for_each_eye(const ovrHmd & hmd, Function function) { } } -#ifdef OVR_CLIENT_DISTORTION -ProgramObject OculusManager::_program; -int OculusManager::_textureLocation; -int OculusManager::_eyeToSourceUVScaleLocation; -int OculusManager::_eyeToSourceUVOffsetLocation; -int OculusManager::_eyeRotationStartLocation; -int OculusManager::_eyeRotationEndLocation; -int OculusManager::_positionAttributeLocation; -int OculusManager::_colorAttributeLocation; -int OculusManager::_texCoord0AttributeLocation; -int OculusManager::_texCoord1AttributeLocation; -int OculusManager::_texCoord2AttributeLocation; -ovrVector2f OculusManager::_UVScaleOffset[ovrEye_Count][2]; -GLuint OculusManager::_vertices[ovrEye_Count] = { 0, 0 }; -GLuint OculusManager::_indices[ovrEye_Count] = { 0, 0 }; -GLsizei OculusManager::_meshSize[ovrEye_Count] = { 0, 0 }; -ovrFrameTiming OculusManager::_hmdFrameTiming; -bool OculusManager::_programInitialized = false; -#endif + +#ifdef Q_OS_WIN + +// A base class for FBO wrappers that need to use the Oculus C +// API to manage textures via ovrHmd_CreateSwapTextureSetGL, +// ovrHmd_CreateMirrorTextureGL, etc +template +struct RiftFramebufferWrapper : public FramebufferWrapper { + ovrHmd hmd; + RiftFramebufferWrapper(const ovrHmd & hmd) : hmd(hmd) { + color = 0; + depth = 0; + }; + + void Resize(const uvec2 & size) { + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, oglplus::GetName(fbo)); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + this->size = size; + initColor(); + initDone(); + } + +protected: + virtual void initDepth() override final { + } +}; + +// A wrapper for constructing and using a swap texture set, +// where each frame you draw to a texture via the FBO, +// then submit it and increment to the next texture. +// The Oculus SDK manages the creation and destruction of +// the textures +struct SwapFramebufferWrapper : public RiftFramebufferWrapper { + SwapFramebufferWrapper(const ovrHmd & hmd) + : RiftFramebufferWrapper(hmd) { + } + + ~SwapFramebufferWrapper() { + if (color) { + ovrHmd_DestroySwapTextureSet(hmd, color); + color = nullptr; + } + } + + void Increment() { + ++color->CurrentIndex; + color->CurrentIndex %= color->TextureCount; + } + +protected: + virtual void initColor() override { + if (color) { + ovrHmd_DestroySwapTextureSet(hmd, color); + color = nullptr; + } + + ovrResult result = ovrHmd_CreateSwapTextureSetGL(hmd, GL_RGBA, size.x, size.y, &color); + Q_ASSERT(OVR_SUCCESS(result)); + + for (int i = 0; i < color->TextureCount; ++i) { + ovrGLTexture& ovrTex = (ovrGLTexture&)color->Textures[i]; + glBindTexture(GL_TEXTURE_2D, ovrTex.OGL.TexId); + 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_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + glBindTexture(GL_TEXTURE_2D, 0); + } + + virtual void initDone() override { + } + + virtual void onBind(oglplus::Framebuffer::Target target) override { + ovrGLTexture& tex = (ovrGLTexture&)(color->Textures[color->CurrentIndex]); + glFramebufferTexture2D(toEnum(target), GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex.OGL.TexId, 0); + } + + virtual void onUnbind(oglplus::Framebuffer::Target target) override { + glFramebufferTexture2D(toEnum(target), GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + } +}; + + +// We use a FBO to wrap the mirror texture because it makes it easier to +// render to the screen via glBlitFramebuffer +struct MirrorFramebufferWrapper : public RiftFramebufferWrapper { + MirrorFramebufferWrapper(const ovrHmd & hmd) + : RiftFramebufferWrapper(hmd) { + } + + virtual ~MirrorFramebufferWrapper() { + if (color) { + ovrHmd_DestroyMirrorTexture(hmd, (ovrTexture*)color); + color = nullptr; + } + } + +private: + void initColor() override { + if (color) { + ovrHmd_DestroyMirrorTexture(hmd, (ovrTexture*)color); + color = nullptr; + } + ovrResult result = ovrHmd_CreateMirrorTextureGL(hmd, GL_RGBA, size.x, size.y, (ovrTexture**)&color); + Q_ASSERT(OVR_SUCCESS(result)); + } + + void initDone() override { + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, oglplus::GetName(fbo)); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color->OGL.TexId, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + } +}; + +SwapFramebufferWrapper* OculusManager::_swapFbo{ nullptr }; +MirrorFramebufferWrapper* OculusManager::_mirrorFbo{ nullptr }; +ovrLayerEyeFov OculusManager::_sceneLayer; + +#else ovrTexture OculusManager::_eyeTextures[ovrEye_Count]; + +#endif + bool OculusManager::_isConnected = false; ovrHmd OculusManager::_ovrHmd; ovrFovPort OculusManager::_eyeFov[ovrEye_Count]; @@ -104,39 +210,41 @@ bool OculusManager::_eyePerFrameMode = false; ovrEyeType OculusManager::_lastEyeRendered = ovrEye_Count; ovrSizei OculusManager::_recommendedTexSize = { 0, 0 }; float OculusManager::_offscreenRenderScale = 1.0; - - -void OculusManager::initSdk() { - ovr_Initialize(); - _ovrHmd = ovrHmd_Create(0); - if (!_ovrHmd) { - _ovrHmd = ovrHmd_CreateDebug(ovrHmd_DK2); - } -} - -void OculusManager::shutdownSdk() { - if (_ovrHmd) { - ovrHmd_Destroy(_ovrHmd); - _ovrHmd = nullptr; - ovr_Shutdown(); - } -} +ovrRecti OculusManager::_eyeViewports[ovrEye_Count]; void OculusManager::init() { -#ifdef OVR_DIRECT_MODE - initSdk(); -#endif } void OculusManager::deinit() { -#ifdef OVR_DIRECT_MODE - shutdownSdk(); -#endif } void OculusManager::connect() { -#ifndef OVR_DIRECT_MODE - initSdk(); + + ovrInitParams initParams; memset(&initParams, 0, sizeof(initParams)); +#ifdef DEBUG + //initParams.Flags |= ovrInit_Debug; +#endif + ovr_Initialize(&initParams); + +#ifdef Q_OS_WIN + + ovrResult res = ovrHmd_Create(0, &_ovrHmd); +#ifdef DEBUG + if (!OVR_SUCCESS(res)) { + res = ovrHmd_CreateDebug(ovrHmd_DK2, &_ovrHmd); + Q_ASSERT(OVR_SUCCESS(res)); + } +#endif + +#else + + _ovrHmd = ovrHmd_Create(0); +#ifdef DEBUG + if (!_ovrHmd) { + _ovrHmd = ovrHmd_CreateDebug(ovrHmd_DK2); + } +#endif + #endif _calibrationState = UNCALIBRATED; qCDebug(interfaceapp) << "Oculus SDK" << OVR_VERSION_STRING; @@ -150,6 +258,28 @@ void OculusManager::connect() { _eyeFov[eye] = _ovrHmd->DefaultEyeFov[eye]; }); + _recommendedTexSize = ovrHmd_GetFovTextureSize(_ovrHmd, ovrEye_Left, _eyeFov[ovrEye_Left], 1.0f); + _renderTargetSize = { _recommendedTexSize.w * 2, _recommendedTexSize.h }; + +#ifdef Q_OS_WIN + + _mirrorFbo = new MirrorFramebufferWrapper(_ovrHmd); + _swapFbo = new SwapFramebufferWrapper(_ovrHmd); + _swapFbo->Init(toGlm(_renderTargetSize)); + _sceneLayer.ColorTexture[0] = _swapFbo->color; + _sceneLayer.ColorTexture[1] = nullptr; + _sceneLayer.Viewport[0].Pos = { 0, 0 }; + _sceneLayer.Viewport[0].Size = { _swapFbo->size.x / 2, _swapFbo->size.y }; + _sceneLayer.Viewport[1].Pos = { _swapFbo->size.x / 2, 0 }; + _sceneLayer.Viewport[1].Size = { _swapFbo->size.x / 2, _swapFbo->size.y }; + _sceneLayer.Header.Type = ovrLayerType_EyeFov; + _sceneLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft; + for_each_eye([&](ovrEyeType eye) { + _eyeViewports[eye] = _sceneLayer.Viewport[eye]; + _sceneLayer.Fov[eye] = _eyeFov[eye]; + }); + +#else ovrGLConfig cfg; memset(&cfg, 0, sizeof(cfg)); cfg.OGL.Header.API = ovrRenderAPI_OpenGL; @@ -166,15 +296,19 @@ void OculusManager::connect() { assert(configResult); - _recommendedTexSize = ovrHmd_GetFovTextureSize(_ovrHmd, ovrEye_Left, _eyeFov[ovrEye_Left], 1.0f); - _renderTargetSize = { _recommendedTexSize.w * 2, _recommendedTexSize.h }; for_each_eye([&](ovrEyeType eye) { //Get texture size _eyeTextures[eye].Header.API = ovrRenderAPI_OpenGL; _eyeTextures[eye].Header.TextureSize = _renderTargetSize; _eyeTextures[eye].Header.RenderViewport.Pos = { 0, 0 }; + _eyeTextures[eye].Header.RenderViewport.Size = _renderTargetSize; + _eyeTextures[eye].Header.RenderViewport.Size.w /= 2; }); _eyeTextures[ovrEye_Right].Header.RenderViewport.Pos.x = _recommendedTexSize.w; + for_each_eye([&](ovrEyeType eye) { + _eyeViewports[eye] = _eyeTextures[eye].Header.RenderViewport; + }); +#endif ovrHmd_SetEnabledCaps(_ovrHmd, ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction); @@ -186,32 +320,6 @@ void OculusManager::connect() { _camera = new Camera; configureCamera(*_camera); // no need to use screen dimensions; they're ignored } -#ifdef OVR_CLIENT_DISTORTION - if (!_programInitialized) { - // Shader program - _programInitialized = true; - _program.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/oculus.vert"); - _program.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/oculus.frag"); - _program.link(); - - // Uniforms - _textureLocation = _program.uniformLocation("texture"); - _eyeToSourceUVScaleLocation = _program.uniformLocation("EyeToSourceUVScale"); - _eyeToSourceUVOffsetLocation = _program.uniformLocation("EyeToSourceUVOffset"); - _eyeRotationStartLocation = _program.uniformLocation("EyeRotationStart"); - _eyeRotationEndLocation = _program.uniformLocation("EyeRotationEnd"); - - // Attributes - _positionAttributeLocation = _program.attributeLocation("position"); - _colorAttributeLocation = _program.attributeLocation("color"); - _texCoord0AttributeLocation = _program.attributeLocation("texCoord0"); - _texCoord1AttributeLocation = _program.attributeLocation("texCoord1"); - _texCoord2AttributeLocation = _program.attributeLocation("texCoord2"); - } - - //Generate the distortion VBOs - generateDistortionMesh(); -#endif } else { _isConnected = false; @@ -223,27 +331,29 @@ void OculusManager::connect() { //Disconnects and deallocates the OR void OculusManager::disconnect() { if (_isConnected) { + +#ifdef Q_OS_WIN + if (_swapFbo) { + delete _swapFbo; + _swapFbo = nullptr; + } + + if (_mirrorFbo) { + delete _mirrorFbo; + _mirrorFbo = nullptr; + } +#endif + + if (_ovrHmd) { + ovrHmd_Destroy(_ovrHmd); + _ovrHmd = nullptr; + } + ovr_Shutdown(); + _isConnected = false; // Prepare to potentially have to dismiss the HSW again // if the user re-enables VR _hswDismissed = false; -#ifndef OVR_DIRECT_MODE - shutdownSdk(); -#endif - -#ifdef OVR_CLIENT_DISTORTION - //Free the distortion mesh data - for (int i = 0; i < ovrEye_Count; i++) { - if (_vertices[i] != 0) { - glDeleteBuffers(1, &(_vertices[i])); - _vertices[i] = 0; - } - if (_indices[i] != 0) { - glDeleteBuffers(1, &(_indices[i])); - _indices[i] = 0; - } - } -#endif } } @@ -363,64 +473,8 @@ void OculusManager::abandonCalibration() { } } -#ifdef OVR_CLIENT_DISTORTION -void OculusManager::generateDistortionMesh() { - - //Check if we already have the distortion mesh - if (_vertices[0] != 0) { - printf("WARNING: Tried to generate Oculus distortion mesh twice without freeing the VBOs."); - return; - } - - for (int eyeNum = 0; eyeNum < ovrEye_Count; eyeNum++) { - // Allocate and generate distortion mesh vertices - ovrDistortionMesh meshData; - ovrHmd_CreateDistortionMesh(_ovrHmd, _eyeRenderDesc[eyeNum].Eye, _eyeRenderDesc[eyeNum].Fov, _ovrHmd->DistortionCaps, &meshData); - - // Parse the vertex data and create a render ready vertex buffer - DistortionVertex* pVBVerts = new DistortionVertex[meshData.VertexCount]; - _meshSize[eyeNum] = meshData.IndexCount; - - // Convert the oculus vertex data to the DistortionVertex format. - DistortionVertex* v = pVBVerts; - ovrDistortionVertex* ov = meshData.pVertexData; - for (unsigned int vertNum = 0; vertNum < meshData.VertexCount; vertNum++) { - v->pos.x = ov->ScreenPosNDC.x; - v->pos.y = ov->ScreenPosNDC.y; - v->texR.x = ov->TanEyeAnglesR.x; - v->texR.y = ov->TanEyeAnglesR.y; - v->texG.x = ov->TanEyeAnglesG.x; - v->texG.y = ov->TanEyeAnglesG.y; - v->texB.x = ov->TanEyeAnglesB.x; - v->texB.y = ov->TanEyeAnglesB.y; - v->color.r = v->color.g = v->color.b = (GLubyte)(ov->VignetteFactor * 255.99f); - v->color.a = (GLubyte)(ov->TimeWarpFactor * 255.99f); - v++; - ov++; - } - - //vertices - glGenBuffers(1, &(_vertices[eyeNum])); - glBindBuffer(GL_ARRAY_BUFFER, _vertices[eyeNum]); - glBufferData(GL_ARRAY_BUFFER, sizeof(DistortionVertex) * meshData.VertexCount, pVBVerts, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - //indices - glGenBuffers(1, &(_indices[eyeNum])); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indices[eyeNum]); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short) * meshData.IndexCount, meshData.pIndexData, GL_STATIC_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - //Now that we have the VBOs we can get rid of the mesh data - delete [] pVBVerts; - ovrHmd_DestroyDistortionMesh(&meshData); - } - -} -#endif - bool OculusManager::isConnected() { - return _isConnected && Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode); + return _isConnected; } //Begins the frame timing for oculus prediction purposes @@ -428,10 +482,6 @@ void OculusManager::beginFrameTiming() { if (_frameTimingActive) { printf("WARNING: Called OculusManager::beginFrameTiming() twice in a row, need to call OculusManager::endFrameTiming()."); } - -#ifdef OVR_CLIENT_DISTORTION - _hmdFrameTiming = ovrHmd_BeginFrameTiming(_ovrHmd, _frameIndex); -#endif _frameTimingActive = true; } @@ -441,9 +491,6 @@ bool OculusManager::allowSwap() { //Ends frame timing void OculusManager::endFrameTiming() { -#ifdef OVR_CLIENT_DISTORTION - ovrHmd_EndFrameTiming(_ovrHmd); -#endif _frameIndex++; _frameTimingActive = false; } @@ -494,19 +541,20 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati timerActive = false; } #endif - -#ifdef OVR_DIRECT_MODE - static bool attached = false; - if (!attached) { - attached = true; - void * nativeWindowHandle = (void*)(size_t)glCanvas->effectiveWinId(); - if (nullptr != nativeWindowHandle) { - ovrHmd_AttachToWindow(_ovrHmd, nativeWindowHandle, nullptr, nullptr); - } + + ovrTrackingState ts = ovrHmd_GetTrackingState(_ovrHmd, ovr_GetTimeInSeconds()); + glm::vec3 trackerPosition = toGlm(ts.HeadPose.ThePose.Position); + + if (_calibrationState != CALIBRATED) { + calibrate(trackerPosition, toGlm(ts.HeadPose.ThePose.Orientation)); } -#endif + + trackerPosition = bodyOrientation * trackerPosition; + static ovrVector3f eyeOffsets[2] = { { 0, 0, 0 }, { 0, 0, 0 } }; + ovrPosef eyePoses[ovrEye_Count]; + ovrHmd_GetEyePoses(_ovrHmd, _frameIndex, eyeOffsets, eyePoses, nullptr); -#ifndef OVR_CLIENT_DISTORTION +#ifndef Q_OS_WIN // FIXME: we need a better way of responding to the HSW. In particular // we need to ensure that it's only displayed once per session, rather than // every time the user toggles VR mode, and we need to hook it up to actual @@ -522,7 +570,6 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati } } #endif - //beginFrameTiming must be called before display if (!_frameTimingActive) { @@ -545,27 +592,12 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati glMatrixMode(GL_MODELVIEW); glPushMatrix(); - - glm::quat orientation; - glm::vec3 trackerPosition; auto deviceSize = qApp->getDeviceSize(); - ovrTrackingState ts = ovrHmd_GetTrackingState(_ovrHmd, ovr_GetTimeInSeconds()); - ovrVector3f ovrHeadPosition = ts.HeadPose.ThePose.Position; - - trackerPosition = glm::vec3(ovrHeadPosition.x, ovrHeadPosition.y, ovrHeadPosition.z); - - if (_calibrationState != CALIBRATED) { - ovrQuatf ovrHeadOrientation = ts.HeadPose.ThePose.Orientation; - orientation = glm::quat(ovrHeadOrientation.w, ovrHeadOrientation.x, ovrHeadOrientation.y, ovrHeadOrientation.z); - calibrate(trackerPosition, orientation); - } - - trackerPosition = bodyOrientation * trackerPosition; - static ovrVector3f eyeOffsets[2] = { { 0, 0, 0 }, { 0, 0, 0 } }; - ovrPosef eyePoses[ovrEye_Count]; - ovrHmd_GetEyePoses(_ovrHmd, _frameIndex, eyeOffsets, eyePoses, nullptr); +#ifndef Q_OS_WIN ovrHmd_BeginFrame(_ovrHmd, _frameIndex); +#endif + static ovrPosef eyeRenderPose[ovrEye_Count]; //Render each eye into an fbo for_each_eye(_ovrHmd, [&](ovrEyeType eye){ @@ -578,11 +610,7 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati _lastEyeRendered = _activeEye = eye; eyeRenderPose[eye] = eyePoses[eye]; // Set the camera rotation for this eye - orientation.x = eyeRenderPose[eye].Orientation.x; - orientation.y = eyeRenderPose[eye].Orientation.y; - orientation.z = eyeRenderPose[eye].Orientation.z; - orientation.w = eyeRenderPose[eye].Orientation.w; - + glm::quat orientation = toGlm(eyeRenderPose[eye].Orientation); // Update the application camera with the latest HMD position whichCamera.setHmdPosition(trackerPosition); whichCamera.setHmdRotation(orientation); @@ -607,19 +635,14 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - ovrRecti & vp = _eyeTextures[eye].Header.RenderViewport; - vp.Size.h = _recommendedTexSize.h * _offscreenRenderScale; - vp.Size.w = _recommendedTexSize.w * _offscreenRenderScale; - + const ovrRecti& vp = _eyeViewports[eye]; glViewport(vp.Pos.x, vp.Pos.y, vp.Size.w, vp.Size.h); qApp->displaySide(*_camera, false, RenderArgs::MONO); - qApp->getApplicationOverlay().displayOverlayTextureHmd(*_camera); + //qApp->getApplicationOverlay().displayOverlayTextureHmd(*_camera); }); _activeEye = ovrEye_Count; - glPopMatrix(); - gpu::FramebufferPointer finalFbo; //Bind the output texture from the glow shader. If glow effect is disabled, we just grab the texture if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) { @@ -633,146 +656,70 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati glMatrixMode(GL_PROJECTION); glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + +#ifdef Q_OS_WIN + auto srcFboSize = finalFbo->getSize(); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(finalFbo)); + _swapFbo->Bound(oglplus::Framebuffer::Target::Draw, [&] { + glBlitFramebuffer( + 0, 0, srcFboSize.x, srcFboSize.y, + 0, 0, _swapFbo->size.x, _swapFbo->size.y, + GL_COLOR_BUFFER_BIT, GL_NEAREST); + }); + auto destWindowSize = qApp->getDeviceSize(); + glBlitFramebuffer( + 0, 0, srcFboSize.x, srcFboSize.y, + 0, 0, destWindowSize.width(), destWindowSize.height(), + GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + + ovrLayerEyeFov sceneLayer; + sceneLayer.ColorTexture[0] = _swapFbo->color; + sceneLayer.ColorTexture[1] = nullptr; + + sceneLayer.Viewport[0].Pos = { 0, 0 }; + sceneLayer.Viewport[0].Size = { _swapFbo->size.x / 2, _swapFbo->size.y }; + sceneLayer.Viewport[1].Pos = { _swapFbo->size.x / 2, 0 }; + sceneLayer.Viewport[1].Size = { _swapFbo->size.x / 2, _swapFbo->size.y }; + sceneLayer.Header.Type = ovrLayerType_EyeFov; + sceneLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft; + for_each_eye([&](ovrEyeType eye) { + sceneLayer.Fov[eye] = _eyeFov[eye]; + sceneLayer.RenderPose[eye] = eyeRenderPose[eye]; + }); + auto header = &sceneLayer.Header; + ovrResult res = ovrHmd_SubmitFrame(_ovrHmd, _frameIndex, nullptr, &header, 1); + Q_ASSERT(OVR_SUCCESS(res)); + _swapFbo->Increment(); +#else + GLuint textureId = gpu::GLBackend::getTextureID(finalFbo->getRenderBuffer(0)); + for_each_eye([&](ovrEyeType eye) { + ovrGLTexture & glEyeTexture = reinterpret_cast(_eyeTextures[eye]); + glEyeTexture.OGL.TexId = textureId; + }); + + //ovrHmd_EndFrame(_ovrHmd, eyeRenderPose, _eyeTextures); + glClearColor(0, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + auto srcFboSize = finalFbo->getSize(); + glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(finalFbo)); + auto destWindowSize = qApp->getDeviceSize(); + glBlitFramebuffer( + 0, 0, srcFboSize.x, srcFboSize.y, + 0, 0, destWindowSize.width(), destWindowSize.height(), + GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glCanvas->swapBuffers(); +#endif // restore our normal viewport glViewport(0, 0, deviceSize.width(), deviceSize.height()); - -#if 0 - if (debugFrame && !timerActive) { - timerQuery.begin(); - } -#endif - -#ifdef OVR_CLIENT_DISTORTION - - //Wait till time-warp to reduce latency - ovr_WaitTillTime(_hmdFrameTiming.TimewarpPointSeconds); - -#ifdef DEBUG_RENDER_WITHOUT_DISTORTION - auto fboSize = finalFbo->getSize(); - glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(finalFbo)); - glBlitFramebuffer( - 0, 0, fboSize.x, fboSize.y, - 0, 0, deviceSize.width(), deviceSize.height(), - GL_COLOR_BUFFER_BIT, GL_NEAREST); -#else - //Clear the color buffer to ensure that there isnt any residual color - //Left over from when OR was not connected. - glClear(GL_COLOR_BUFFER_BIT); - glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(finalFbo->getRenderBuffer(0))); - //Renders the distorted mesh onto the screen - renderDistortionMesh(eyeRenderPose); - glBindTexture(GL_TEXTURE_2D, 0); -#endif - glCanvas->swapBuffers(); - -#else - - for_each_eye([&](ovrEyeType eye) { - ovrGLTexture & glEyeTexture = reinterpret_cast(_eyeTextures[eye]); - glEyeTexture.OGL.TexId = finalFbo->texture(); - - }); - - ovrHmd_EndFrame(_ovrHmd, eyeRenderPose, _eyeTextures); - -#endif - -#if 0 - if (debugFrame && !timerActive) { - timerQuery.end(); - timerActive = true; - } -#endif - - // No DK2, no message. - { - float latencies[5] = {}; - if (debugFrame && ovrHmd_GetFloatArray(_ovrHmd, "DK2Latency", latencies, 5) == 5) - { - bool nonZero = false; - for (int i = 0; i < 5; ++i) - { - nonZero |= (latencies[i] != 0.f); - } - - if (nonZero) - { - qCDebug(interfaceapp) << QString().sprintf("M2P Latency: Ren: %4.2fms TWrp: %4.2fms PostPresent: %4.2fms Err: %4.2fms %4.2fms", - latencies[0], latencies[1], latencies[2], latencies[3], latencies[4]); - } - } - } - } -#ifdef OVR_CLIENT_DISTORTION -void OculusManager::renderDistortionMesh(ovrPosef eyeRenderPose[ovrEye_Count]) { - - glLoadIdentity(); - auto deviceSize = qApp->getDeviceSize(); - glOrtho(0, deviceSize.width(), 0, deviceSize.height(), -1.0, 1.0); - - glDisable(GL_DEPTH_TEST); - - glDisable(GL_BLEND); - _program.bind(); - _program.setUniformValue(_textureLocation, 0); - - _program.enableAttributeArray(_positionAttributeLocation); - _program.enableAttributeArray(_colorAttributeLocation); - _program.enableAttributeArray(_texCoord0AttributeLocation); - _program.enableAttributeArray(_texCoord1AttributeLocation); - _program.enableAttributeArray(_texCoord2AttributeLocation); - - //Render the distortion meshes for each eye - for (int eyeNum = 0; eyeNum < ovrEye_Count; eyeNum++) { - - ovrHmd_GetRenderScaleAndOffset(_eyeRenderDesc[eyeNum].Fov, _renderTargetSize, _eyeTextures[eyeNum].Header.RenderViewport, - _UVScaleOffset[eyeNum]); - - GLfloat uvScale[2] = { _UVScaleOffset[eyeNum][0].x, _UVScaleOffset[eyeNum][0].y }; - _program.setUniformValueArray(_eyeToSourceUVScaleLocation, uvScale, 1, 2); - GLfloat uvOffset[2] = { _UVScaleOffset[eyeNum][1].x, 1.0f - _UVScaleOffset[eyeNum][1].y }; - _program.setUniformValueArray(_eyeToSourceUVOffsetLocation, uvOffset, 1, 2); - - ovrMatrix4f timeWarpMatrices[2]; - glm::mat4 transposeMatrices[2]; - //Grabs the timewarp matrices to be used in the shader - ovrHmd_GetEyeTimewarpMatrices(_ovrHmd, (ovrEyeType)eyeNum, eyeRenderPose[eyeNum], timeWarpMatrices); - //Have to transpose the matrices before using them - transposeMatrices[0] = glm::transpose(toGlm(timeWarpMatrices[0])); - transposeMatrices[1] = glm::transpose(toGlm(timeWarpMatrices[1])); - - glUniformMatrix4fv(_eyeRotationStartLocation, 1, GL_FALSE, (GLfloat *)&transposeMatrices[0][0][0]); - glUniformMatrix4fv(_eyeRotationEndLocation, 1, GL_FALSE, (GLfloat *)&transposeMatrices[1][0][0]); - - glBindBuffer(GL_ARRAY_BUFFER, _vertices[eyeNum]); - - //Set vertex attribute pointers - glVertexAttribPointer(_positionAttributeLocation, 2, GL_FLOAT, GL_FALSE, sizeof(DistortionVertex), (void *)0); - glVertexAttribPointer(_texCoord0AttributeLocation, 2, GL_FLOAT, GL_FALSE, sizeof(DistortionVertex), (void *)8); - glVertexAttribPointer(_texCoord1AttributeLocation, 2, GL_FLOAT, GL_FALSE, sizeof(DistortionVertex), (void *)16); - glVertexAttribPointer(_texCoord2AttributeLocation, 2, GL_FLOAT, GL_FALSE, sizeof(DistortionVertex), (void *)24); - glVertexAttribPointer(_colorAttributeLocation, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(DistortionVertex), (void *)32); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indices[eyeNum]); - glDrawElements(GL_TRIANGLES, _meshSize[eyeNum], GL_UNSIGNED_SHORT, 0); - } - - _program.disableAttributeArray(_positionAttributeLocation); - _program.disableAttributeArray(_colorAttributeLocation); - _program.disableAttributeArray(_texCoord0AttributeLocation); - _program.disableAttributeArray(_texCoord1AttributeLocation); - _program.disableAttributeArray(_texCoord2AttributeLocation); - - glEnable(GL_BLEND); - glEnable(GL_DEPTH_TEST); - _program.release(); - glBindBuffer(GL_ARRAY_BUFFER, 0); -} -#endif - //Tries to reconnect to the sensors void OculusManager::reset() { if (_isConnected) { @@ -825,6 +772,9 @@ void OculusManager::overrideOffAxisFrustum(float& left, float& right, float& bot } int OculusManager::getHMDScreen() { +#ifdef Q_OS_WIN + return -1; +#else int hmdScreenIndex = -1; // unknown // TODO: it might be smarter to handle multiple HMDs connected in this case. but for now, // we will simply assume the initialization code that set up _ovrHmd picked the best hmd @@ -875,5 +825,6 @@ int OculusManager::getHMDScreen() { } } return hmdScreenIndex; +#endif } diff --git a/interface/src/devices/OculusManager.h b/interface/src/devices/OculusManager.h index a6c3bbf4d5..d07a22fbd1 100644 --- a/interface/src/devices/OculusManager.h +++ b/interface/src/devices/OculusManager.h @@ -24,26 +24,9 @@ class Camera; class PalmData; class Text3DOverlay; -// Uncomment this to enable client side distortion. NOT recommended since -// the Oculus SDK will ideally provide the best practices for distortion in -// in terms of performance and quality, and by using it we will get updated -// best practices for free with new runtime releases. -#define OVR_CLIENT_DISTORTION 1 - - -// Direct HMD mode is currently only supported on windows and some linux systems will -// misbehave if we try to enable the Oculus SDK at all, so isolate support for Direct -// mode only to windows for now #ifdef Q_OS_WIN -// On Win32 platforms, enabling Direct HMD requires that the SDK be -// initialized before the GL context is set up, but this breaks v-sync -// for any application that has a Direct mode enable Rift connected -// but is not rendering to it. For the time being I'm setting this as -// a macro enabled mechanism which changes where the SDK is initialized. -// To enable Direct HMD mode, you can un-comment this, but with the -// caveat that it will break v-sync in NON-VR mode if you have an Oculus -// Rift connect and in Direct mode -#define OVR_DIRECT_MODE 1 +struct SwapFramebufferWrapper; +struct MirrorFramebufferWrapper; #endif @@ -83,44 +66,7 @@ public: private: static void initSdk(); static void shutdownSdk(); -#ifdef OVR_CLIENT_DISTORTION - static void generateDistortionMesh(); - static void renderDistortionMesh(ovrPosef eyeRenderPose[ovrEye_Count]); - struct DistortionVertex { - glm::vec2 pos; - glm::vec2 texR; - glm::vec2 texG; - glm::vec2 texB; - struct { - GLubyte r; - GLubyte g; - GLubyte b; - GLubyte a; - } color; - }; - static ProgramObject _program; - //Uniforms - static int _textureLocation; - static int _eyeToSourceUVScaleLocation; - static int _eyeToSourceUVOffsetLocation; - static int _eyeRotationStartLocation; - static int _eyeRotationEndLocation; - //Attributes - static int _positionAttributeLocation; - static int _colorAttributeLocation; - static int _texCoord0AttributeLocation; - static int _texCoord1AttributeLocation; - static int _texCoord2AttributeLocation; - static ovrVector2f _UVScaleOffset[ovrEye_Count][2]; - static GLuint _vertices[ovrEye_Count]; - static GLuint _indices[ovrEye_Count]; - static GLsizei _meshSize[ovrEye_Count]; - static ovrFrameTiming _hmdFrameTiming; - static bool _programInitialized; -#endif - - static ovrTexture _eyeTextures[ovrEye_Count]; static bool _isConnected; static glm::vec3 _eyePositions[ovrEye_Count]; static ovrHmd _ovrHmd; @@ -128,6 +74,7 @@ private: static ovrVector3f _eyeOffset[ovrEye_Count]; static glm::mat4 _eyeProjection[ovrEye_Count]; static ovrEyeRenderDesc _eyeRenderDesc[ovrEye_Count]; + static ovrRecti _eyeViewports[ovrEye_Count]; static ovrSizei _renderTargetSize; static unsigned int _frameIndex; static bool _frameTimingActive; @@ -160,6 +107,13 @@ private: static float _offscreenRenderScale; static bool _eyePerFrameMode; static ovrEyeType _lastEyeRendered; +#ifdef Q_OS_WIN + static SwapFramebufferWrapper* _swapFbo; + static MirrorFramebufferWrapper* _mirrorFbo; + static ovrLayerEyeFov _sceneLayer; +#else + static ovrTexture _eyeTextures[ovrEye_Count]; +#endif }; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 483ea6177e..feddf61405 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1412,7 +1412,7 @@ void Model::simulate(float deltaTime, bool fullUpdate) { if (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint) { snapToRegistrationPoint(); } - simulateInternal(deltaTime); + //simulateInternal(deltaTime); } } diff --git a/libraries/shared/CMakeLists.txt b/libraries/shared/CMakeLists.txt index 9785994a29..6f7efd1b40 100644 --- a/libraries/shared/CMakeLists.txt +++ b/libraries/shared/CMakeLists.txt @@ -2,8 +2,18 @@ set(TARGET_NAME shared) # use setup_hifi_library macro to setup our project and link appropriate Qt modules # TODO: there isn't really a good reason to have Script linked here - let's get what is requiring it out (RegisteredMetaTypes.cpp) -setup_hifi_library(Gui Network Script Widgets) +setup_hifi_library(Gui Network OpenGL Script Widgets) + +setup_hifi_opengl() add_dependency_external_projects(glm) find_package(GLM REQUIRED) -target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) \ No newline at end of file +target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) + +add_dependency_external_projects(boostconfig) +find_package(BOOSTCONFIG REQUIRED) +target_include_directories(${TARGET_NAME} PUBLIC ${BOOSTCONFIG_INCLUDE_DIRS}) + +add_dependency_external_projects(oglplus) +find_package(OGLPLUS REQUIRED) +target_include_directories(${TARGET_NAME} PUBLIC ${OGLPLUS_INCLUDE_DIRS}) diff --git a/libraries/shared/src/OglplusHelpers.cpp b/libraries/shared/src/OglplusHelpers.cpp new file mode 100644 index 0000000000..47e0773b5e --- /dev/null +++ b/libraries/shared/src/OglplusHelpers.cpp @@ -0,0 +1,322 @@ +// +// Created by Bradley Austin Davis on 2015/05/29 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "OglplusHelpers.h" + +using namespace oglplus; +using namespace oglplus::shapes; + +static const char * SIMPLE_TEXTURED_VS = R"VS(#version 410 core +#pragma line __LINE__ + +uniform mat4 Projection = mat4(1); +uniform mat4 ModelView = mat4(1); + +layout(location = 0) in vec3 Position; +layout(location = 1) in vec2 TexCoord; + +out vec2 vTexCoord; + +void main() { + gl_Position = Projection * ModelView * vec4(Position, 1); + vTexCoord = TexCoord; +} + +)VS"; + +static const char * SIMPLE_TEXTURED_FS = R"FS(#version 410 core +#pragma line __LINE__ + +uniform sampler2D sampler; +uniform float Alpha = 1.0; + +in vec2 vTexCoord; +out vec4 vFragColor; + +void main() { + vec4 c = texture(sampler, vTexCoord); + c.a = min(Alpha, c.a); + vFragColor = c; +} + +)FS"; + + +ProgramPtr loadDefaultShader() { + ProgramPtr result; + compileProgram(result, SIMPLE_TEXTURED_VS, SIMPLE_TEXTURED_FS); + return result; +} + +void compileProgram(ProgramPtr & result, const std::string& vs, const std::string& fs) { + using namespace oglplus; + try { + result = ProgramPtr(new Program()); + // attach the shaders to the program + result->AttachShader( + VertexShader() + .Source(GLSLSource(vs)) + .Compile() + ); + result->AttachShader( + FragmentShader() + .Source(GLSLSource(fs)) + .Compile() + ); + result->Link(); + } catch (ProgramBuildError & err) { + Q_UNUSED(err); + Q_ASSERT_X(false, "compileProgram", "Failed to build shader program"); + qFatal((const char*)err.Message); + result.reset(); + } +} + + +ShapeWrapperPtr loadPlane(ProgramPtr program, float aspect) { + using namespace oglplus; + Vec3f a(1, 0, 0); + Vec3f b(0, 1, 0); + if (aspect > 1) { + b[1] /= aspect; + } else { + a[0] *= aspect; + } + return ShapeWrapperPtr( + new shapes::ShapeWrapper({ "Position", "TexCoord" }, shapes::Plane(a, b), *program) + ); +} + +// Return a point's cartesian coordinates on a sphere from pitch and yaw +static glm::vec3 getPoint(float yaw, float pitch) { + return glm::vec3(glm::cos(-pitch) * (-glm::sin(yaw)), + glm::sin(-pitch), + glm::cos(-pitch) * (-glm::cos(yaw))); +} + + +class SphereSection : public DrawingInstructionWriter, public DrawMode { +public: + using IndexArray = std::vector; + using PosArray = std::vector; + using TexArray = std::vector; + /// The type of the index container returned by Indices() + // vertex positions + PosArray _pos_data; + // vertex tex coords + TexArray _tex_data; + IndexArray _idx_data; + unsigned int _prim_count{ 0 }; + +public: + SphereSection( + const float fov, + const float aspectRatio, + const int slices_, + const int stacks_) { + //UV mapping source: http://www.mvps.org/directx/articles/spheremap.htm + if (fov >= PI) { + qDebug() << "TexturedHemisphere::buildVBO(): FOV greater or equal than Pi will create issues"; + } + + int gridSize = std::max(slices_, stacks_); + int gridSizeLog2 = 1; + while (1 << gridSizeLog2 < gridSize) { + ++gridSizeLog2; + } + gridSize = (1 << gridSizeLog2) + 1; + // Compute number of vertices needed + int vertices = gridSize * gridSize; + _pos_data.resize(vertices * 3); + _tex_data.resize(vertices * 2); + + // Compute vertices positions and texture UV coordinate + for (int y = 0; y <= gridSize; ++y) { + for (int x = 0; x <= gridSize; ++x) { + + } + } + for (int i = 0; i < gridSize; i++) { + float stacksRatio = (float)i / (float)(gridSize - 1); // First stack is 0.0f, last stack is 1.0f + // abs(theta) <= fov / 2.0f + float pitch = -fov * (stacksRatio - 0.5f); + for (int j = 0; j < gridSize; j++) { + float slicesRatio = (float)j / (float)(gridSize - 1); // First slice is 0.0f, last slice is 1.0f + // abs(phi) <= fov * aspectRatio / 2.0f + float yaw = -fov * aspectRatio * (slicesRatio - 0.5f); + int vertex = i * gridSize + j; + int posOffset = vertex * 3; + int texOffset = vertex * 2; + vec3 pos = getPoint(yaw, pitch); + _pos_data[posOffset] = pos.x; + _pos_data[posOffset + 1] = pos.y; + _pos_data[posOffset + 2] = pos.z; + _tex_data[texOffset] = slicesRatio; + _tex_data[texOffset + 1] = stacksRatio; + } + } // done with vertices + + int rowLen = gridSize; + + // gridsize now refers to the triangles, not the vertices, so reduce by one + // or die by fencepost error http://en.wikipedia.org/wiki/Off-by-one_error + --gridSize; + int quads = gridSize * gridSize; + for (int t = 0; t < quads; ++t) { + int x = + ((t & 0x0001) >> 0) | + ((t & 0x0004) >> 1) | + ((t & 0x0010) >> 2) | + ((t & 0x0040) >> 3) | + ((t & 0x0100) >> 4) | + ((t & 0x0400) >> 5) | + ((t & 0x1000) >> 6) | + ((t & 0x4000) >> 7); + int y = + ((t & 0x0002) >> 1) | + ((t & 0x0008) >> 2) | + ((t & 0x0020) >> 3) | + ((t & 0x0080) >> 4) | + ((t & 0x0200) >> 5) | + ((t & 0x0800) >> 6) | + ((t & 0x2000) >> 7) | + ((t & 0x8000) >> 8); + int i = x * (rowLen) + y; + + _idx_data.push_back(i); + _idx_data.push_back(i + 1); + _idx_data.push_back(i + rowLen + 1); + + _idx_data.push_back(i + rowLen + 1); + _idx_data.push_back(i + rowLen); + _idx_data.push_back(i); + } + _prim_count = quads * 2; + } + + /// Returns the winding direction of faces + FaceOrientation FaceWinding(void) const { + return FaceOrientation::CCW; + } + + typedef GLuint(SphereSection::*VertexAttribFunc)(std::vector&) const; + + /// Makes the vertex positions and returns the number of values per vertex + template + GLuint Positions(std::vector& dest) const { + dest.clear(); + dest.insert(dest.begin(), _pos_data.begin(), _pos_data.end()); + return 3; + } + + /// Makes the vertex normals and returns the number of values per vertex + template + GLuint Normals(std::vector& dest) const { + dest.clear(); + return 3; + } + + /// Makes the vertex tangents and returns the number of values per vertex + template + GLuint Tangents(std::vector& dest) const { + dest.clear(); + return 3; + } + + /// Makes the vertex bi-tangents and returns the number of values per vertex + template + GLuint Bitangents(std::vector& dest) const { + dest.clear(); + return 3; + } + + /// Makes the texture coordinates returns the number of values per vertex + template + GLuint TexCoordinates(std::vector& dest) const { + dest.clear(); + dest.insert(dest.begin(), _tex_data.begin(), _tex_data.end()); + return 2; + } + + typedef VertexAttribsInfo< + SphereSection, + std::tuple< + VertexPositionsTag, + VertexNormalsTag, + VertexTangentsTag, + VertexBitangentsTag, + VertexTexCoordinatesTag + > + > VertexAttribs; + + Spheref MakeBoundingSphere(void) const { + GLfloat min_x = _pos_data[3], max_x = _pos_data[3]; + GLfloat min_y = _pos_data[4], max_y = _pos_data[4]; + GLfloat min_z = _pos_data[5], max_z = _pos_data[5]; + for (std::size_t v = 0, vn = _pos_data.size() / 3; v != vn; ++v) { + GLfloat x = _pos_data[v * 3 + 0]; + GLfloat y = _pos_data[v * 3 + 1]; + GLfloat z = _pos_data[v * 3 + 2]; + + if (min_x > x) min_x = x; + if (min_y > y) min_y = y; + if (min_z > z) min_z = z; + if (max_x < x) max_x = x; + if (max_y < y) max_y = y; + if (max_z < z) max_z = z; + } + + Vec3f c( + (min_x + max_x) * 0.5f, + (min_y + max_y) * 0.5f, + (min_z + max_z) * 0.5f + ); + + return Spheref( + c.x(), c.y(), c.z(), + Distance(c, Vec3f(min_x, min_y, min_z)) + ); + } + + /// Queries the bounding sphere coordinates and dimensions + template + void BoundingSphere(oglplus::Sphere& bounding_sphere) const { + bounding_sphere = oglplus::Sphere(MakeBoundingSphere()); + } + + + /// Returns element indices that are used with the drawing instructions + const IndexArray & Indices(Default = Default()) const { + return _idx_data; + } + + /// Returns the instructions for rendering of faces + DrawingInstructions Instructions(PrimitiveType primitive) const { + DrawingInstructions instr = this->MakeInstructions(); + DrawOperation operation; + operation.method = DrawOperation::Method::DrawElements; + operation.mode = primitive; + operation.first = 0; + operation.count = _prim_count * 3; + operation.restart_index = DrawOperation::NoRestartIndex(); + operation.phase = 0; + this->AddInstruction(instr, operation); + return std::move(instr); + } + + /// Returns the instructions for rendering of faces + DrawingInstructions Instructions(Default = Default()) const { + return Instructions(PrimitiveType::Triangles); + } +}; + +ShapeWrapperPtr loadSphereSection(ProgramPtr program, float fov, float aspect, int slices, int stacks) { + using namespace oglplus; + return ShapeWrapperPtr( + new shapes::ShapeWrapper({ "Position", "TexCoord" }, SphereSection(fov, aspect, slices, stacks), *program) + ); +} diff --git a/libraries/shared/src/OglplusHelpers.h b/libraries/shared/src/OglplusHelpers.h new file mode 100644 index 0000000000..1a00c021f9 --- /dev/null +++ b/libraries/shared/src/OglplusHelpers.h @@ -0,0 +1,166 @@ +// +// Created by Bradley Austin Davis on 2015/05/26 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#pragma once + +#include "GLMHelpers.h" + +#define OGLPLUS_USE_GLCOREARB_H 0 + +#if defined(__APPLE__) + +#define OGLPLUS_USE_GL3_H 1 + +#elif defined(WIN32) + +#define OGLPLUS_USE_GLEW 1 +#pragma warning(disable : 4068) + +#elif defined(ANDROID) + +#else + +#define OGLPLUS_USE_GLCOREARB_H 1 + +#endif + + + +#define OGLPLUS_USE_BOOST_CONFIG 1 +#define OGLPLUS_NO_SITE_CONFIG 1 +#define OGLPLUS_LOW_PROFILE 1 +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "NumericalConstants.h" + +using FramebufferPtr = std::shared_ptr; +using ShapeWrapperPtr = std::shared_ptr; +using BufferPtr = std::shared_ptr; +using VertexArrayPtr = std::shared_ptr; +using ProgramPtr = std::shared_ptr; +using Mat4Uniform = oglplus::Uniform; + +ProgramPtr loadDefaultShader(); +void compileProgram(ProgramPtr & result, const std::string& vs, const std::string& fs); +ShapeWrapperPtr loadPlane(ProgramPtr program, float aspect = 1.0f); +ShapeWrapperPtr loadSphereSection(ProgramPtr program, float fov = PI / 3.0f * 2.0f, float aspect = 16.0f / 9.0f, int slices = 32, int stacks = 32); + + +// A basic wrapper for constructing a framebuffer with a renderbuffer +// for the depth attachment and an undefined type for the color attachement +// This allows us to reuse the basic framebuffer code for both the Mirror +// FBO as well as the Oculus swap textures we will use to render the scene +// Though we don't really need depth at all for the mirror FBO, or even an +// FBO, but using one means I can just use a glBlitFramebuffer to get it onto +// the screen. +template < + typename C, + typename D +> +struct FramebufferWrapper { + uvec2 size; + oglplus::Framebuffer fbo; + C color; + D depth; + + FramebufferWrapper() {} + + virtual ~FramebufferWrapper() { + } + + virtual void Init(const uvec2 & size) { + this->size = size; + initColor(); + initDepth(); + initDone(); + } + + template + void Bound(F f) { + Bound(oglplus::Framebuffer::Target::Draw, f); + } + + template + void Bound(oglplus::Framebuffer::Target target , F f) { + fbo.Bind(target); + onBind(target); + f(); + onUnbind(target); + oglplus::DefaultFramebuffer().Bind(target); + } + + void Viewport() { + oglplus::Context::Viewport(size.x, size.y); + } + +protected: + virtual void onBind(oglplus::Framebuffer::Target target) {} + virtual void onUnbind(oglplus::Framebuffer::Target target) {} + + static GLenum toEnum(oglplus::Framebuffer::Target target) { + switch (target) { + case oglplus::Framebuffer::Target::Draw: + return GL_DRAW_FRAMEBUFFER; + case oglplus::Framebuffer::Target::Read: + return GL_READ_FRAMEBUFFER; + default: + Q_ASSERT(false); + return GL_FRAMEBUFFER; + } + } + + virtual void initDepth() {} + + virtual void initColor() {} + + virtual void initDone() = 0; +}; + +struct BasicFramebufferWrapper : public FramebufferWrapper { +protected: + virtual void initDepth() override { + using namespace oglplus; + Context::Bound(Renderbuffer::Target::Renderbuffer, depth) + .Storage( + PixelDataInternalFormat::DepthComponent, + size.x, size.y); + } + + virtual void initColor() override { + using namespace oglplus; + Context::Bound(oglplus::Texture::Target::_2D, color) + .MinFilter(TextureMinFilter::Linear) + .MagFilter(TextureMagFilter::Linear) + .WrapS(TextureWrap::ClampToEdge) + .WrapT(TextureWrap::ClampToEdge) + .Image2D( + 0, PixelDataInternalFormat::RGBA8, + size.x, size.y, + 0, PixelDataFormat::RGB, PixelDataType::UnsignedByte, nullptr + ); + } + + virtual void initDone() override { + using namespace oglplus; + static const Framebuffer::Target target = Framebuffer::Target::Draw; + Bound(target, [&] { + fbo.AttachTexture(target, FramebufferAttachment::Color, color, 0); + fbo.AttachRenderbuffer(target, FramebufferAttachment::Depth, depth); + fbo.Complete(target); + }); + } +}; + +using BasicFramebufferWrapperPtr = std::shared_ptr; \ No newline at end of file From b56fbd474456ef9959b638fbd4fdfbb2ecad243f Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Sun, 7 Jun 2015 13:56:06 -0700 Subject: [PATCH 02/34] Working on SDK 0.6 --- interface/src/devices/OculusManager.cpp | 56 ++++++++++++++++--------- libraries/shared/src/OglplusHelpers.cpp | 3 ++ libraries/shared/src/OglplusHelpers.h | 4 +- 3 files changed, 42 insertions(+), 21 deletions(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 12b8abeb66..d6151200f8 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -269,9 +269,9 @@ void OculusManager::connect() { _sceneLayer.ColorTexture[0] = _swapFbo->color; _sceneLayer.ColorTexture[1] = nullptr; _sceneLayer.Viewport[0].Pos = { 0, 0 }; - _sceneLayer.Viewport[0].Size = { _swapFbo->size.x / 2, _swapFbo->size.y }; - _sceneLayer.Viewport[1].Pos = { _swapFbo->size.x / 2, 0 }; - _sceneLayer.Viewport[1].Size = { _swapFbo->size.x / 2, _swapFbo->size.y }; + _sceneLayer.Viewport[0].Size = _recommendedTexSize; + _sceneLayer.Viewport[1].Pos = { _recommendedTexSize.x, 0 }; + _sceneLayer.Viewport[1].Size = _recommendedTexSize; _sceneLayer.Header.Type = ovrLayerType_EyeFov; _sceneLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft; for_each_eye([&](ovrEyeType eye) { @@ -541,18 +541,6 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati timerActive = false; } #endif - - ovrTrackingState ts = ovrHmd_GetTrackingState(_ovrHmd, ovr_GetTimeInSeconds()); - glm::vec3 trackerPosition = toGlm(ts.HeadPose.ThePose.Position); - - if (_calibrationState != CALIBRATED) { - calibrate(trackerPosition, toGlm(ts.HeadPose.ThePose.Orientation)); - } - - trackerPosition = bodyOrientation * trackerPosition; - static ovrVector3f eyeOffsets[2] = { { 0, 0, 0 }, { 0, 0, 0 } }; - ovrPosef eyePoses[ovrEye_Count]; - ovrHmd_GetEyePoses(_ovrHmd, _frameIndex, eyeOffsets, eyePoses, nullptr); #ifndef Q_OS_WIN // FIXME: we need a better way of responding to the HSW. In particular @@ -570,6 +558,7 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati } } #endif + //beginFrameTiming must be called before display if (!_frameTimingActive) { @@ -592,12 +581,30 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati glMatrixMode(GL_MODELVIEW); glPushMatrix(); + + glm::quat orientation; + glm::vec3 trackerPosition; auto deviceSize = qApp->getDeviceSize(); #ifndef Q_OS_WIN ovrHmd_BeginFrame(_ovrHmd, _frameIndex); #endif + ovrTrackingState ts = ovrHmd_GetTrackingState(_ovrHmd, ovr_GetTimeInSeconds()); + ovrVector3f ovrHeadPosition = ts.HeadPose.ThePose.Position; + + trackerPosition = glm::vec3(ovrHeadPosition.x, ovrHeadPosition.y, ovrHeadPosition.z); + if (_calibrationState != CALIBRATED) { + ovrQuatf ovrHeadOrientation = ts.HeadPose.ThePose.Orientation; + orientation = glm::quat(ovrHeadOrientation.w, ovrHeadOrientation.x, ovrHeadOrientation.y, ovrHeadOrientation.z); + calibrate(trackerPosition, orientation); + } + + trackerPosition = bodyOrientation * trackerPosition; + static ovrVector3f eyeOffsets[2] = { { 0, 0, 0 }, { 0, 0, 0 } }; + ovrPosef eyePoses[ovrEye_Count]; + ovrHmd_GetEyePoses(_ovrHmd, _frameIndex, eyeOffsets, eyePoses, nullptr); + ovrHmd_BeginFrame(_ovrHmd, _frameIndex); static ovrPosef eyeRenderPose[ovrEye_Count]; //Render each eye into an fbo for_each_eye(_ovrHmd, [&](ovrEyeType eye){ @@ -610,7 +617,11 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati _lastEyeRendered = _activeEye = eye; eyeRenderPose[eye] = eyePoses[eye]; // Set the camera rotation for this eye - glm::quat orientation = toGlm(eyeRenderPose[eye].Orientation); + orientation.x = eyeRenderPose[eye].Orientation.x; + orientation.y = eyeRenderPose[eye].Orientation.y; + orientation.z = eyeRenderPose[eye].Orientation.z; + orientation.w = eyeRenderPose[eye].Orientation.w; + // Update the application camera with the latest HMD position whichCamera.setHmdPosition(trackerPosition); whichCamera.setHmdRotation(orientation); @@ -635,14 +646,18 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - const ovrRecti& vp = _eyeViewports[eye]; + ovrRecti & vp = _eyeViewports[eye]; + vp.Size.h = _recommendedTexSize.h * _offscreenRenderScale; + vp.Size.w = _recommendedTexSize.w * _offscreenRenderScale; glViewport(vp.Pos.x, vp.Pos.y, vp.Size.w, vp.Size.h); qApp->displaySide(*_camera, false, RenderArgs::MONO); - //qApp->getApplicationOverlay().displayOverlayTextureHmd(*_camera); + qApp->getApplicationOverlay().displayOve rlayTextureHmd(*_camera); }); _activeEye = ovrEye_Count; + glPopMatrix(); + gpu::FramebufferPointer finalFbo; //Bind the output texture from the glow shader. If glow effect is disabled, we just grab the texture if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) { @@ -656,9 +671,9 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati glMatrixMode(GL_PROJECTION); glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); + // restore our normal viewport + glViewport(0, 0, deviceSize.width(), deviceSize.height()); #ifdef Q_OS_WIN auto srcFboSize = finalFbo->getSize(); @@ -715,6 +730,7 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); glCanvas->swapBuffers(); #endif + // restore our normal viewport glViewport(0, 0, deviceSize.width(), deviceSize.height()); diff --git a/libraries/shared/src/OglplusHelpers.cpp b/libraries/shared/src/OglplusHelpers.cpp index 47e0773b5e..47f9778cac 100644 --- a/libraries/shared/src/OglplusHelpers.cpp +++ b/libraries/shared/src/OglplusHelpers.cpp @@ -1,3 +1,5 @@ +#ifdef Q_OS_WIN + // // Created by Bradley Austin Davis on 2015/05/29 // Copyright 2015 High Fidelity, Inc. @@ -320,3 +322,4 @@ ShapeWrapperPtr loadSphereSection(ProgramPtr program, float fov, float aspect, i new shapes::ShapeWrapper({ "Position", "TexCoord" }, SphereSection(fov, aspect, slices, stacks), *program) ); } +#endif \ No newline at end of file diff --git a/libraries/shared/src/OglplusHelpers.h b/libraries/shared/src/OglplusHelpers.h index 1a00c021f9..73d32c4079 100644 --- a/libraries/shared/src/OglplusHelpers.h +++ b/libraries/shared/src/OglplusHelpers.h @@ -5,6 +5,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#ifdef Q_OS_WIN #pragma once #include "GLMHelpers.h" @@ -163,4 +164,5 @@ protected: } }; -using BasicFramebufferWrapperPtr = std::shared_ptr; \ No newline at end of file +using BasicFramebufferWrapperPtr = std::shared_ptr; +#endif \ No newline at end of file From 4d8bc27ece9ad434c7a0d383a4c34efb69e8a7c1 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 3 Jun 2015 11:11:31 -0700 Subject: [PATCH 03/34] Rename Dialog.qml to DialogOld.qml --- interface/resources/qml/Browser.qml | 2 +- interface/resources/qml/InfoView.qml | 2 +- interface/resources/qml/LoginDialog.qml | 2 +- interface/resources/qml/MarketplaceDialog.qml | 2 +- interface/resources/qml/MessageDialog.qml | 2 +- interface/resources/qml/TestDialog.qml | 2 +- interface/resources/qml/controls/{Dialog.qml => DialogOld.qml} | 0 7 files changed, 6 insertions(+), 6 deletions(-) rename interface/resources/qml/controls/{Dialog.qml => DialogOld.qml} (100%) diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index 55a0a6a461..3de616e05b 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -4,7 +4,7 @@ import QtWebKit 3.0 import "controls" import "styles" -Dialog { +DialogOld { id: root HifiConstants { id: hifi } title: "Browser" diff --git a/interface/resources/qml/InfoView.qml b/interface/resources/qml/InfoView.qml index 6b49e6f0c7..e97ebdeaf3 100644 --- a/interface/resources/qml/InfoView.qml +++ b/interface/resources/qml/InfoView.qml @@ -5,7 +5,7 @@ import QtQuick.Controls.Styles 1.3 import QtWebKit 3.0 import "controls" -Dialog { +DialogOld { id: root width: 800 height: 800 diff --git a/interface/resources/qml/LoginDialog.qml b/interface/resources/qml/LoginDialog.qml index 5653dfc7a1..0c02c0af64 100644 --- a/interface/resources/qml/LoginDialog.qml +++ b/interface/resources/qml/LoginDialog.qml @@ -4,7 +4,7 @@ import QtQuick.Controls.Styles 1.3 import "controls" import "styles" -Dialog { +DialogOld { HifiConstants { id: hifi } title: "Login" objectName: "LoginDialog" diff --git a/interface/resources/qml/MarketplaceDialog.qml b/interface/resources/qml/MarketplaceDialog.qml index 58bb3e6183..4ad3c6515f 100644 --- a/interface/resources/qml/MarketplaceDialog.qml +++ b/interface/resources/qml/MarketplaceDialog.qml @@ -5,7 +5,7 @@ import QtQuick.Controls.Styles 1.3 import QtWebKit 3.0 import "controls" -Dialog { +DialogOld { title: "Test Dlg" id: testDialog objectName: "Browser" diff --git a/interface/resources/qml/MessageDialog.qml b/interface/resources/qml/MessageDialog.qml index dd410b8070..5c699e1f1f 100644 --- a/interface/resources/qml/MessageDialog.qml +++ b/interface/resources/qml/MessageDialog.qml @@ -5,7 +5,7 @@ import QtQuick.Dialogs 1.2 import "controls" import "styles" -Dialog { +DialogOld { id: root HifiConstants { id: hifi } property real spacing: hifi.layout.spacing diff --git a/interface/resources/qml/TestDialog.qml b/interface/resources/qml/TestDialog.qml index 15bd790c22..3ae61fa054 100644 --- a/interface/resources/qml/TestDialog.qml +++ b/interface/resources/qml/TestDialog.qml @@ -3,7 +3,7 @@ import QtQuick.Controls 1.2 import QtQuick.Controls.Styles 1.3 import "controls" -Dialog { +DialogOld { title: "Test Dialog" id: testDialog objectName: "TestDialog" diff --git a/interface/resources/qml/controls/Dialog.qml b/interface/resources/qml/controls/DialogOld.qml similarity index 100% rename from interface/resources/qml/controls/Dialog.qml rename to interface/resources/qml/controls/DialogOld.qml From 811c2507630ef3e8ade00bbf7e4cf7e4bd5ca577 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 3 Jun 2015 13:01:47 -0700 Subject: [PATCH 04/34] Refactor common new dialog functionality into new Dialog.qml --- interface/resources/qml/AddressBarDialog.qml | 62 ++++--------------- interface/resources/qml/ErrorDialog.qml | 50 ++------------- interface/resources/qml/controls/Dialog.qml | 65 ++++++++++++++++++++ 3 files changed, 82 insertions(+), 95 deletions(-) create mode 100644 interface/resources/qml/controls/Dialog.qml diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 91e05d020d..b4f1b2b247 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -9,18 +9,16 @@ // import Hifi 1.0 -import QtQuick 2.3 -import QtQuick.Controls 1.2 +import QtQuick 2.4 import "controls" import "styles" -Item { +Dialog { id: root HifiConstants { id: hifi } objectName: "AddressBarDialog" - property int animationDuration: hifi.effects.fadeInDuration property bool destroyOnInvisible: false property real scale: 1.25 // Make this dialog a little larger than normal @@ -101,47 +99,16 @@ Item { } } - // The UI enables an object, rather than manipulating its visibility, so that we can do animations in both directions. - // Because visibility and enabled are booleans, they cannot be animated. So when enabled is changed, we modify a property - // that can be animated, like scale or opacity, and then when the target animation value is reached, we can modify the - // visibility. - enabled: false - opacity: 0.0 - onEnabledChanged: { - opacity = enabled ? 1.0 : 0.0 if (enabled) { addressLine.forceActiveFocus(); } } - Behavior on opacity { - // Animate opacity. - NumberAnimation { - duration: animationDuration - easing.type: Easing.OutCubic - } - } - - onOpacityChanged: { - // Once we're transparent, disable the dialog's visibility. - visible = (opacity != 0.0) - } - onVisibleChanged: { if (!visible) { - reset() - - // Some dialogs should be destroyed when they become invisible. - if (destroyOnInvisible) { - destroy() - } + addressLine.text = "" } - - } - - function reset() { - addressLine.text = "" } function toggleOrGo() { @@ -152,21 +119,18 @@ Item { } } - Keys.onEscapePressed: { - enabled = false - } - Keys.onPressed: { - switch(event.key) { - case Qt.Key_W: - if (event.modifiers == Qt.ControlModifier) { - event.accepted = true - enabled = false - } + switch (event.key) { + case Qt.Key_Escape: + case Qt.Key_Back: + enabled = false; + event.accepted = true + break + case Qt.Key_Enter: + case Qt.Key_Return: + toggleOrGo() + event.accepted = true break } } - - Keys.onReturnPressed: toggleOrGo() - Keys.onEnterPressed: toggleOrGo() } diff --git a/interface/resources/qml/ErrorDialog.qml b/interface/resources/qml/ErrorDialog.qml index c0f8132f14..c3639f5f3c 100644 --- a/interface/resources/qml/ErrorDialog.qml +++ b/interface/resources/qml/ErrorDialog.qml @@ -9,17 +9,14 @@ // import Hifi 1.0 as Hifi -import QtQuick 2.3 -import QtQuick.Controls 1.2 -import QtQuick.Dialogs 1.2 +import QtQuick 2.4 import "controls" import "styles" -Item { +Dialog { id: root HifiConstants { id: hifi } - property int animationDuration: hifi.effects.fadeInDuration property bool destroyOnInvisible: true Component.onCompleted: { @@ -69,7 +66,7 @@ Item { Text { id: messageText - font.pointSize: 10 + font.pixelSize: hifi.fonts.pixelSize * 0.6 font.weight: Font.Bold anchors { @@ -99,47 +96,8 @@ Item { } } - // The UI enables an object, rather than manipulating its visibility, so that we can do animations in both directions. - // Because visibility and enabled are booleans, they cannot be animated. So when enabled is changed, we modify a property - // that can be animated, like scale or opacity, and then when the target animation value is reached, we can modify the - // visibility. - enabled: false - opacity: 0.0 - - onEnabledChanged: { - opacity = enabled ? 1.0 : 0.0 - } - - Behavior on opacity { - // Animate opacity. - NumberAnimation { - duration: animationDuration - easing.type: Easing.OutCubic - } - } - - onOpacityChanged: { - // Once we're transparent, disable the dialog's visibility. - visible = (opacity != 0.0) - } - - onVisibleChanged: { - if (!visible) { - // Some dialogs should be destroyed when they become invisible. - if (destroyOnInvisible) { - destroy() - } - } - } - Keys.onPressed: { - if (event.modifiers === Qt.ControlModifier) - switch (event.key) { - case Qt.Key_W: - event.accepted = true - content.accept() - break - } else switch (event.key) { + switch (event.key) { case Qt.Key_Escape: case Qt.Key_Back: case Qt.Key_Enter: diff --git a/interface/resources/qml/controls/Dialog.qml b/interface/resources/qml/controls/Dialog.qml new file mode 100644 index 0000000000..63430bdae0 --- /dev/null +++ b/interface/resources/qml/controls/Dialog.qml @@ -0,0 +1,65 @@ +// +// Dialog.qml +// +// Created by David Rowe on 3 Jun 2015 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import Hifi 1.0 +import QtQuick 2.4 +import "../styles" + +Item { + id: root + + property int animationDuration: hifi.effects.fadeInDuration + + + // The UI enables an object, rather than manipulating its visibility, so that we can do animations in both directions. + // Because visibility and enabled are booleans, they cannot be animated. So when enabled is changed, we modify a property + // that can be animated, like scale or opacity, and then when the target animation value is reached, we can modify the + // visibility. + enabled: false + opacity: 0.0 + + onEnabledChanged: { + opacity = enabled ? 1.0 : 0.0 + } + + Behavior on opacity { + // Animate opacity. + NumberAnimation { + duration: animationDuration + easing.type: Easing.OutCubic + } + } + + onOpacityChanged: { + // Once we're transparent, disable the dialog's visibility. + visible = (opacity != 0.0) + } + + onVisibleChanged: { + if (!visible) { + // Some dialogs should be destroyed when they become invisible. + if (destroyOnInvisible) { + destroy() + } + } + } + + + Keys.onPressed: { + switch(event.key) { + case Qt.Key_W: + if (event.modifiers == Qt.ControlModifier) { + enabled = false + event.accepted = true + } + break + } + } +} From 511832c273172f36476fa7d806a3a1d82376bad1 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 4 Jun 2015 13:20:48 -0700 Subject: [PATCH 05/34] New login dialog background with circular and rectangular variations Developer menu item toggles between the two. --- interface/resources/images/login-circle.svg | 3 + interface/resources/images/login-close.svg | 55 ++++ .../resources/images/login-rectangle.svg | 3 + interface/resources/qml/ErrorDialog.qml | 5 +- interface/resources/qml/LoginDialog.qml | 253 ++++++------------ interface/src/Menu.cpp | 15 ++ interface/src/Menu.h | 2 + interface/src/ui/DialogsManager.cpp | 4 + interface/src/ui/DialogsManager.h | 4 + interface/src/ui/LoginDialog.cpp | 37 ++- interface/src/ui/LoginDialog.h | 11 + 11 files changed, 219 insertions(+), 173 deletions(-) create mode 100644 interface/resources/images/login-circle.svg create mode 100644 interface/resources/images/login-close.svg create mode 100644 interface/resources/images/login-rectangle.svg diff --git a/interface/resources/images/login-circle.svg b/interface/resources/images/login-circle.svg new file mode 100644 index 0000000000..8a98902e6b --- /dev/null +++ b/interface/resources/images/login-circle.svg @@ -0,0 +1,3 @@ + + +2015-06-02 19:43ZCanvas 1Login Circle diff --git a/interface/resources/images/login-close.svg b/interface/resources/images/login-close.svg new file mode 100644 index 0000000000..88ca90b96f --- /dev/null +++ b/interface/resources/images/login-close.svg @@ -0,0 +1,55 @@ + +image/svg+xml \ No newline at end of file diff --git a/interface/resources/images/login-rectangle.svg b/interface/resources/images/login-rectangle.svg new file mode 100644 index 0000000000..774baf8193 --- /dev/null +++ b/interface/resources/images/login-rectangle.svg @@ -0,0 +1,3 @@ + + +2015-06-02 19:42ZCanvas 1Login2 diff --git a/interface/resources/qml/ErrorDialog.qml b/interface/resources/qml/ErrorDialog.qml index c3639f5f3c..51befb12a7 100644 --- a/interface/resources/qml/ErrorDialog.qml +++ b/interface/resources/qml/ErrorDialog.qml @@ -8,7 +8,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -import Hifi 1.0 as Hifi +import Hifi 1.0 import QtQuick 2.4 import "controls" import "styles" @@ -35,7 +35,7 @@ Dialog { x: parent ? parent.width / 2 - width / 2 : 0 y: parent ? parent.height / 2 - height / 2 : 0 - Hifi.ErrorDialog { + ErrorDialog { id: content implicitWidth: box.width @@ -88,6 +88,7 @@ Dialog { } MouseArea { anchors.fill: parent + cursorShape: "PointingHandCursor" onClicked: { content.accept(); } diff --git a/interface/resources/qml/LoginDialog.qml b/interface/resources/qml/LoginDialog.qml index 0c02c0af64..6db56d21bf 100644 --- a/interface/resources/qml/LoginDialog.qml +++ b/interface/resources/qml/LoginDialog.qml @@ -1,198 +1,119 @@ +// +// LoginDialog.qml +// +// Created by David Rowe on 3 Jun 2015 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + import Hifi 1.0 -import QtQuick 2.3 -import QtQuick.Controls.Styles 1.3 +import QtQuick 2.4 +import QtQuick.Controls 1.3 // TODO: Needed? import "controls" import "styles" -DialogOld { +Dialog { + id: root HifiConstants { id: hifi } - title: "Login" + objectName: "LoginDialog" - height: 512 - width: 384 - onVisibleChanged: { - if (!visible) { - reset() - } - } + property bool destroyOnInvisible: false - onEnabledChanged: { - if (enabled) { - username.forceActiveFocus(); - } - } + implicitWidth: loginDialog.implicitWidth + implicitHeight: loginDialog.implicitHeight - function reset() { - username.text = "" - password.text = "" - loginDialog.statusText = "" + x: parent ? parent.width / 2 - width / 2 : 0 + y: parent ? parent.height / 2 - height / 2 : 0 + property int maximumX: parent ? parent.width - width : 0 + property int maximumY: parent ? parent.height - height : 0 + + function isCircular() { + return loginDialog.dialogFormat == "circular" } LoginDialog { id: loginDialog - anchors.fill: parent - anchors.margins: parent.margins - anchors.topMargin: parent.topMargin - Column { - anchors.topMargin: 8 - anchors.right: parent.right - anchors.rightMargin: 0 - anchors.left: parent.left - anchors.top: parent.top - spacing: 8 - Image { - height: 64 - anchors.horizontalCenter: parent.horizontalCenter - width: 64 - source: "../images/hifi-logo.svg" + implicitWidth: isCircular() ? circularBackground.width : rectangularBackground.width + implicitHeight: isCircular() ? circularBackground.height : rectangularBackground.height + + Image { + id: circularBackground + visible: isCircular() + + source: "../images/login-circle.svg" + width: 500 + height: 500 + } + + Image { + id: rectangularBackground + visible: !isCircular() + + source: "../images/login-rectangle.svg" + width: 400 + height: 400 + } + + Text { + id: closeText + visible: isCircular() + + text: "Close" + font.pixelSize: hifi.fonts.pixelSize * 0.8 + font.weight: Font.Bold + color: "#175d74" + + anchors { + horizontalCenter: circularBackground.horizontalCenter + bottom: circularBackground.bottom + bottomMargin: hifi.layout.spacing * 4 } - Border { - width: 304 - height: 64 - anchors.horizontalCenter: parent.horizontalCenter - TextInput { - id: username - anchors.fill: parent - helperText: "Username or Email" - anchors.margins: 8 - KeyNavigation.tab: password - KeyNavigation.backtab: password + MouseArea { + anchors.fill: parent + cursorShape: "PointingHandCursor" + onClicked: { + root.enabled = false } } - - Border { - width: 304 - height: 64 - anchors.horizontalCenter: parent.horizontalCenter - TextInput { - id: password - anchors.fill: parent - echoMode: TextInput.Password - helperText: "Password" - anchors.margins: 8 - KeyNavigation.tab: username - KeyNavigation.backtab: username - onFocusChanged: { - if (password.focus) { - password.selectAll() - } - } - } - } - - Text { - anchors.horizontalCenter: parent.horizontalCenter - textFormat: Text.StyledText - width: parent.width - height: 96 - wrapMode: Text.WordWrap - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - text: loginDialog.statusText - } } - Column { - anchors.bottomMargin: 5 - anchors.right: parent.right - anchors.rightMargin: 0 - anchors.left: parent.left - anchors.bottom: parent.bottom + Image { + id: closeIcon + visible: !isCircular() - Rectangle { - width: 192 - height: 64 - anchors.horizontalCenter: parent.horizontalCenter - color: hifi.colors.hifiBlue - border.width: 0 - radius: 10 - - MouseArea { - anchors.bottom: parent.bottom - anchors.bottomMargin: 0 - anchors.top: parent.top - anchors.right: parent.right - anchors.left: parent.left - onClicked: { - loginDialog.login(username.text, password.text) - } - } - - Row { - anchors.centerIn: parent - anchors.verticalCenter: parent.verticalCenter - spacing: 8 - Image { - id: loginIcon - height: 32 - width: 32 - source: "../images/login.svg" - } - Text { - text: "Login" - color: "white" - width: 64 - height: parent.height - } - } + source: "../images/login-close.svg" + width: 20 + height: 20 + anchors { + top: rectangularBackground.top + right: rectangularBackground.right + topMargin: hifi.layout.spacing * 2 + rightMargin: hifi.layout.spacing * 2 } - Text { - width: parent.width - height: 24 - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - text:"Create Account" - font.pointSize: 12 - font.bold: true - color: hifi.colors.hifiBlue - - MouseArea { - anchors.fill: parent - onClicked: { - loginDialog.openUrl(loginDialog.rootUrl + "/signup") - } - } - } - - Text { - width: parent.width - height: 24 - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - font.pointSize: 12 - text: "Recover Password" - color: hifi.colors.hifiBlue - - MouseArea { - anchors.fill: parent - onClicked: { - loginDialog.openUrl(loginDialog.rootUrl + "/users/password/new") - } + MouseArea { + anchors.fill: parent + cursorShape: "PointingHandCursor" + onClicked: { + root.enabled = false } } } } + Keys.onPressed: { - switch(event.key) { - case Qt.Key_Enter: - case Qt.Key_Return: - if (username.activeFocus) { - event.accepted = true - password.forceActiveFocus() - } else if (password.activeFocus) { - event.accepted = true - if (username.text == "") { - username.forceActiveFocus() - } else { - loginDialog.login(username.text, password.text) - } - } - break; + switch (event.key) { + case Qt.Key_Escape: + case Qt.Key_Back: + enabled = false; + event.accepted = true + break } } } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6242318170..b2b9553ea5 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -571,6 +571,21 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowOwned); addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowHulls); + MenuWrapper* loginDialogFormatMenu = developerMenu->addMenu("Login Dialog"); + { + QActionGroup* dialogMenuFormatGroup = new QActionGroup(loginDialogFormatMenu); + + QAction* circularLoginDialog = addCheckableActionToQMenuAndActionHash(loginDialogFormatMenu, + MenuOption::LoginDialogCircular, 0, false, + dialogsManager.data(), SLOT(updateLoginDialogFormat())); + dialogMenuFormatGroup->addAction(circularLoginDialog); + + QAction* rectangularLoginDialog = addCheckableActionToQMenuAndActionHash(loginDialogFormatMenu, + MenuOption::LoginDialogRectangular, 0, true, + dialogsManager.data(), SLOT(updateLoginDialogFormat())); + dialogMenuFormatGroup->addAction(rectangularLoginDialog); + } + MenuWrapper* helpMenu = addMenu("Help"); addActionToQMenuAndActionHash(helpMenu, MenuOption::EditEntitiesHelp, 0, qApp, SLOT(showEditEntitiesHelp())); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 6107744abc..eb1bd94637 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -209,6 +209,8 @@ namespace MenuOption { const QString LoadRSSDKFile = "Load .rssdk file"; const QString LodTools = "LOD Tools"; const QString Login = "Login"; + const QString LoginDialogCircular = "Circular"; + const QString LoginDialogRectangular = "Rectangular"; const QString Log = "Log"; const QString LowVelocityFilter = "Low Velocity Filter"; const QString Mirror = "Mirror"; diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index 1170e3c3a6..705f55586c 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -50,6 +50,10 @@ void DialogsManager::showLoginDialog() { LoginDialog::show(); } +void DialogsManager::updateLoginDialogFormat() { + emit loginDialogFormatChanged(); +} + void DialogsManager::octreeStatsDetails() { if (!_octreeStatsDialog) { _octreeStatsDialog = new OctreeStatsDialog(qApp->getWindow(), qApp->getOcteeSceneStats()); diff --git a/interface/src/ui/DialogsManager.h b/interface/src/ui/DialogsManager.h index fc2dad072b..f7301f5444 100644 --- a/interface/src/ui/DialogsManager.h +++ b/interface/src/ui/DialogsManager.h @@ -47,11 +47,15 @@ public: QPointer getOctreeStatsDialog() const { return _octreeStatsDialog; } QPointer getPreferencesDialog() const { return _preferencesDialog; } +signals: + void loginDialogFormatChanged(); + public slots: void toggleAddressBar(); void toggleDiskCacheEditor(); void toggleLoginDialog(); void showLoginDialog(); + void updateLoginDialogFormat(); void octreeStatsDetails(); void cachesSizeDialog(); void editPreferences(); diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index b452f153f0..4ed338c7db 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -1,6 +1,6 @@ // -// // LoginDialog.cpp +// interface/src/ui // // Created by Bradley Austin Davis on 2015/04/14 // Copyright 2015 High Fidelity, Inc. @@ -8,20 +8,28 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // + #include "LoginDialog.h" -#include "DependencyManager.h" -#include "AccountManager.h" -#include "Menu.h" #include +#include "AccountManager.h" +#include "DependencyManager.h" +#include "Menu.h" + HIFI_QML_DEF(LoginDialog) -LoginDialog::LoginDialog(QQuickItem *parent) : OffscreenQmlDialog(parent), _rootUrl(NetworkingConstants::METAVERSE_SERVER_URL.toString()) { +LoginDialog::LoginDialog(QQuickItem *parent) : OffscreenQmlDialog(parent), + _dialogFormat("rectangular"), + _rootUrl(NetworkingConstants::METAVERSE_SERVER_URL.toString()) +{ connect(&AccountManager::getInstance(), &AccountManager::loginComplete, this, &LoginDialog::handleLoginCompleted); connect(&AccountManager::getInstance(), &AccountManager::loginFailed, this, &LoginDialog::handleLoginFailed); + + connect(DependencyManager::get().data(), &DialogsManager::loginDialogFormatChanged, + this, &LoginDialog::updateDialogFormat); } void LoginDialog::toggleAction() { @@ -51,6 +59,25 @@ void LoginDialog::handleLoginFailed() { setStatusText("Invalid username or password.< / font>"); } +void LoginDialog::setDialogFormat(const QString& dialogFormat) { + if (dialogFormat != _dialogFormat) { + _dialogFormat = dialogFormat; + emit dialogFormatChanged(); + } +} + +QString LoginDialog::dialogFormat() const { + return _dialogFormat; +} + +void LoginDialog::updateDialogFormat() { + if (Menu::getInstance()->isOptionChecked(MenuOption::LoginDialogCircular)) { + setDialogFormat("circular"); + } else { + setDialogFormat("rectangular"); + } +} + void LoginDialog::setStatusText(const QString& statusText) { if (statusText != _statusText) { _statusText = statusText; diff --git a/interface/src/ui/LoginDialog.h b/interface/src/ui/LoginDialog.h index e9ae0a1c16..5761914642 100644 --- a/interface/src/ui/LoginDialog.h +++ b/interface/src/ui/LoginDialog.h @@ -1,5 +1,6 @@ // // LoginDialog.h +// interface/src/ui // // Created by Bradley Austin Davis on 2015/04/14 // Copyright 2015 High Fidelity, Inc. @@ -9,9 +10,12 @@ // #pragma once + #ifndef hifi_LoginDialog_h #define hifi_LoginDialog_h +#include "DialogsManager.h" // Need before OffscreenQmlDialog.h in order to get gl.h and glew.h includes in correct order. + #include class LoginDialog : public OffscreenQmlDialog @@ -19,6 +23,7 @@ class LoginDialog : public OffscreenQmlDialog Q_OBJECT HIFI_QML_DECL + Q_PROPERTY(QString dialogFormat READ dialogFormat WRITE setDialogFormat NOTIFY dialogFormatChanged) Q_PROPERTY(QString statusText READ statusText WRITE setStatusText NOTIFY statusTextChanged) Q_PROPERTY(QString rootUrl READ rootUrl) @@ -27,12 +32,17 @@ public: LoginDialog(QQuickItem* parent = nullptr); + void setDialogFormat(const QString& dialogFormat); + QString dialogFormat() const; + void updateDialogFormat(); // protected? + void setStatusText(const QString& statusText); QString statusText() const; QString rootUrl() const; signals: + void dialogFormatChanged(); void statusTextChanged(); protected: @@ -42,6 +52,7 @@ protected: Q_INVOKABLE void login(const QString& username, const QString& password); Q_INVOKABLE void openUrl(const QString& url); private: + QString _dialogFormat; QString _statusText; const QString _rootUrl; }; From a2f262f6595bec5ebd342e8355355237a67654a1 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 4 Jun 2015 18:48:21 -0700 Subject: [PATCH 06/34] Add basic username, password, login, and error functionality and styling --- interface/resources/qml/LoginDialog.qml | 180 +++++++++++++++++++----- interface/src/ui/LoginDialog.cpp | 4 +- 2 files changed, 148 insertions(+), 36 deletions(-) diff --git a/interface/resources/qml/LoginDialog.qml b/interface/resources/qml/LoginDialog.qml index 6db56d21bf..75adc30a1c 100644 --- a/interface/resources/qml/LoginDialog.qml +++ b/interface/resources/qml/LoginDialog.qml @@ -10,7 +10,6 @@ import Hifi 1.0 import QtQuick 2.4 -import QtQuick.Controls 1.3 // TODO: Needed? import "controls" import "styles" @@ -40,39 +39,148 @@ Dialog { implicitWidth: isCircular() ? circularBackground.width : rectangularBackground.width implicitHeight: isCircular() ? circularBackground.height : rectangularBackground.height + property int inputWidth: 500 + property int inputHeight: 60 + property int inputSpacing: isCircular() ? 24 : 16 + property int borderWidth: 30 + property int closeMargin: 16 + Image { id: circularBackground visible: isCircular() - source: "../images/login-circle.svg" - width: 500 - height: 500 + width: loginDialog.inputWidth * 1.2 + height: width } Image { id: rectangularBackground visible: !isCircular() - source: "../images/login-rectangle.svg" - width: 400 - height: 400 + width: loginDialog.inputWidth + loginDialog.borderWidth * 2 + height: loginDialog.inputHeight * 6 + } + + Image { + id: closeIcon + visible: !isCircular() + source: "../images/login-close.svg" + width: 20 + height: 20 + anchors { + top: rectangularBackground.top + right: rectangularBackground.right + topMargin: loginDialog.closeMargin + rightMargin: loginDialog.closeMargin + } + + MouseArea { + anchors.fill: parent + cursorShape: "PointingHandCursor" + onClicked: { + root.enabled = false + } + } + } + + Column { + id: mainContent + width: loginDialog.inputWidth + spacing: loginDialog.inputSpacing + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + } + + Rectangle { + width: loginDialog.inputWidth + height: loginDialog.inputHeight + radius: height / 2 + color: "#ebebeb" + + TextInput { + id: username + anchors.fill: parent + anchors.leftMargin: loginDialog.inputHeight / 2 + + helperText: "username or email" + + KeyNavigation.tab: password + KeyNavigation.backtab: password + } + } + + Rectangle { + width: loginDialog.inputWidth + height: loginDialog.inputHeight + radius: height / 2 + color: "#ebebeb" + + TextInput { + id: password + anchors.fill: parent + anchors.leftMargin: loginDialog.inputHeight / 2 + + helperText: "password" + echoMode: TextInput.Password + + KeyNavigation.tab: username + KeyNavigation.backtab: username + onFocusChanged: { + if (password.focus) { + password.selectAll() + } + } + } + } + + Text { + id: messageText + width: loginDialog.inputWidth + height: loginDialog.inputHeight / 2 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + text: loginDialog.statusText + } + + Rectangle { + width: loginDialog.inputWidth + height: loginDialog.inputHeight + radius: height / 2 + color: "#353535" + + TextInput { + anchors.fill: parent + text: "Login" + color: "white" + horizontalAlignment: Text.AlignHCenter + } + + MouseArea { + anchors.fill: parent + cursorShape: "PointingHandCursor" + onClicked: { + loginDialog.login(username.text, password.text) + } + } + } } Text { id: closeText visible: isCircular() + anchors { + horizontalCenter: parent.horizontalCenter + top: mainContent.bottom + topMargin: loginDialog.inputSpacing + } text: "Close" font.pixelSize: hifi.fonts.pixelSize * 0.8 font.weight: Font.Bold color: "#175d74" - anchors { - horizontalCenter: circularBackground.horizontalCenter - bottom: circularBackground.bottom - bottomMargin: hifi.layout.spacing * 4 - } - MouseArea { anchors.fill: parent cursorShape: "PointingHandCursor" @@ -81,29 +189,19 @@ Dialog { } } } + } - Image { - id: closeIcon - visible: !isCircular() + onEnabledChanged: { + if (enabled) { + username.forceActiveFocus(); + } + } - source: "../images/login-close.svg" - - width: 20 - height: 20 - anchors { - top: rectangularBackground.top - right: rectangularBackground.right - topMargin: hifi.layout.spacing * 2 - rightMargin: hifi.layout.spacing * 2 - } - - MouseArea { - anchors.fill: parent - cursorShape: "PointingHandCursor" - onClicked: { - root.enabled = false - } - } + onVisibleChanged: { + if (!visible) { + username.text = "" + password.text = "" + loginDialog.statusText = "" } } @@ -114,6 +212,20 @@ Dialog { enabled = false; event.accepted = true break + case Qt.Key_Enter: + case Qt.Key_Return: + if (username.activeFocus) { + event.accepted = true + password.forceActiveFocus() + } else if (password.activeFocus) { + event.accepted = true + if (username.text == "") { + username.forceActiveFocus() + } else { + loginDialog.login(username.text, password.text) + } + } + break; } } } diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index 4ed338c7db..a326d6a6d1 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -56,7 +56,7 @@ void LoginDialog::handleLoginCompleted(const QUrl&) { } void LoginDialog::handleLoginFailed() { - setStatusText("Invalid username or password.< / font>"); + setStatusText("Invalid username or password"); } void LoginDialog::setDialogFormat(const QString& dialogFormat) { @@ -95,7 +95,7 @@ QString LoginDialog::rootUrl() const { void LoginDialog::login(const QString& username, const QString& password) { qDebug() << "Attempting to login " << username; - setStatusText("Authenticating..."); + setStatusText("Logging in..."); AccountManager::getInstance().requestAccessToken(username, password); } From 2a40bbb02b502a39d0fa2bac5d425698b1193386 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 4 Jun 2015 22:27:23 -0700 Subject: [PATCH 07/34] Add remainder of dialog content and polish look --- .../resources/images/hifi-logo-blackish.svg | 123 ++++++++++++++++++ interface/resources/images/login-close.svg | 4 +- interface/resources/images/login-password.svg | 58 +++++++++ interface/resources/images/login-username.svg | 51 ++++++++ interface/resources/qml/LoginDialog.qml | 104 ++++++++++++++- .../resources/qml/styles/HifiConstants.qml | 3 +- 6 files changed, 333 insertions(+), 10 deletions(-) create mode 100644 interface/resources/images/hifi-logo-blackish.svg create mode 100644 interface/resources/images/login-password.svg create mode 100644 interface/resources/images/login-username.svg diff --git a/interface/resources/images/hifi-logo-blackish.svg b/interface/resources/images/hifi-logo-blackish.svg new file mode 100644 index 0000000000..60bfb3d418 --- /dev/null +++ b/interface/resources/images/hifi-logo-blackish.svg @@ -0,0 +1,123 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/interface/resources/images/login-close.svg b/interface/resources/images/login-close.svg index 88ca90b96f..2fb10c241b 100644 --- a/interface/resources/images/login-close.svg +++ b/interface/resources/images/login-close.svg @@ -35,7 +35,7 @@ id="namedview4139" showgrid="false" inkscape:zoom="4.8487496" - inkscape:cx="-11.452085" + inkscape:cx="-41.872299" inkscape:cy="37.53545" inkscape:window-x="77" inkscape:window-y="-8" @@ -48,7 +48,7 @@ d="M 38.400102,87.62655 C 28.705316,86.39839 21.084707,83.18102 13.982682,77.31765 5.5185024,70.329714 -0.09877759,60.244376 -1.7904936,48.998291 -2.1921426,46.328239 -2.2434696,39.677941 -1.8825126,37.07572 0.23131941,21.836625 9.4778634,8.9272213 23.005945,2.3281243 c 9.805646,-4.783264 20.444414,-5.902737 30.964952,-3.25830896 7.357662,1.849413 14.403738,5.75570696 19.976698,11.07495366 7.36697,7.031569 12.03213,16.084669 13.58981,26.37208 0.45133,2.980701 0.44981,9.518147 -0.003,12.481442 -0.72914,4.772737 -2.08456,9.199896 -4.04575,13.214497 -2.40852,4.930297 -4.94684,8.502038 -8.75077,12.313422 -6.78153,6.79482 -14.822805,10.95587 -24.504932,12.68035 -1.787127,0.3183 -3.134188,0.40875 -6.708441,0.45045 -2.459762,0.0287 -4.765789,0.0149 -5.124505,-0.0304 z m -3.02899,-27.869116 7.314939,-7.311007 7.360877,7.35692 7.360872,7.356917 4.983865,-4.982378 4.98386,-4.982378 -7.359111,-7.358686 -7.359105,-7.358687 7.359105,-7.358687 7.359111,-7.358686 -4.98387,-4.982383 -4.983864,-4.982384 -7.407456,7.393329 -7.407456,7.393328 -7.360652,-7.342464 -7.36065,-7.342467 -4.922357,4.916384 -4.922356,4.916381 7.300528,7.417269 7.300528,7.417267 -7.362706,7.362244 -7.362709,7.362244 4.890918,4.889465 c 2.690008,2.689205 4.974582,4.889463 5.076835,4.889463 0.102254,0 3.477639,-3.289951 7.500854,-7.311004 z" id="path4145" inkscape:connector-curvature="0" /> +image/svg+xml \ No newline at end of file diff --git a/interface/resources/images/login-username.svg b/interface/resources/images/login-username.svg new file mode 100644 index 0000000000..a40dd91cf7 --- /dev/null +++ b/interface/resources/images/login-username.svg @@ -0,0 +1,51 @@ + +image/svg+xml \ No newline at end of file diff --git a/interface/resources/qml/LoginDialog.qml b/interface/resources/qml/LoginDialog.qml index 75adc30a1c..f39eb7f5f2 100644 --- a/interface/resources/qml/LoginDialog.qml +++ b/interface/resources/qml/LoginDialog.qml @@ -58,7 +58,7 @@ Dialog { visible: !isCircular() source: "../images/login-rectangle.svg" width: loginDialog.inputWidth + loginDialog.borderWidth * 2 - height: loginDialog.inputHeight * 6 + height: loginDialog.inputHeight * 6 + loginDialog.closeMargin * 2 } Image { @@ -92,18 +92,39 @@ Dialog { verticalCenter: parent.verticalCenter } + Item { + // Offset content down a little + width: loginDialog.inputWidth + height: isCircular() ? loginDialog.inputHeight : loginDialog.closeMargin + } + Rectangle { width: loginDialog.inputWidth height: loginDialog.inputHeight radius: height / 2 color: "#ebebeb" + Image { + source: "../images/login-username.svg" + width: loginDialog.inputHeight * 0.65 + height: width + anchors { + verticalCenter: parent.verticalCenter + left: parent.left + leftMargin: loginDialog.inputHeight / 4 + } + } + TextInput { id: username - anchors.fill: parent - anchors.leftMargin: loginDialog.inputHeight / 2 + anchors { + fill: parent + leftMargin: loginDialog.inputHeight + rightMargin: loginDialog.inputHeight / 2 + } helperText: "username or email" + color: hifi.colors.text KeyNavigation.tab: password KeyNavigation.backtab: password @@ -116,13 +137,28 @@ Dialog { radius: height / 2 color: "#ebebeb" + Image { + source: "../images/login-password.svg" + width: loginDialog.inputHeight * 0.65 + height: width + anchors { + verticalCenter: parent.verticalCenter + left: parent.left + leftMargin: loginDialog.inputHeight / 4 + } + } + TextInput { id: password - anchors.fill: parent - anchors.leftMargin: loginDialog.inputHeight / 2 + anchors { + fill: parent + leftMargin: loginDialog.inputHeight + rightMargin: loginDialog.inputHeight / 2 + } helperText: "password" echoMode: TextInput.Password + color: hifi.colors.text KeyNavigation.tab: username KeyNavigation.backtab: username @@ -142,6 +178,7 @@ Dialog { verticalAlignment: Text.AlignVCenter text: loginDialog.statusText + color: "black" } Rectangle { @@ -165,6 +202,62 @@ Dialog { } } } + + Row { + anchors.horizontalCenter: parent.horizontalCenter + + Text { + text: "Forgot Password?" + font.pixelSize: hifi.fonts.pixelSize * 0.8 + font.underline: true + color: "#e0e0e0" + width: loginDialog.inputHeight * 4 + horizontalAlignment: Text.AlignRight + anchors.verticalCenter: parent.verticalCenter + + MouseArea { + anchors.fill: parent + cursorShape: "PointingHandCursor" + onClicked: { + loginDialog.openUrl(loginDialog.rootUrl + "/users/password/new") + } + } + } + + Item { + width: loginDialog.inputHeight + loginDialog.inputSpacing * 2 + height: loginDialog.inputHeight + + Image { + id: hifiIcon + source: "../images/hifi-logo-blackish.svg" + width: loginDialog.inputHeight + height: width + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + } + } + } + + Text { + text: "Register" + font.pixelSize: hifi.fonts.pixelSize * 0.8 + font.underline: true + color: "#e0e0e0" + width: loginDialog.inputHeight * 4 + horizontalAlignment: Text.AlignLeft + anchors.verticalCenter: parent.verticalCenter + + MouseArea { + anchors.fill: parent + cursorShape: "PointingHandCursor" + onClicked: { + loginDialog.openUrl(loginDialog.rootUrl + "/signup") + } + } + } + } } Text { @@ -178,7 +271,6 @@ Dialog { text: "Close" font.pixelSize: hifi.fonts.pixelSize * 0.8 - font.weight: Font.Bold color: "#175d74" MouseArea { diff --git a/interface/resources/qml/styles/HifiConstants.qml b/interface/resources/qml/styles/HifiConstants.qml index fa556f2083..c232b993d1 100644 --- a/interface/resources/qml/styles/HifiConstants.qml +++ b/interface/resources/qml/styles/HifiConstants.qml @@ -13,10 +13,9 @@ Item { readonly property color hifiBlue: "#0e7077" readonly property color window: sysPalette.window readonly property color dialogBackground: sysPalette.window - //readonly property color dialogBackground: "#00000000" readonly property color inputBackground: "white" readonly property color background: sysPalette.dark - readonly property color text: sysPalette.text + readonly property color text: "#202020" readonly property color disabledText: "gray" readonly property color hintText: "gray" // A bit darker than sysPalette.dark so that it is visible on the DK2 readonly property color light: sysPalette.light From ed60e409ab527310e4b5ba83d2f915e825971e0f Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 5 Jun 2015 08:22:36 -0700 Subject: [PATCH 08/34] Make login dialog able to be dragged --- interface/resources/qml/LoginDialog.qml | 82 +++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/interface/resources/qml/LoginDialog.qml b/interface/resources/qml/LoginDialog.qml index f39eb7f5f2..55859cb83d 100644 --- a/interface/resources/qml/LoginDialog.qml +++ b/interface/resources/qml/LoginDialog.qml @@ -44,6 +44,9 @@ Dialog { property int inputSpacing: isCircular() ? 24 : 16 property int borderWidth: 30 property int closeMargin: 16 + property int maximumX: parent ? parent.width - width : 0 + property int maximumY: parent ? parent.height - height : 0 + property real tan30: 0.577 // tan(30°) Image { id: circularBackground @@ -51,6 +54,69 @@ Dialog { source: "../images/login-circle.svg" width: loginDialog.inputWidth * 1.2 height: width + + Item { + // Approximage circle with 3 rectangles that together contain the circle in a hexagon. + anchors.fill: parent + + MouseArea { + width: parent.width + height: parent.width * loginDialog.tan30 + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + } + drag { + target: root + minimumX: -loginDialog.borderWidth + minimumY: -loginDialog.borderWidth + maximumX: root.parent ? root.maximumX + loginDialog.borderWidth : 0 + maximumY: root.parent ? root.maximumY + loginDialog.borderWidth : 0 + } + } + + MouseArea { + width: parent.width + height: parent.width * loginDialog.tan30 + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + } + transform: Rotation { + origin.x: width / 2 + origin.y: width * loginDialog.tan30 / 2 + angle: -60 + } + drag { + target: root + minimumX: -loginDialog.borderWidth + minimumY: -loginDialog.borderWidth + maximumX: root.parent ? root.maximumX + loginDialog.borderWidth : 0 + maximumY: root.parent ? root.maximumY + loginDialog.borderWidth : 0 + } + } + + MouseArea { + width: parent.width + height: parent.width * loginDialog.tan30 + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + } + transform: Rotation { + origin.x: width / 2 + origin.y: width * loginDialog.tan30 / 2 + angle: 60 + } + drag { + target: root + minimumX: -loginDialog.borderWidth + minimumY: -loginDialog.borderWidth + maximumX: root.parent ? root.maximumX + loginDialog.borderWidth : 0 + maximumY: root.parent ? root.maximumY + loginDialog.borderWidth : 0 + } + } + } } Image { @@ -59,6 +125,22 @@ Dialog { source: "../images/login-rectangle.svg" width: loginDialog.inputWidth + loginDialog.borderWidth * 2 height: loginDialog.inputHeight * 6 + loginDialog.closeMargin * 2 + + MouseArea { + width: parent.width + height: parent.height + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + } + drag { + target: root + minimumX: 0 + minimumY: 0 + maximumX: root.parent ? root.maximumX : 0 + maximumY: root.parent ? root.maximumY : 0 + } + } } Image { From 162395e7fe8e62566f27408eb280ed2be2cb4df6 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 5 Jun 2015 08:42:33 -0700 Subject: [PATCH 09/34] Make login password and register links work --- interface/src/ui/LoginDialog.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index a326d6a6d1..3de8b5adf1 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -101,4 +101,5 @@ void LoginDialog::login(const QString& username, const QString& password) { void LoginDialog::openUrl(const QString& url) { qDebug() << url; + Application::getInstance()->openUrl(url); } From 7819b5b5c3c1f425647651f0d74010cc86d598bd Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 5 Jun 2015 09:02:35 -0700 Subject: [PATCH 10/34] Fix setting focus at start-up when not logged in --- interface/resources/qml/LoginDialog.qml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/LoginDialog.qml b/interface/resources/qml/LoginDialog.qml index 55859cb83d..55a4fec34c 100644 --- a/interface/resources/qml/LoginDialog.qml +++ b/interface/resources/qml/LoginDialog.qml @@ -365,9 +365,10 @@ Dialog { } } - onEnabledChanged: { - if (enabled) { - username.forceActiveFocus(); + onOpacityChanged: { + // Set focus once animation is completed so that focus is set at start-up when not logged in + if (opacity == 1.0) { + username.forceActiveFocus() } } From 263f3053497a7b8126296338a890de3540bf0895 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 5 Jun 2015 09:03:46 -0700 Subject: [PATCH 11/34] White error text instead of black --- interface/resources/qml/LoginDialog.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/LoginDialog.qml b/interface/resources/qml/LoginDialog.qml index 55a4fec34c..b1d488e0cf 100644 --- a/interface/resources/qml/LoginDialog.qml +++ b/interface/resources/qml/LoginDialog.qml @@ -260,7 +260,7 @@ Dialog { verticalAlignment: Text.AlignVCenter text: loginDialog.statusText - color: "black" + color: "white" } Rectangle { From 34209fa671fa823e0f7bf837085e1f2198a22d83 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 5 Jun 2015 09:07:07 -0700 Subject: [PATCH 12/34] Remove unnecessary semicolons --- interface/resources/qml/AddressBarDialog.qml | 4 ++-- interface/resources/qml/ErrorDialog.qml | 4 ++-- interface/resources/qml/LoginDialog.qml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index b4f1b2b247..7fa6bb3481 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -101,7 +101,7 @@ Dialog { onEnabledChanged: { if (enabled) { - addressLine.forceActiveFocus(); + addressLine.forceActiveFocus() } } @@ -123,7 +123,7 @@ Dialog { switch (event.key) { case Qt.Key_Escape: case Qt.Key_Back: - enabled = false; + enabled = false event.accepted = true break case Qt.Key_Enter: diff --git a/interface/resources/qml/ErrorDialog.qml b/interface/resources/qml/ErrorDialog.qml index 51befb12a7..1757aee376 100644 --- a/interface/resources/qml/ErrorDialog.qml +++ b/interface/resources/qml/ErrorDialog.qml @@ -25,7 +25,7 @@ Dialog { onParentChanged: { if (visible && enabled) { - forceActiveFocus(); + forceActiveFocus() } } @@ -90,7 +90,7 @@ Dialog { anchors.fill: parent cursorShape: "PointingHandCursor" onClicked: { - content.accept(); + content.accept() } } } diff --git a/interface/resources/qml/LoginDialog.qml b/interface/resources/qml/LoginDialog.qml index b1d488e0cf..ba8c24f3a7 100644 --- a/interface/resources/qml/LoginDialog.qml +++ b/interface/resources/qml/LoginDialog.qml @@ -384,7 +384,7 @@ Dialog { switch (event.key) { case Qt.Key_Escape: case Qt.Key_Back: - enabled = false; + enabled = false event.accepted = true break case Qt.Key_Enter: @@ -400,7 +400,7 @@ Dialog { loginDialog.login(username.text, password.text) } } - break; + break } } } From 8682cfc14a88e3b13f4c048955e8ba8702a80103 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 5 Jun 2015 09:47:34 -0700 Subject: [PATCH 13/34] Change login password recovery link text --- interface/resources/qml/LoginDialog.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/LoginDialog.qml b/interface/resources/qml/LoginDialog.qml index ba8c24f3a7..d75f692827 100644 --- a/interface/resources/qml/LoginDialog.qml +++ b/interface/resources/qml/LoginDialog.qml @@ -289,7 +289,7 @@ Dialog { anchors.horizontalCenter: parent.horizontalCenter Text { - text: "Forgot Password?" + text: "Password?" font.pixelSize: hifi.fonts.pixelSize * 0.8 font.underline: true color: "#e0e0e0" From 84ab8277dfa9001fae5c7bbb0adcdbb591c19b0c Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 5 Jun 2015 12:57:40 -0700 Subject: [PATCH 14/34] Add spinner in place of "Logging in..." --- interface/resources/qml/LoginDialog.qml | 69 ++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 6 deletions(-) diff --git a/interface/resources/qml/LoginDialog.qml b/interface/resources/qml/LoginDialog.qml index d75f692827..0fa6ff43cc 100644 --- a/interface/resources/qml/LoginDialog.qml +++ b/interface/resources/qml/LoginDialog.qml @@ -252,15 +252,72 @@ Dialog { } } - Text { - id: messageText + Item { width: loginDialog.inputWidth height: loginDialog.inputHeight / 2 - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - text: loginDialog.statusText - color: "white" + Text { + id: messageText + + visible: loginDialog.statusText != "" && loginDialog.statusText != "Logging in..." + + width: loginDialog.inputWidth + height: loginDialog.inputHeight / 2 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + text: loginDialog.statusText + color: "white" + } + + Row { + id: messageSpinner + + visible: loginDialog.statusText == "Logging in..." + onVisibleChanged: visible ? messageSpinnerAnimation.restart() : messageSpinnerAnimation.stop() + + spacing: 24 + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + + Rectangle { + id: spinner1 + width: 10 + height: 10 + color: "#ebebeb" + opacity: 0.05 + } + + Rectangle { + id: spinner2 + width: 10 + height: 10 + color: "#ebebeb" + opacity: 0.05 + } + + Rectangle { + id: spinner3 + width: 10 + height: 10 + color: "#ebebeb" + opacity: 0.05 + } + + SequentialAnimation { + id: messageSpinnerAnimation + running: messageSpinner.visible + loops: Animation.Infinite + NumberAnimation { target: spinner1; property: "opacity"; to: 1.0; duration: 1000 } + NumberAnimation { target: spinner2; property: "opacity"; to: 1.0; duration: 1000 } + NumberAnimation { target: spinner3; property: "opacity"; to: 1.0; duration: 1000 } + NumberAnimation { target: spinner1; property: "opacity"; to: 0.05; duration: 0 } + NumberAnimation { target: spinner2; property: "opacity"; to: 0.05; duration: 0 } + NumberAnimation { target: spinner3; property: "opacity"; to: 0.05; duration: 0 } + } + } } Rectangle { From dbe57696d827318b2029be4d32b3dfef56050f83 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 5 Jun 2015 13:15:18 -0700 Subject: [PATCH 15/34] Replace login background SVGs with QML rectangles --- interface/resources/images/login-circle.svg | 3 --- interface/resources/images/login-rectangle.svg | 3 --- interface/resources/qml/LoginDialog.qml | 14 ++++++++++---- 3 files changed, 10 insertions(+), 10 deletions(-) delete mode 100644 interface/resources/images/login-circle.svg delete mode 100644 interface/resources/images/login-rectangle.svg diff --git a/interface/resources/images/login-circle.svg b/interface/resources/images/login-circle.svg deleted file mode 100644 index 8a98902e6b..0000000000 --- a/interface/resources/images/login-circle.svg +++ /dev/null @@ -1,3 +0,0 @@ - - -2015-06-02 19:43ZCanvas 1Login Circle diff --git a/interface/resources/images/login-rectangle.svg b/interface/resources/images/login-rectangle.svg deleted file mode 100644 index 774baf8193..0000000000 --- a/interface/resources/images/login-rectangle.svg +++ /dev/null @@ -1,3 +0,0 @@ - - -2015-06-02 19:42ZCanvas 1Login2 diff --git a/interface/resources/qml/LoginDialog.qml b/interface/resources/qml/LoginDialog.qml index 0fa6ff43cc..aa6cbb162d 100644 --- a/interface/resources/qml/LoginDialog.qml +++ b/interface/resources/qml/LoginDialog.qml @@ -48,12 +48,15 @@ Dialog { property int maximumY: parent ? parent.height - height : 0 property real tan30: 0.577 // tan(30°) - Image { + Rectangle { id: circularBackground visible: isCircular() - source: "../images/login-circle.svg" width: loginDialog.inputWidth * 1.2 height: width + radius: width / 2 + + color: "#2c86b1" + opacity: 0.85 Item { // Approximage circle with 3 rectangles that together contain the circle in a hexagon. @@ -119,12 +122,15 @@ Dialog { } } - Image { + Rectangle { id: rectangularBackground visible: !isCircular() - source: "../images/login-rectangle.svg" width: loginDialog.inputWidth + loginDialog.borderWidth * 2 height: loginDialog.inputHeight * 6 + loginDialog.closeMargin * 2 + radius: loginDialog.closeMargin * 2 + + color: "#2c86b1" + opacity: 0.85 MouseArea { width: parent.width From b1f2ffd00869521bb881b4fcc75c32616768cbfa Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 5 Jun 2015 13:23:06 -0700 Subject: [PATCH 16/34] Code review and tidying --- interface/resources/qml/ErrorDialog.qml | 2 -- interface/resources/qml/LoginDialog.qml | 10 +++++----- interface/resources/qml/controls/Dialog.qml | 4 ++-- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/interface/resources/qml/ErrorDialog.qml b/interface/resources/qml/ErrorDialog.qml index 1757aee376..26b18f4ffd 100644 --- a/interface/resources/qml/ErrorDialog.qml +++ b/interface/resources/qml/ErrorDialog.qml @@ -17,8 +17,6 @@ Dialog { id: root HifiConstants { id: hifi } - property bool destroyOnInvisible: true - Component.onCompleted: { enabled = true } diff --git a/interface/resources/qml/LoginDialog.qml b/interface/resources/qml/LoginDialog.qml index aa6cbb162d..3291fed0d0 100644 --- a/interface/resources/qml/LoginDialog.qml +++ b/interface/resources/qml/LoginDialog.qml @@ -39,14 +39,14 @@ Dialog { implicitWidth: isCircular() ? circularBackground.width : rectangularBackground.width implicitHeight: isCircular() ? circularBackground.height : rectangularBackground.height - property int inputWidth: 500 - property int inputHeight: 60 + readonly property int inputWidth: 500 + readonly property int inputHeight: 60 + readonly property int borderWidth: 30 + readonly property int closeMargin: 16 + readonly property real tan30: 0.577 // tan(30°) property int inputSpacing: isCircular() ? 24 : 16 - property int borderWidth: 30 - property int closeMargin: 16 property int maximumX: parent ? parent.width - width : 0 property int maximumY: parent ? parent.height - height : 0 - property real tan30: 0.577 // tan(30°) Rectangle { id: circularBackground diff --git a/interface/resources/qml/controls/Dialog.qml b/interface/resources/qml/controls/Dialog.qml index 63430bdae0..3cada90c3e 100644 --- a/interface/resources/qml/controls/Dialog.qml +++ b/interface/resources/qml/controls/Dialog.qml @@ -15,7 +15,7 @@ import "../styles" Item { id: root - property int animationDuration: hifi.effects.fadeInDuration + property bool destroyOnInvisible: true // The UI enables an object, rather than manipulating its visibility, so that we can do animations in both directions. @@ -32,7 +32,7 @@ Item { Behavior on opacity { // Animate opacity. NumberAnimation { - duration: animationDuration + duration: hifi.effects.fadeInDuration easing.type: Easing.OutCubic } } From 36312e7bb44d8945bac539031f55741049c06c54 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 5 Jun 2015 15:37:25 -0700 Subject: [PATCH 17/34] Remove circular login dialog variation --- interface/resources/qml/LoginDialog.qml | 116 ++---------------------- interface/src/Menu.cpp | 15 --- interface/src/Menu.h | 2 - interface/src/ui/DialogsManager.cpp | 4 - interface/src/ui/DialogsManager.h | 4 - interface/src/ui/LoginDialog.cpp | 26 +----- interface/src/ui/LoginDialog.h | 9 -- 7 files changed, 9 insertions(+), 167 deletions(-) diff --git a/interface/resources/qml/LoginDialog.qml b/interface/resources/qml/LoginDialog.qml index 3291fed0d0..e552532cbd 100644 --- a/interface/resources/qml/LoginDialog.qml +++ b/interface/resources/qml/LoginDialog.qml @@ -29,102 +29,23 @@ Dialog { property int maximumX: parent ? parent.width - width : 0 property int maximumY: parent ? parent.height - height : 0 - function isCircular() { - return loginDialog.dialogFormat == "circular" - } - LoginDialog { id: loginDialog - implicitWidth: isCircular() ? circularBackground.width : rectangularBackground.width - implicitHeight: isCircular() ? circularBackground.height : rectangularBackground.height + implicitWidth: backgroundRectangle.width + implicitHeight: backgroundRectangle.height readonly property int inputWidth: 500 readonly property int inputHeight: 60 readonly property int borderWidth: 30 readonly property int closeMargin: 16 readonly property real tan30: 0.577 // tan(30°) - property int inputSpacing: isCircular() ? 24 : 16 + readonly property int inputSpacing: 16 property int maximumX: parent ? parent.width - width : 0 property int maximumY: parent ? parent.height - height : 0 Rectangle { - id: circularBackground - visible: isCircular() - width: loginDialog.inputWidth * 1.2 - height: width - radius: width / 2 - - color: "#2c86b1" - opacity: 0.85 - - Item { - // Approximage circle with 3 rectangles that together contain the circle in a hexagon. - anchors.fill: parent - - MouseArea { - width: parent.width - height: parent.width * loginDialog.tan30 - anchors { - horizontalCenter: parent.horizontalCenter - verticalCenter: parent.verticalCenter - } - drag { - target: root - minimumX: -loginDialog.borderWidth - minimumY: -loginDialog.borderWidth - maximumX: root.parent ? root.maximumX + loginDialog.borderWidth : 0 - maximumY: root.parent ? root.maximumY + loginDialog.borderWidth : 0 - } - } - - MouseArea { - width: parent.width - height: parent.width * loginDialog.tan30 - anchors { - horizontalCenter: parent.horizontalCenter - verticalCenter: parent.verticalCenter - } - transform: Rotation { - origin.x: width / 2 - origin.y: width * loginDialog.tan30 / 2 - angle: -60 - } - drag { - target: root - minimumX: -loginDialog.borderWidth - minimumY: -loginDialog.borderWidth - maximumX: root.parent ? root.maximumX + loginDialog.borderWidth : 0 - maximumY: root.parent ? root.maximumY + loginDialog.borderWidth : 0 - } - } - - MouseArea { - width: parent.width - height: parent.width * loginDialog.tan30 - anchors { - horizontalCenter: parent.horizontalCenter - verticalCenter: parent.verticalCenter - } - transform: Rotation { - origin.x: width / 2 - origin.y: width * loginDialog.tan30 / 2 - angle: 60 - } - drag { - target: root - minimumX: -loginDialog.borderWidth - minimumY: -loginDialog.borderWidth - maximumX: root.parent ? root.maximumX + loginDialog.borderWidth : 0 - maximumY: root.parent ? root.maximumY + loginDialog.borderWidth : 0 - } - } - } - } - - Rectangle { - id: rectangularBackground - visible: !isCircular() + id: backgroundRectangle width: loginDialog.inputWidth + loginDialog.borderWidth * 2 height: loginDialog.inputHeight * 6 + loginDialog.closeMargin * 2 radius: loginDialog.closeMargin * 2 @@ -151,13 +72,12 @@ Dialog { Image { id: closeIcon - visible: !isCircular() source: "../images/login-close.svg" width: 20 height: 20 anchors { - top: rectangularBackground.top - right: rectangularBackground.right + top: backgroundRectangle.top + right: backgroundRectangle.right topMargin: loginDialog.closeMargin rightMargin: loginDialog.closeMargin } @@ -183,7 +103,7 @@ Dialog { Item { // Offset content down a little width: loginDialog.inputWidth - height: isCircular() ? loginDialog.inputHeight : loginDialog.closeMargin + height: loginDialog.closeMargin } Rectangle { @@ -404,28 +324,6 @@ Dialog { } } } - - Text { - id: closeText - visible: isCircular() - anchors { - horizontalCenter: parent.horizontalCenter - top: mainContent.bottom - topMargin: loginDialog.inputSpacing - } - - text: "Close" - font.pixelSize: hifi.fonts.pixelSize * 0.8 - color: "#175d74" - - MouseArea { - anchors.fill: parent - cursorShape: "PointingHandCursor" - onClicked: { - root.enabled = false - } - } - } } onOpacityChanged: { diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index b2b9553ea5..6242318170 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -571,21 +571,6 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowOwned); addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowHulls); - MenuWrapper* loginDialogFormatMenu = developerMenu->addMenu("Login Dialog"); - { - QActionGroup* dialogMenuFormatGroup = new QActionGroup(loginDialogFormatMenu); - - QAction* circularLoginDialog = addCheckableActionToQMenuAndActionHash(loginDialogFormatMenu, - MenuOption::LoginDialogCircular, 0, false, - dialogsManager.data(), SLOT(updateLoginDialogFormat())); - dialogMenuFormatGroup->addAction(circularLoginDialog); - - QAction* rectangularLoginDialog = addCheckableActionToQMenuAndActionHash(loginDialogFormatMenu, - MenuOption::LoginDialogRectangular, 0, true, - dialogsManager.data(), SLOT(updateLoginDialogFormat())); - dialogMenuFormatGroup->addAction(rectangularLoginDialog); - } - MenuWrapper* helpMenu = addMenu("Help"); addActionToQMenuAndActionHash(helpMenu, MenuOption::EditEntitiesHelp, 0, qApp, SLOT(showEditEntitiesHelp())); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index eb1bd94637..6107744abc 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -209,8 +209,6 @@ namespace MenuOption { const QString LoadRSSDKFile = "Load .rssdk file"; const QString LodTools = "LOD Tools"; const QString Login = "Login"; - const QString LoginDialogCircular = "Circular"; - const QString LoginDialogRectangular = "Rectangular"; const QString Log = "Log"; const QString LowVelocityFilter = "Low Velocity Filter"; const QString Mirror = "Mirror"; diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index 705f55586c..1170e3c3a6 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -50,10 +50,6 @@ void DialogsManager::showLoginDialog() { LoginDialog::show(); } -void DialogsManager::updateLoginDialogFormat() { - emit loginDialogFormatChanged(); -} - void DialogsManager::octreeStatsDetails() { if (!_octreeStatsDialog) { _octreeStatsDialog = new OctreeStatsDialog(qApp->getWindow(), qApp->getOcteeSceneStats()); diff --git a/interface/src/ui/DialogsManager.h b/interface/src/ui/DialogsManager.h index f7301f5444..fc2dad072b 100644 --- a/interface/src/ui/DialogsManager.h +++ b/interface/src/ui/DialogsManager.h @@ -47,15 +47,11 @@ public: QPointer getOctreeStatsDialog() const { return _octreeStatsDialog; } QPointer getPreferencesDialog() const { return _preferencesDialog; } -signals: - void loginDialogFormatChanged(); - public slots: void toggleAddressBar(); void toggleDiskCacheEditor(); void toggleLoginDialog(); void showLoginDialog(); - void updateLoginDialogFormat(); void octreeStatsDetails(); void cachesSizeDialog(); void editPreferences(); diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index 3de8b5adf1..eb6f3c0607 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -12,6 +12,7 @@ #include "LoginDialog.h" #include +#include #include "AccountManager.h" #include "DependencyManager.h" @@ -20,16 +21,12 @@ HIFI_QML_DEF(LoginDialog) LoginDialog::LoginDialog(QQuickItem *parent) : OffscreenQmlDialog(parent), - _dialogFormat("rectangular"), _rootUrl(NetworkingConstants::METAVERSE_SERVER_URL.toString()) { connect(&AccountManager::getInstance(), &AccountManager::loginComplete, this, &LoginDialog::handleLoginCompleted); connect(&AccountManager::getInstance(), &AccountManager::loginFailed, this, &LoginDialog::handleLoginFailed); - - connect(DependencyManager::get().data(), &DialogsManager::loginDialogFormatChanged, - this, &LoginDialog::updateDialogFormat); } void LoginDialog::toggleAction() { @@ -59,25 +56,6 @@ void LoginDialog::handleLoginFailed() { setStatusText("Invalid username or password"); } -void LoginDialog::setDialogFormat(const QString& dialogFormat) { - if (dialogFormat != _dialogFormat) { - _dialogFormat = dialogFormat; - emit dialogFormatChanged(); - } -} - -QString LoginDialog::dialogFormat() const { - return _dialogFormat; -} - -void LoginDialog::updateDialogFormat() { - if (Menu::getInstance()->isOptionChecked(MenuOption::LoginDialogCircular)) { - setDialogFormat("circular"); - } else { - setDialogFormat("rectangular"); - } -} - void LoginDialog::setStatusText(const QString& statusText) { if (statusText != _statusText) { _statusText = statusText; @@ -101,5 +79,5 @@ void LoginDialog::login(const QString& username, const QString& password) { void LoginDialog::openUrl(const QString& url) { qDebug() << url; - Application::getInstance()->openUrl(url); + QDesktopServices::openUrl(url); } diff --git a/interface/src/ui/LoginDialog.h b/interface/src/ui/LoginDialog.h index 5761914642..50c820aa07 100644 --- a/interface/src/ui/LoginDialog.h +++ b/interface/src/ui/LoginDialog.h @@ -14,8 +14,6 @@ #ifndef hifi_LoginDialog_h #define hifi_LoginDialog_h -#include "DialogsManager.h" // Need before OffscreenQmlDialog.h in order to get gl.h and glew.h includes in correct order. - #include class LoginDialog : public OffscreenQmlDialog @@ -23,7 +21,6 @@ class LoginDialog : public OffscreenQmlDialog Q_OBJECT HIFI_QML_DECL - Q_PROPERTY(QString dialogFormat READ dialogFormat WRITE setDialogFormat NOTIFY dialogFormatChanged) Q_PROPERTY(QString statusText READ statusText WRITE setStatusText NOTIFY statusTextChanged) Q_PROPERTY(QString rootUrl READ rootUrl) @@ -32,17 +29,12 @@ public: LoginDialog(QQuickItem* parent = nullptr); - void setDialogFormat(const QString& dialogFormat); - QString dialogFormat() const; - void updateDialogFormat(); // protected? - void setStatusText(const QString& statusText); QString statusText() const; QString rootUrl() const; signals: - void dialogFormatChanged(); void statusTextChanged(); protected: @@ -52,7 +44,6 @@ protected: Q_INVOKABLE void login(const QString& username, const QString& password); Q_INVOKABLE void openUrl(const QString& url); private: - QString _dialogFormat; QString _statusText; const QString _rootUrl; }; From 8c1ece88657035c4f94599a8b4ce53810fcfe11f Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 5 Jun 2015 15:57:09 -0700 Subject: [PATCH 18/34] Fix #include for Unix --- interface/src/ui/LoginDialog.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index eb6f3c0607..196ba5d29e 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -11,8 +11,9 @@ #include "LoginDialog.h" +#include + #include -#include #include "AccountManager.h" #include "DependencyManager.h" From 6f7c52d2cca4c50c52d00a9ca5168537e70e92e8 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 6 Jun 2015 10:42:49 -0700 Subject: [PATCH 19/34] Rename new Dialog to DialogContainer --- interface/resources/qml/AddressBarDialog.qml | 2 +- interface/resources/qml/ErrorDialog.qml | 2 +- interface/resources/qml/LoginDialog.qml | 2 +- .../resources/qml/controls/{Dialog.qml => DialogContainer.qml} | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename interface/resources/qml/controls/{Dialog.qml => DialogContainer.qml} (98%) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 7fa6bb3481..3377b20d87 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -13,7 +13,7 @@ import QtQuick 2.4 import "controls" import "styles" -Dialog { +DialogContainer { id: root HifiConstants { id: hifi } diff --git a/interface/resources/qml/ErrorDialog.qml b/interface/resources/qml/ErrorDialog.qml index 26b18f4ffd..76d9111d97 100644 --- a/interface/resources/qml/ErrorDialog.qml +++ b/interface/resources/qml/ErrorDialog.qml @@ -13,7 +13,7 @@ import QtQuick 2.4 import "controls" import "styles" -Dialog { +DialogContainer { id: root HifiConstants { id: hifi } diff --git a/interface/resources/qml/LoginDialog.qml b/interface/resources/qml/LoginDialog.qml index e552532cbd..8d5267f7f8 100644 --- a/interface/resources/qml/LoginDialog.qml +++ b/interface/resources/qml/LoginDialog.qml @@ -13,7 +13,7 @@ import QtQuick 2.4 import "controls" import "styles" -Dialog { +DialogContainer { id: root HifiConstants { id: hifi } diff --git a/interface/resources/qml/controls/Dialog.qml b/interface/resources/qml/controls/DialogContainer.qml similarity index 98% rename from interface/resources/qml/controls/Dialog.qml rename to interface/resources/qml/controls/DialogContainer.qml index 3cada90c3e..4aa4e45d67 100644 --- a/interface/resources/qml/controls/Dialog.qml +++ b/interface/resources/qml/controls/DialogContainer.qml @@ -1,5 +1,5 @@ // -// Dialog.qml +// DialogCommon.qml // // Created by David Rowe on 3 Jun 2015 // Copyright 2015 High Fidelity, Inc. From 77f2943877fc1ac6b9389887cf9c2fa38f945619 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 6 Jun 2015 10:48:07 -0700 Subject: [PATCH 20/34] Rename previous Dialog to VrDialog --- interface/resources/qml/Browser.qml | 2 +- interface/resources/qml/InfoView.qml | 2 +- interface/resources/qml/MarketplaceDialog.qml | 2 +- interface/resources/qml/MessageDialog.qml | 2 +- interface/resources/qml/TestDialog.qml | 2 +- .../resources/qml/controls/{DialogOld.qml => VrDialog.qml} | 0 6 files changed, 5 insertions(+), 5 deletions(-) rename interface/resources/qml/controls/{DialogOld.qml => VrDialog.qml} (100%) diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index 3de616e05b..947bf739fc 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -4,7 +4,7 @@ import QtWebKit 3.0 import "controls" import "styles" -DialogOld { +VrDialog { id: root HifiConstants { id: hifi } title: "Browser" diff --git a/interface/resources/qml/InfoView.qml b/interface/resources/qml/InfoView.qml index e97ebdeaf3..012f04f1fd 100644 --- a/interface/resources/qml/InfoView.qml +++ b/interface/resources/qml/InfoView.qml @@ -5,7 +5,7 @@ import QtQuick.Controls.Styles 1.3 import QtWebKit 3.0 import "controls" -DialogOld { +VrDialog { id: root width: 800 height: 800 diff --git a/interface/resources/qml/MarketplaceDialog.qml b/interface/resources/qml/MarketplaceDialog.qml index 4ad3c6515f..946f32e84a 100644 --- a/interface/resources/qml/MarketplaceDialog.qml +++ b/interface/resources/qml/MarketplaceDialog.qml @@ -5,7 +5,7 @@ import QtQuick.Controls.Styles 1.3 import QtWebKit 3.0 import "controls" -DialogOld { +VrDialog { title: "Test Dlg" id: testDialog objectName: "Browser" diff --git a/interface/resources/qml/MessageDialog.qml b/interface/resources/qml/MessageDialog.qml index 5c699e1f1f..e8b01df9d0 100644 --- a/interface/resources/qml/MessageDialog.qml +++ b/interface/resources/qml/MessageDialog.qml @@ -5,7 +5,7 @@ import QtQuick.Dialogs 1.2 import "controls" import "styles" -DialogOld { +VrDialog { id: root HifiConstants { id: hifi } property real spacing: hifi.layout.spacing diff --git a/interface/resources/qml/TestDialog.qml b/interface/resources/qml/TestDialog.qml index 3ae61fa054..e6675b7282 100644 --- a/interface/resources/qml/TestDialog.qml +++ b/interface/resources/qml/TestDialog.qml @@ -3,7 +3,7 @@ import QtQuick.Controls 1.2 import QtQuick.Controls.Styles 1.3 import "controls" -DialogOld { +VrDialog { title: "Test Dialog" id: testDialog objectName: "TestDialog" diff --git a/interface/resources/qml/controls/DialogOld.qml b/interface/resources/qml/controls/VrDialog.qml similarity index 100% rename from interface/resources/qml/controls/DialogOld.qml rename to interface/resources/qml/controls/VrDialog.qml From 119f37a1784f3a7e89120ae092dea1bf8a96c099 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sun, 7 Jun 2015 14:34:40 -0700 Subject: [PATCH 21/34] Working on SDK 0.6 --- cmake/externals/oglplus/CMakeLists.txt | 8 +++---- interface/src/devices/OculusManager.cpp | 28 +++++++------------------ libraries/render-utils/src/Model.cpp | 2 +- 3 files changed, 13 insertions(+), 25 deletions(-) diff --git a/cmake/externals/oglplus/CMakeLists.txt b/cmake/externals/oglplus/CMakeLists.txt index 13709c1fde..1ef67b5e9f 100644 --- a/cmake/externals/oglplus/CMakeLists.txt +++ b/cmake/externals/oglplus/CMakeLists.txt @@ -3,13 +3,13 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) include(ExternalProject) ExternalProject_Add( - ${EXTERNAL_NAME} - GIT_REPOSITORY https://github.com/matus-chochlik/oglplus.git - GIT_TAG 9660aaaf65c5a3f47e6c54827ae28ae1ec5c5deb + ${EXTERNAL_NAME} + URL http://softlayer-dal.dl.sourceforge.net/project/oglplus/oglplus-0.61.x/oglplus-0.61.0.zip + URL_MD5 bb55038c36c660d2b6c7be380414fa60 CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" - LOG_DOWNLOAD 1 + LOG_DOWNLOAD 1 ) ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index d6151200f8..24b378f4a4 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -270,7 +270,7 @@ void OculusManager::connect() { _sceneLayer.ColorTexture[1] = nullptr; _sceneLayer.Viewport[0].Pos = { 0, 0 }; _sceneLayer.Viewport[0].Size = _recommendedTexSize; - _sceneLayer.Viewport[1].Pos = { _recommendedTexSize.x, 0 }; + _sceneLayer.Viewport[1].Pos = { _recommendedTexSize.w, 0 }; _sceneLayer.Viewport[1].Size = _recommendedTexSize; _sceneLayer.Header.Type = ovrLayerType_EyeFov; _sceneLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft; @@ -344,10 +344,10 @@ void OculusManager::disconnect() { } #endif - if (_ovrHmd) { + if (_ovrHmd) { ovrHmd_Destroy(_ovrHmd); _ovrHmd = nullptr; - } + } ovr_Shutdown(); _isConnected = false; @@ -586,9 +586,6 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati glm::vec3 trackerPosition; auto deviceSize = qApp->getDeviceSize(); -#ifndef Q_OS_WIN - ovrHmd_BeginFrame(_ovrHmd, _frameIndex); -#endif ovrTrackingState ts = ovrHmd_GetTrackingState(_ovrHmd, ovr_GetTimeInSeconds()); ovrVector3f ovrHeadPosition = ts.HeadPose.ThePose.Position; @@ -604,7 +601,9 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati static ovrVector3f eyeOffsets[2] = { { 0, 0, 0 }, { 0, 0, 0 } }; ovrPosef eyePoses[ovrEye_Count]; ovrHmd_GetEyePoses(_ovrHmd, _frameIndex, eyeOffsets, eyePoses, nullptr); +#ifndef Q_OS_WIN ovrHmd_BeginFrame(_ovrHmd, _frameIndex); +#endif static ovrPosef eyeRenderPose[ovrEye_Count]; //Render each eye into an fbo for_each_eye(_ovrHmd, [&](ovrEyeType eye){ @@ -652,7 +651,7 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati glViewport(vp.Pos.x, vp.Pos.y, vp.Size.w, vp.Size.h); qApp->displaySide(*_camera, false, RenderArgs::MONO); - qApp->getApplicationOverlay().displayOve rlayTextureHmd(*_camera); + qApp->getApplicationOverlay().displayOverlayTextureHmd(*_camera); }); _activeEye = ovrEye_Count; @@ -692,21 +691,10 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati GL_COLOR_BUFFER_BIT, GL_NEAREST); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - ovrLayerEyeFov sceneLayer; - sceneLayer.ColorTexture[0] = _swapFbo->color; - sceneLayer.ColorTexture[1] = nullptr; - - sceneLayer.Viewport[0].Pos = { 0, 0 }; - sceneLayer.Viewport[0].Size = { _swapFbo->size.x / 2, _swapFbo->size.y }; - sceneLayer.Viewport[1].Pos = { _swapFbo->size.x / 2, 0 }; - sceneLayer.Viewport[1].Size = { _swapFbo->size.x / 2, _swapFbo->size.y }; - sceneLayer.Header.Type = ovrLayerType_EyeFov; - sceneLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft; for_each_eye([&](ovrEyeType eye) { - sceneLayer.Fov[eye] = _eyeFov[eye]; - sceneLayer.RenderPose[eye] = eyeRenderPose[eye]; + _sceneLayer.RenderPose[eye] = eyeRenderPose[eye]; }); - auto header = &sceneLayer.Header; + auto header = &_sceneLayer.Header; ovrResult res = ovrHmd_SubmitFrame(_ovrHmd, _frameIndex, nullptr, &header, 1); Q_ASSERT(OVR_SUCCESS(res)); _swapFbo->Increment(); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index feddf61405..483ea6177e 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1412,7 +1412,7 @@ void Model::simulate(float deltaTime, bool fullUpdate) { if (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint) { snapToRegistrationPoint(); } - //simulateInternal(deltaTime); + simulateInternal(deltaTime); } } From 6a60da2a6c5de3fdeda6aeb0087a013a133572bc Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Sun, 7 Jun 2015 17:58:33 -0700 Subject: [PATCH 22/34] Working on SDK 0.6 --- interface/src/devices/OculusManager.cpp | 39 +++++++++++++++---------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 24b378f4a4..f177aa3097 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -219,6 +219,7 @@ void OculusManager::deinit() { } void OculusManager::connect() { + qCDebug(interfaceapp) << "Oculus SDK" << OVR_VERSION_STRING; ovrInitParams initParams; memset(&initParams, 0, sizeof(initParams)); #ifdef DEBUG @@ -245,10 +246,13 @@ void OculusManager::connect() { } #endif + _isConnected = false; + + // we're definitely not in "VR mode" so tell the menu that + Menu::getInstance()->getActionForOption(MenuOption::EnableVRMode)->setChecked(false); + #endif _calibrationState = UNCALIBRATED; - qCDebug(interfaceapp) << "Oculus SDK" << OVR_VERSION_STRING; - if (_ovrHmd) { if (!_isConnected) { UserActivityLogger::getInstance().connectedDevice("hmd", "oculus"); } @@ -677,6 +681,7 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati #ifdef Q_OS_WIN auto srcFboSize = finalFbo->getSize(); + // Blit to the oculus provided texture glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(finalFbo)); _swapFbo->Bound(oglplus::Framebuffer::Target::Draw, [&] { glBlitFramebuffer( @@ -684,6 +689,8 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati 0, 0, _swapFbo->size.x, _swapFbo->size.y, GL_COLOR_BUFFER_BIT, GL_NEAREST); }); + + // Blit to the onscreen window auto destWindowSize = qApp->getDeviceSize(); glBlitFramebuffer( 0, 0, srcFboSize.x, srcFboSize.y, @@ -691,6 +698,7 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati GL_COLOR_BUFFER_BIT, GL_NEAREST); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + // Submit the frame to the Oculus SDK for timewarp and distortion for_each_eye([&](ovrEyeType eye) { _sceneLayer.RenderPose[eye] = eyeRenderPose[eye]; }); @@ -705,23 +713,22 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati glEyeTexture.OGL.TexId = textureId; }); - //ovrHmd_EndFrame(_ovrHmd, eyeRenderPose, _eyeTextures); - glClearColor(0, 0, 0, 1); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - auto srcFboSize = finalFbo->getSize(); - glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(finalFbo)); - auto destWindowSize = qApp->getDeviceSize(); - glBlitFramebuffer( - 0, 0, srcFboSize.x, srcFboSize.y, - 0, 0, destWindowSize.width(), destWindowSize.height(), - GL_COLOR_BUFFER_BIT, GL_NEAREST); - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - glCanvas->swapBuffers(); + // restore our normal viewport + glViewport(0, 0, deviceSize.width(), deviceSize.height()); + ovrHmd_EndFrame(_ovrHmd, eyeRenderPose, _eyeTextures); + +// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +// auto srcFboSize = finalFbo->getSize(); +// glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(finalFbo)); +// glBlitFramebuffer( +// 0, 0, srcFboSize.x, srcFboSize.y, +// 0, 0, deviceSize.width(), deviceSize.height(), +// GL_COLOR_BUFFER_BIT, GL_NEAREST); +// glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); +// glCanvas->swapBuffers(); #endif - // restore our normal viewport - glViewport(0, 0, deviceSize.width(), deviceSize.height()); } //Tries to reconnect to the sensors From de268c47b3e73ff3dbaadb7af040defaeab1c20a Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sun, 7 Jun 2015 18:25:16 -0700 Subject: [PATCH 23/34] Working on 0.6 --- interface/src/Application.cpp | 3 +- interface/src/devices/OculusManager.cpp | 174 +++++++++++++----------- interface/src/devices/OculusManager.h | 5 +- 3 files changed, 98 insertions(+), 84 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 93f6217cb9..84aaa2297f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1860,8 +1860,7 @@ void Application::setEnableVRMode(bool enableVRMode) { // attempt to reconnect the Oculus manager - it's possible this was a workaround // for the sixense crash OculusManager::disconnect(); - _glWidget->makeCurrent(); - OculusManager::connect(); + OculusManager::connect(_glWidget->context()->contextHandle()); } OculusManager::recalibrate(); } else { diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index f177aa3097..8e5866a1ef 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -177,6 +178,7 @@ ovrLayerEyeFov OculusManager::_sceneLayer; #else ovrTexture OculusManager::_eyeTextures[ovrEye_Count]; +GlWindow* OculusManager::_outputWindow{ nullptr }; #endif @@ -197,12 +199,12 @@ float OculusManager::CALIBRATION_DELTA_MINIMUM_LENGTH = 0.02f; float OculusManager::CALIBRATION_DELTA_MINIMUM_ANGLE = 5.0f * RADIANS_PER_DEGREE; float OculusManager::CALIBRATION_ZERO_MAXIMUM_LENGTH = 0.01f; float OculusManager::CALIBRATION_ZERO_MAXIMUM_ANGLE = 2.0f * RADIANS_PER_DEGREE; -quint64 OculusManager::CALIBRATION_ZERO_HOLD_TIME = 3000000; // usec +uint64_t OculusManager::CALIBRATION_ZERO_HOLD_TIME = 3000000; // usec float OculusManager::CALIBRATION_MESSAGE_DISTANCE = 2.5f; OculusManager::CalibrationState OculusManager::_calibrationState; glm::vec3 OculusManager::_calibrationPosition; glm::quat OculusManager::_calibrationOrientation; -quint64 OculusManager::_calibrationStartTime; +uint64_t OculusManager::_calibrationStartTime; int OculusManager::_calibrationMessage = 0; glm::vec3 OculusManager::_eyePositions[ovrEye_Count]; // TODO expose this as a developer toggle @@ -218,13 +220,15 @@ void OculusManager::init() { void OculusManager::deinit() { } -void OculusManager::connect() { +void OculusManager::connect(QOpenGLContext* shareContext) { qCDebug(interfaceapp) << "Oculus SDK" << OVR_VERSION_STRING; ovrInitParams initParams; memset(&initParams, 0, sizeof(initParams)); + #ifdef DEBUG - //initParams.Flags |= ovrInit_Debug; + initParams.Flags |= ovrInit_Debug; #endif + ovr_Initialize(&initParams); #ifdef Q_OS_WIN @@ -246,89 +250,97 @@ void OculusManager::connect() { } #endif - _isConnected = false; - - // we're definitely not in "VR mode" so tell the menu that - Menu::getInstance()->getActionForOption(MenuOption::EnableVRMode)->setChecked(false); - #endif + + if (!_ovrHmd) { + _isConnected = false; + // we're definitely not in "VR mode" so tell the menu that + Menu::getInstance()->getActionForOption(MenuOption::EnableVRMode)->setChecked(false); + ovr_Shutdown(); + return; + } + _calibrationState = UNCALIBRATED; - if (!_isConnected) { - UserActivityLogger::getInstance().connectedDevice("hmd", "oculus"); - } - _isConnected = true; + if (!_isConnected) { + UserActivityLogger::getInstance().connectedDevice("hmd", "oculus"); + } + _isConnected = true; - for_each_eye([&](ovrEyeType eye) { - _eyeFov[eye] = _ovrHmd->DefaultEyeFov[eye]; - }); + for_each_eye([&](ovrEyeType eye) { + _eyeFov[eye] = _ovrHmd->DefaultEyeFov[eye]; + }); - _recommendedTexSize = ovrHmd_GetFovTextureSize(_ovrHmd, ovrEye_Left, _eyeFov[ovrEye_Left], 1.0f); - _renderTargetSize = { _recommendedTexSize.w * 2, _recommendedTexSize.h }; + _recommendedTexSize = ovrHmd_GetFovTextureSize(_ovrHmd, ovrEye_Left, _eyeFov[ovrEye_Left], 1.0f); + _renderTargetSize = { _recommendedTexSize.w * 2, _recommendedTexSize.h }; #ifdef Q_OS_WIN - _mirrorFbo = new MirrorFramebufferWrapper(_ovrHmd); - _swapFbo = new SwapFramebufferWrapper(_ovrHmd); - _swapFbo->Init(toGlm(_renderTargetSize)); - _sceneLayer.ColorTexture[0] = _swapFbo->color; - _sceneLayer.ColorTexture[1] = nullptr; - _sceneLayer.Viewport[0].Pos = { 0, 0 }; - _sceneLayer.Viewport[0].Size = _recommendedTexSize; - _sceneLayer.Viewport[1].Pos = { _recommendedTexSize.w, 0 }; - _sceneLayer.Viewport[1].Size = _recommendedTexSize; - _sceneLayer.Header.Type = ovrLayerType_EyeFov; - _sceneLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft; - for_each_eye([&](ovrEyeType eye) { - _eyeViewports[eye] = _sceneLayer.Viewport[eye]; - _sceneLayer.Fov[eye] = _eyeFov[eye]; - }); + _mirrorFbo = new MirrorFramebufferWrapper(_ovrHmd); + _swapFbo = new SwapFramebufferWrapper(_ovrHmd); + _swapFbo->Init(toGlm(_renderTargetSize)); + _sceneLayer.ColorTexture[0] = _swapFbo->color; + _sceneLayer.ColorTexture[1] = nullptr; + _sceneLayer.Viewport[0].Pos = { 0, 0 }; + _sceneLayer.Viewport[0].Size = _recommendedTexSize; + _sceneLayer.Viewport[1].Pos = { _recommendedTexSize.w, 0 }; + _sceneLayer.Viewport[1].Size = _recommendedTexSize; + _sceneLayer.Header.Type = ovrLayerType_EyeFov; + _sceneLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft; + for_each_eye([&](ovrEyeType eye) { + _eyeViewports[eye] = _sceneLayer.Viewport[eye]; + _sceneLayer.Fov[eye] = _eyeFov[eye]; + }); + + #else - ovrGLConfig cfg; - memset(&cfg, 0, sizeof(cfg)); - cfg.OGL.Header.API = ovrRenderAPI_OpenGL; - cfg.OGL.Header.BackBufferSize = _ovrHmd->Resolution; - cfg.OGL.Header.Multisample = 1; + _outputWindow = new GlWindow(shareContext); + _outputWindow->show(); + _outputWindow->setFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); + _outputWindow->resize(_ovrHmd->Resolution.w, _ovrHmd->Resolution.h); + // _outputWindow->setPosition(_ovrHmd->Position.x, _ovrHmd->Position.y); + _outputWindow->makeCurrent(); - int distortionCaps = 0 - | ovrDistortionCap_Vignette - | ovrDistortionCap_Overdrive - | ovrDistortionCap_TimeWarp; + ovrGLConfig cfg; + memset(&cfg, 0, sizeof(cfg)); + cfg.OGL.Header.API = ovrRenderAPI_OpenGL; + cfg.OGL.Header.BackBufferSize = _ovrHmd->Resolution; + cfg.OGL.Header.Multisample = 0; - int configResult = ovrHmd_ConfigureRendering(_ovrHmd, &cfg.Config, - distortionCaps, _eyeFov, _eyeRenderDesc); - assert(configResult); + int distortionCaps = 0 + | ovrDistortionCap_Vignette + | ovrDistortionCap_Overdrive + | ovrDistortionCap_TimeWarp; + + int configResult = ovrHmd_ConfigureRendering(_ovrHmd, &cfg.Config, + distortionCaps, _eyeFov, _eyeRenderDesc); + assert(configResult); - for_each_eye([&](ovrEyeType eye) { - //Get texture size - _eyeTextures[eye].Header.API = ovrRenderAPI_OpenGL; - _eyeTextures[eye].Header.TextureSize = _renderTargetSize; - _eyeTextures[eye].Header.RenderViewport.Pos = { 0, 0 }; - _eyeTextures[eye].Header.RenderViewport.Size = _renderTargetSize; - _eyeTextures[eye].Header.RenderViewport.Size.w /= 2; - }); - _eyeTextures[ovrEye_Right].Header.RenderViewport.Pos.x = _recommendedTexSize.w; - for_each_eye([&](ovrEyeType eye) { - _eyeViewports[eye] = _eyeTextures[eye].Header.RenderViewport; - }); + for_each_eye([&](ovrEyeType eye) { + //Get texture size + _eyeTextures[eye].Header.API = ovrRenderAPI_OpenGL; + _eyeTextures[eye].Header.TextureSize = _renderTargetSize; + _eyeTextures[eye].Header.RenderViewport.Pos = { 0, 0 }; + _eyeTextures[eye].Header.RenderViewport.Size = _renderTargetSize; + _eyeTextures[eye].Header.RenderViewport.Size.w /= 2; + }); + _eyeTextures[ovrEye_Right].Header.RenderViewport.Pos.x = _recommendedTexSize.w; + for_each_eye([&](ovrEyeType eye) { + _eyeViewports[eye] = _eyeTextures[eye].Header.RenderViewport; + }); #endif - ovrHmd_SetEnabledCaps(_ovrHmd, ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction); + ovrHmd_SetEnabledCaps(_ovrHmd, + ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction); - ovrHmd_ConfigureTracking(_ovrHmd, ovrTrackingCap_Orientation | ovrTrackingCap_Position | - ovrTrackingCap_MagYawCorrection, - ovrTrackingCap_Orientation); + ovrHmd_ConfigureTracking(_ovrHmd, + ovrTrackingCap_Orientation | ovrTrackingCap_Position | ovrTrackingCap_MagYawCorrection, + ovrTrackingCap_Orientation); - if (!_camera) { - _camera = new Camera; - configureCamera(*_camera); // no need to use screen dimensions; they're ignored - } - } else { - _isConnected = false; - - // we're definitely not in "VR mode" so tell the menu that - Menu::getInstance()->getActionForOption(MenuOption::EnableVRMode)->setChecked(false); + if (!_camera) { + _camera = new Camera; + configureCamera(*_camera); // no need to use screen dimensions; they're ignored } } @@ -460,7 +472,6 @@ void OculusManager::calibrate(glm::vec3 position, glm::quat orientation) { break; default: break; - } } @@ -713,19 +724,20 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati glEyeTexture.OGL.TexId = textureId; }); + _outputWindow->makeCurrent(); // restore our normal viewport - glViewport(0, 0, deviceSize.width(), deviceSize.height()); ovrHmd_EndFrame(_ovrHmd, eyeRenderPose, _eyeTextures); -// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); -// auto srcFboSize = finalFbo->getSize(); -// glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(finalFbo)); -// glBlitFramebuffer( -// 0, 0, srcFboSize.x, srcFboSize.y, -// 0, 0, deviceSize.width(), deviceSize.height(), -// GL_COLOR_BUFFER_BIT, GL_NEAREST); -// glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); -// glCanvas->swapBuffers(); + //auto outputSize = _outputWindow->size(); + //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + //auto srcFboSize = finalFbo->getSize(); + //glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(finalFbo)); + //glBlitFramebuffer( + // 0, 0, srcFboSize.x, srcFboSize.y, + // 0, 0, outputSize.width(), outputSize.height(), + // GL_COLOR_BUFFER_BIT, GL_NEAREST); + //glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + //glCanvas->swapBuffers(); #endif diff --git a/interface/src/devices/OculusManager.h b/interface/src/devices/OculusManager.h index d07a22fbd1..81377870eb 100644 --- a/interface/src/devices/OculusManager.h +++ b/interface/src/devices/OculusManager.h @@ -20,7 +20,9 @@ #include #include +class QOpenGLContext; class Camera; +class GlWindow; class PalmData; class Text3DOverlay; @@ -35,7 +37,7 @@ class OculusManager { public: static void init(); static void deinit(); - static void connect(); + static void connect(QOpenGLContext* shareContext); static void disconnect(); static bool isConnected(); static void recalibrate(); @@ -113,6 +115,7 @@ private: static ovrLayerEyeFov _sceneLayer; #else static ovrTexture _eyeTextures[ovrEye_Count]; + static GlWindow* _outputWindow; #endif }; From 5a52a389bebf5a2f89bb71136dfd62efbb9ef457 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Sun, 7 Jun 2015 23:23:21 -0700 Subject: [PATCH 24/34] Working on SDK 0.6 --- interface/src/Application.cpp | 3 ++ interface/src/avatar/SkeletonModel.cpp | 4 ++ interface/src/devices/OculusManager.cpp | 66 +++++++++++-------------- interface/src/devices/OculusManager.h | 4 ++ interface/src/ui/ApplicationOverlay.cpp | 2 +- interface/src/ui/HMDToolsDialog.cpp | 2 +- libraries/shared/src/OglplusHelpers.h | 4 +- 7 files changed, 42 insertions(+), 43 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 84aaa2297f..4f314eeb2c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1861,6 +1861,9 @@ void Application::setEnableVRMode(bool enableVRMode) { // for the sixense crash OculusManager::disconnect(); OculusManager::connect(_glWidget->context()->contextHandle()); + _glWidget->setFocus(); + _glWidget->makeCurrent(); + glClear(GL_COLOR_BUFFER_BIT); } OculusManager::recalibrate(); } else { diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index e2f4ca51a0..5ccda4d288 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -258,6 +258,10 @@ void SkeletonModel::updateJointState(int index) { JointState& state = _jointStates[index]; const FBXJoint& joint = state.getFBXJoint(); if (joint.parentIndex != -1) { + if (joint.parentIndex < 0 || joint.parentIndex >= _jointStates.size()) { + qDebug() << "Bad parent index"; + return; + } const JointState& parentState = _jointStates.at(joint.parentIndex); const FBXGeometry& geometry = _geometry->getFBXGeometry(); if (index == geometry.leanJointIndex) { diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 8e5866a1ef..5353d1cd55 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -177,6 +177,7 @@ ovrLayerEyeFov OculusManager::_sceneLayer; #else +BasicFramebufferWrapper* _transferFbo; ovrTexture OculusManager::_eyeTextures[ovrEye_Count]; GlWindow* OculusManager::_outputWindow{ nullptr }; @@ -296,11 +297,24 @@ void OculusManager::connect(QOpenGLContext* shareContext) { #else _outputWindow = new GlWindow(shareContext); _outputWindow->show(); - _outputWindow->setFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); - _outputWindow->resize(_ovrHmd->Resolution.w, _ovrHmd->Resolution.h); - // _outputWindow->setPosition(_ovrHmd->Position.x, _ovrHmd->Position.y); +// _outputWindow->setFlags(Qt::FramelessWindowHint ); +// _outputWindow->resize(_ovrHmd->Resolution.w, _ovrHmd->Resolution.h); +// _outputWindow->setPosition(_ovrHmd->WindowsPos.x, _ovrHmd->WindowsPos.y); + ivec2 desiredPosition = toGlm(_ovrHmd->WindowsPos); + foreach(QScreen* screen, qGuiApp->screens()) { + ivec2 screenPosition = toGlm(screen->geometry().topLeft()); + if (screenPosition == desiredPosition) { + _outputWindow->setScreen(screen); + break; + } + } + _outputWindow->showFullScreen(); _outputWindow->makeCurrent(); - + _transferFbo = new BasicFramebufferWrapper(); + _transferFbo->Init(toGlm(_renderTargetSize)); + + + ovrGLConfig cfg; memset(&cfg, 0, sizeof(cfg)); cfg.OGL.Header.API = ovrRenderAPI_OpenGL; @@ -315,7 +329,7 @@ void OculusManager::connect(QOpenGLContext* shareContext) { int configResult = ovrHmd_ConfigureRendering(_ovrHmd, &cfg.Config, distortionCaps, _eyeFov, _eyeRenderDesc); assert(configResult); - + _outputWindow->doneCurrent(); for_each_eye([&](ovrEyeType eye) { //Get texture size @@ -358,6 +372,10 @@ void OculusManager::disconnect() { delete _mirrorFbo; _mirrorFbo = nullptr; } +#else + _outputWindow->showNormal(); + _outputWindow->deleteLater(); + _outputWindow = nullptr; #endif if (_ovrHmd) { @@ -535,28 +553,11 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati assert(oldFrameIndex == -1 || (unsigned int)oldFrameIndex == _frameIndex - 1); oldFrameIndex = _frameIndex; #endif - - // Every so often do some additional timing calculations and debug output - bool debugFrame = 0 == _frameIndex % 400; -#if 0 - // Try to measure the amount of time taken to do the distortion - // (does not seem to work on OSX with SDK based distortion) - // FIXME can't use a static object here, because it will cause a crash when the - // query attempts deconstruct after the GL context is gone. - static bool timerActive = false; - static QOpenGLTimerQuery timerQuery; - if (!timerQuery.isCreated()) { - timerQuery.create(); + if (_outputWindow->visibility() != QWindow::FullScreen) { + // _outputWindow->showFullScreen(); } - if (timerActive && timerQuery.isResultAvailable()) { - auto result = timerQuery.waitForResult(); - if (result) { qCDebug(interfaceapp) << "Distortion took " << result << "ns"; }; - timerActive = false; - } -#endif - #ifndef Q_OS_WIN // FIXME: we need a better way of responding to the HSW. In particular // we need to ensure that it's only displayed once per session, rather than @@ -573,7 +574,6 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati } } #endif - //beginFrameTiming must be called before display if (!_frameTimingActive) { @@ -718,26 +718,16 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati Q_ASSERT(OVR_SUCCESS(res)); _swapFbo->Increment(); #else + glFinish(); GLuint textureId = gpu::GLBackend::getTextureID(finalFbo->getRenderBuffer(0)); + _outputWindow->makeCurrent(); for_each_eye([&](ovrEyeType eye) { ovrGLTexture & glEyeTexture = reinterpret_cast(_eyeTextures[eye]); glEyeTexture.OGL.TexId = textureId; }); - - _outputWindow->makeCurrent(); // restore our normal viewport ovrHmd_EndFrame(_ovrHmd, eyeRenderPose, _eyeTextures); - - //auto outputSize = _outputWindow->size(); - //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - //auto srcFboSize = finalFbo->getSize(); - //glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(finalFbo)); - //glBlitFramebuffer( - // 0, 0, srcFboSize.x, srcFboSize.y, - // 0, 0, outputSize.width(), outputSize.height(), - // GL_COLOR_BUFFER_BIT, GL_NEAREST); - //glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - //glCanvas->swapBuffers(); + glCanvas->makeCurrent(); #endif diff --git a/interface/src/devices/OculusManager.h b/interface/src/devices/OculusManager.h index 81377870eb..03e754c40a 100644 --- a/interface/src/devices/OculusManager.h +++ b/interface/src/devices/OculusManager.h @@ -136,6 +136,10 @@ inline glm::vec2 toGlm(const ovrVector2f & ov) { return glm::make_vec2(&ov.x); } +inline glm::ivec2 toGlm(const ovrVector2i & ov) { + return glm::ivec2(ov.x, ov.y); +} + inline glm::uvec2 toGlm(const ovrSizei & ov) { return glm::uvec2(ov.w, ov.h); } diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index d9d2a1d971..7213635065 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -349,7 +349,7 @@ void ApplicationOverlay::displayOverlayTextureHmd(Camera& whichCamera) { textureAspectRatio = _textureAspectRatio; _overlays.buildVBO(_textureFov, _textureAspectRatio, 80, 80); - } + } with_each_texture(_overlays.getTexture(), _newUiTexture, [&] { _overlays.render(); diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp index 0dfbb202da..7db0867d1c 100644 --- a/interface/src/ui/HMDToolsDialog.cpp +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -250,7 +250,7 @@ void HMDToolsDialog::aboutToQuit() { void HMDToolsDialog::screenCountChanged(int newCount) { if (!OculusManager::isConnected()) { - OculusManager::connect(); + //OculusManager::connect(); } int hmdScreenNumber = OculusManager::getHMDScreen(); diff --git a/libraries/shared/src/OglplusHelpers.h b/libraries/shared/src/OglplusHelpers.h index 73d32c4079..1a00c021f9 100644 --- a/libraries/shared/src/OglplusHelpers.h +++ b/libraries/shared/src/OglplusHelpers.h @@ -5,7 +5,6 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifdef Q_OS_WIN #pragma once #include "GLMHelpers.h" @@ -164,5 +163,4 @@ protected: } }; -using BasicFramebufferWrapperPtr = std::shared_ptr; -#endif \ No newline at end of file +using BasicFramebufferWrapperPtr = std::shared_ptr; \ No newline at end of file From 5faa53d7e9c1309599310cd11a042dd2b232e329 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 8 Jun 2015 10:17:34 -0700 Subject: [PATCH 25/34] Working on OVR SDK 0.6 --- interface/src/Application.cpp | 7 --- interface/src/devices/OculusManager.cpp | 4 -- interface/src/ui/HMDToolsDialog.cpp | 61 ++----------------------- interface/src/ui/HMDToolsDialog.h | 4 -- 4 files changed, 3 insertions(+), 73 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4f314eeb2c..5f8403e3f1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2106,13 +2106,6 @@ void Application::init() { _mirrorCamera.setMode(CAMERA_MODE_MIRROR); - //OculusManager::connect(); - //if (OculusManager::isConnected()) { - // QMetaObject::invokeMethod(Menu::getInstance()->getActionForOption(MenuOption::Fullscreen), - // "trigger", - // Qt::QueuedConnection); - //} - TV3DManager::connect(); if (TV3DManager::isConnected()) { QMetaObject::invokeMethod(Menu::getInstance()->getActionForOption(MenuOption::Fullscreen), diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 5353d1cd55..1fef48a8c9 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -554,10 +554,6 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati oldFrameIndex = _frameIndex; #endif - if (_outputWindow->visibility() != QWindow::FullScreen) { - // _outputWindow->showFullScreen(); - } - #ifndef Q_OS_WIN // FIXME: we need a better way of responding to the HSW. In particular // we need to ensure that it's only displayed once per session, rather than diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp index 7db0867d1c..9afd0f51c7 100644 --- a/interface/src/ui/HMDToolsDialog.cpp +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -56,8 +56,6 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) : this->QDialog::setLayout(form); - _wasMoved = false; - _previousRect = Application::getInstance()->getWindow()->rect(); Application::getInstance()->getWindow()->activateWindow(); // watch for our application window moving screens. If it does we want to update our screen details @@ -136,24 +134,6 @@ void HMDToolsDialog::enterHDMMode() { if (!_inHDMMode) { _switchModeButton->setText("Leave HMD Mode"); _debugDetails->setText(getDebugDetails()); - - _hmdScreenNumber = OculusManager::getHMDScreen(); - - if (_hmdScreenNumber >= 0) { - QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); - _hmdScreen = QGuiApplication::screens()[_hmdScreenNumber]; - - _previousRect = Application::getInstance()->getWindow()->rect(); - _previousRect = QRect(mainWindow->mapToGlobal(_previousRect.topLeft()), - mainWindow->mapToGlobal(_previousRect.bottomRight())); - _previousScreen = mainWindow->screen(); - QRect rect = QApplication::desktop()->screenGeometry(_hmdScreenNumber); - mainWindow->setScreen(_hmdScreen); - mainWindow->setGeometry(rect); - - _wasMoved = true; - } - // if we're on a single screen setup, then hide our tools window when entering HMD mode if (QApplication::desktop()->screenCount() == 1) { @@ -161,58 +141,21 @@ void HMDToolsDialog::enterHDMMode() { } Application::getInstance()->setEnableVRMode(true); - - const int SLIGHT_DELAY = 500; - // If we go to fullscreen immediately, it ends up on the primary monitor, - // even though we've already moved the window. By adding this delay, the - // fullscreen target screen ends up correct. - QTimer::singleShot(SLIGHT_DELAY, this, [&]{ - Application::getInstance()->setFullscreen(true); - activateWindowAfterEnterMode(); - }); - + _inHDMMode = true; } } -void HMDToolsDialog::activateWindowAfterEnterMode() { - Application::getInstance()->getWindow()->activateWindow(); - - // center the cursor on the main application window - centerCursorOnWidget(Application::getInstance()->getWindow()); -} - void HMDToolsDialog::leaveHDMMode() { if (_inHDMMode) { _switchModeButton->setText("Enter HMD Mode"); _debugDetails->setText(getDebugDetails()); - Application::getInstance()->setEnableVRMode(false); - Application::getInstance()->setFullscreen(false); Application::getInstance()->getWindow()->activateWindow(); - - if (_wasMoved) { - QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); - mainWindow->setScreen(_previousScreen); - mainWindow->setGeometry(_previousRect); - - const int SLIGHT_DELAY = 1500; - QTimer::singleShot(SLIGHT_DELAY, this, SLOT(moveWindowAfterLeaveMode())); - } - _wasMoved = false; _inHDMMode = false; } } -void HMDToolsDialog::moveWindowAfterLeaveMode() { - QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); - mainWindow->setScreen(_previousScreen); - mainWindow->setGeometry(_previousRect); - Application::getInstance()->getWindow()->activateWindow(); - Application::getInstance()->resetSensors(); -} - - void HMDToolsDialog::reject() { // Just regularly close upon ESC close(); @@ -244,6 +187,8 @@ void HMDToolsDialog::hideEvent(QHideEvent* event) { void HMDToolsDialog::aboutToQuit() { if (_inHDMMode) { + // FIXME this is ineffective because it doesn't trigger the menu to + // save the fact that VR Mode is not checked. leaveHDMMode(); } } diff --git a/interface/src/ui/HMDToolsDialog.h b/interface/src/ui/HMDToolsDialog.h index 10dc1c5c80..c16957f2d7 100644 --- a/interface/src/ui/HMDToolsDialog.h +++ b/interface/src/ui/HMDToolsDialog.h @@ -35,8 +35,6 @@ signals: public slots: void reject(); void switchModeClicked(bool checked); - void activateWindowAfterEnterMode(); - void moveWindowAfterLeaveMode(); void applicationWindowScreenChanged(QScreen* screen); void aboutToQuit(); void screenCountChanged(int newCount); @@ -51,8 +49,6 @@ private: void enterHDMMode(); void leaveHDMMode(); - bool _wasMoved; - QRect _previousRect; QScreen* _previousScreen; QScreen* _hmdScreen; int _hmdScreenNumber; From 11bc838be9580528dd29be643d0cc5c83aecff4e Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 9 Jun 2015 00:48:42 -0700 Subject: [PATCH 26/34] Switching to Git for oglplus --- cmake/externals/oglplus/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/externals/oglplus/CMakeLists.txt b/cmake/externals/oglplus/CMakeLists.txt index 1ef67b5e9f..fd3dcee687 100644 --- a/cmake/externals/oglplus/CMakeLists.txt +++ b/cmake/externals/oglplus/CMakeLists.txt @@ -4,8 +4,8 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://softlayer-dal.dl.sourceforge.net/project/oglplus/oglplus-0.61.x/oglplus-0.61.0.zip - URL_MD5 bb55038c36c660d2b6c7be380414fa60 + GIT_REPOSITORY https://github.com/matus-chochlik/oglplus.git + GIT_TAG 1aab48f45b40b4ea06a15975fa033b66b237078f CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" From 5a1b7131603ae451ba15189cad093a96fba1a97e Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 9 Jun 2015 00:59:17 -0700 Subject: [PATCH 27/34] Fixing texture include error in oglplus --- cmake/externals/oglplus/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/externals/oglplus/CMakeLists.txt b/cmake/externals/oglplus/CMakeLists.txt index fd3dcee687..bfe6f2a20a 100644 --- a/cmake/externals/oglplus/CMakeLists.txt +++ b/cmake/externals/oglplus/CMakeLists.txt @@ -4,8 +4,8 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} - GIT_REPOSITORY https://github.com/matus-chochlik/oglplus.git - GIT_TAG 1aab48f45b40b4ea06a15975fa033b66b237078f + GIT_REPOSITORY https://github.com/jherico/oglplus.git + GIT_TAG e67b24a6e3397c2dc16523bcd5d4c229abd20b81 CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" From 43bddf23b4424c5d425945fc6bc66f1a68f188c1 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 9 Jun 2015 01:03:14 -0700 Subject: [PATCH 28/34] Grabbing correct oglplus commit --- cmake/externals/oglplus/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/externals/oglplus/CMakeLists.txt b/cmake/externals/oglplus/CMakeLists.txt index bfe6f2a20a..23ba0d515e 100644 --- a/cmake/externals/oglplus/CMakeLists.txt +++ b/cmake/externals/oglplus/CMakeLists.txt @@ -5,7 +5,7 @@ include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} GIT_REPOSITORY https://github.com/jherico/oglplus.git - GIT_TAG e67b24a6e3397c2dc16523bcd5d4c229abd20b81 + GIT_TAG 470d8e56fd6bf3913ceec03d82f42d3bafab2cbe CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" From e9587d90c4c6902e92c335ff6d1980bd6098515f Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 9 Jun 2015 01:50:32 -0700 Subject: [PATCH 29/34] Trying to fix linux build --- cmake/externals/boostconfig/CMakeLists.txt | 14 +++++++------- libraries/shared/CMakeLists.txt | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cmake/externals/boostconfig/CMakeLists.txt b/cmake/externals/boostconfig/CMakeLists.txt index 8785e0d7c7..8494bb0114 100644 --- a/cmake/externals/boostconfig/CMakeLists.txt +++ b/cmake/externals/boostconfig/CMakeLists.txt @@ -3,13 +3,13 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) include(ExternalProject) ExternalProject_Add( - ${EXTERNAL_NAME} - URL https://github.com/boostorg/config/archive/boost-1.58.0.zip - URL_MD5 42fa673bae2b7645a22736445e80eb8d - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" - LOG_DOWNLOAD 1 + ${EXTERNAL_NAME} + URL https://github.com/boostorg/config/archive/boost-1.58.0.zip + URL_MD5 42fa673bae2b7645a22736445e80eb8d + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + LOG_DOWNLOAD 1 ) ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) diff --git a/libraries/shared/CMakeLists.txt b/libraries/shared/CMakeLists.txt index 6f7efd1b40..cac8de2ced 100644 --- a/libraries/shared/CMakeLists.txt +++ b/libraries/shared/CMakeLists.txt @@ -11,7 +11,7 @@ find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) add_dependency_external_projects(boostconfig) -find_package(BOOSTCONFIG REQUIRED) +find_package(BoostConfig REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${BOOSTCONFIG_INCLUDE_DIRS}) add_dependency_external_projects(oglplus) From 5680d58a191c0a3e4a9455e4160133a931f9e543 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 9 Jun 2015 03:09:10 -0700 Subject: [PATCH 30/34] Removing oglplus requirement for linux and mac --- interface/src/devices/OculusManager.cpp | 5 ----- libraries/shared/src/OglplusHelpers.h | 9 ++++++++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 64f12969a0..1fd84bb921 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -177,7 +177,6 @@ ovrLayerEyeFov OculusManager::_sceneLayer; #else -BasicFramebufferWrapper* _transferFbo; ovrTexture OculusManager::_eyeTextures[ovrEye_Count]; GlWindow* OculusManager::_outputWindow{ nullptr }; @@ -310,10 +309,6 @@ void OculusManager::connect(QOpenGLContext* shareContext) { } _outputWindow->showFullScreen(); _outputWindow->makeCurrent(); - _transferFbo = new BasicFramebufferWrapper(); - _transferFbo->Init(toGlm(_renderTargetSize)); - - ovrGLConfig cfg; memset(&cfg, 0, sizeof(cfg)); diff --git a/libraries/shared/src/OglplusHelpers.h b/libraries/shared/src/OglplusHelpers.h index 1a00c021f9..47e7331ce0 100644 --- a/libraries/shared/src/OglplusHelpers.h +++ b/libraries/shared/src/OglplusHelpers.h @@ -7,6 +7,12 @@ // #pragma once +// FIXME support oglplus on all platforms +// For now it's a convenient helper for Windows + +#include + +#ifdef Q_OS_WIN #include "GLMHelpers.h" #define OGLPLUS_USE_GLCOREARB_H 0 @@ -163,4 +169,5 @@ protected: } }; -using BasicFramebufferWrapperPtr = std::shared_ptr; \ No newline at end of file +using BasicFramebufferWrapperPtr = std::shared_ptr; +#endif From 64bb120712ed8f4691e4337281ae8054202566b5 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 9 Jun 2015 10:25:05 -0700 Subject: [PATCH 31/34] Be a little less heavy handed with the GPU sync --- interface/src/devices/OculusManager.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 1fd84bb921..6c3a3d84a0 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -710,13 +710,21 @@ void OculusManager::display(QGLWidget * glCanvas, RenderArgs* renderArgs, const Q_ASSERT(OVR_SUCCESS(res)); _swapFbo->Increment(); #else - glFinish(); - GLuint textureId = gpu::GLBackend::getTextureID(finalFbo->getRenderBuffer(0)); + GLsync syncObject = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + glFlush(); + _outputWindow->makeCurrent(); + // force the compositing context to wait for the texture + // rendering to complete before it starts the distortion rendering, + // but without triggering a CPU/GPU synchronization + glWaitSync(syncObject, 0, GL_TIMEOUT_IGNORED); + + GLuint textureId = gpu::GLBackend::getTextureID(finalFbo->getRenderBuffer(0)); for_each_eye([&](ovrEyeType eye) { ovrGLTexture & glEyeTexture = reinterpret_cast(_eyeTextures[eye]); glEyeTexture.OGL.TexId = textureId; }); + // restore our normal viewport ovrHmd_EndFrame(_ovrHmd, eyeRenderPose, _eyeTextures); glCanvas->makeCurrent(); From 78c3ba0e2cf6005f2a7a5a455c292f6e40774954 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 9 Jun 2015 10:25:21 -0700 Subject: [PATCH 32/34] Removing dead code --- interface/src/devices/OculusManager.cpp | 15 --------------- interface/src/devices/OculusManager.h | 4 ---- interface/src/ui/ApplicationOverlay.cpp | 1 - 3 files changed, 20 deletions(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 6c3a3d84a0..ef3a906878 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -740,21 +740,6 @@ void OculusManager::reset() { } } -//Gets the current predicted angles from the oculus sensors -void OculusManager::getEulerAngles(float& yaw, float& pitch, float& roll) { - ovrTrackingState ts = ovrHmd_GetTrackingState(_ovrHmd, ovr_GetTimeInSeconds()); - if (ts.StatusFlags & (ovrStatus_OrientationTracked | ovrStatus_PositionTracked)) { - glm::vec3 euler = glm::eulerAngles(toGlm(ts.HeadPose.ThePose.Orientation)); - yaw = euler.y; - pitch = euler.x; - roll = euler.z; - } else { - yaw = 0.0f; - pitch = 0.0f; - roll = 0.0f; - } -} - glm::vec3 OculusManager::getRelativePosition() { ovrTrackingState trackingState = ovrHmd_GetTrackingState(_ovrHmd, ovr_GetTimeInSeconds()); return toGlm(trackingState.HeadPose.ThePose.Position); diff --git a/interface/src/devices/OculusManager.h b/interface/src/devices/OculusManager.h index f5265f3a74..b82379a7b3 100644 --- a/interface/src/devices/OculusManager.h +++ b/interface/src/devices/OculusManager.h @@ -52,10 +52,6 @@ public: static void display(QGLWidget * glCanvas, RenderArgs* renderArgs, const glm::quat &bodyOrientation, const glm::vec3 &position, Camera& whichCamera); static void reset(); - /// param \yaw[out] yaw in radians - /// param \pitch[out] pitch in radians - /// param \roll[out] roll in radians - static void getEulerAngles(float& yaw, float& pitch, float& roll); static glm::vec3 getRelativePosition(); static glm::quat getOrientation(); static QSize getRenderTargetSize(); diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 7768b32eed..59ae786008 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -573,7 +573,6 @@ void ApplicationOverlay::renderPointers() { _lastMouseMove = usecTimestampNow(); } else if (usecTimestampNow() - _lastMouseMove > MAX_IDLE_TIME * USECS_PER_SECOND) { //float pitch = 0.0f, yaw = 0.0f, roll = 0.0f; // radians - //OculusManager::getEulerAngles(yaw, pitch, roll); glm::quat orientation = qApp->getHeadOrientation(); // (glm::vec3(pitch, yaw, roll)); glm::vec3 result; From 7b355fe69fdf5dc9a5659a2cbb27fe8e86a79a87 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 9 Jun 2015 10:29:10 -0700 Subject: [PATCH 33/34] Removing build of oglplus and boostconfig on non-Windows --- libraries/shared/CMakeLists.txt | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/libraries/shared/CMakeLists.txt b/libraries/shared/CMakeLists.txt index cac8de2ced..c4159b1190 100644 --- a/libraries/shared/CMakeLists.txt +++ b/libraries/shared/CMakeLists.txt @@ -10,10 +10,12 @@ add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) -add_dependency_external_projects(boostconfig) -find_package(BoostConfig REQUIRED) -target_include_directories(${TARGET_NAME} PUBLIC ${BOOSTCONFIG_INCLUDE_DIRS}) +if (WIN32) + add_dependency_external_projects(boostconfig) + find_package(BoostConfig REQUIRED) + target_include_directories(${TARGET_NAME} PUBLIC ${BOOSTCONFIG_INCLUDE_DIRS}) -add_dependency_external_projects(oglplus) -find_package(OGLPLUS REQUIRED) -target_include_directories(${TARGET_NAME} PUBLIC ${OGLPLUS_INCLUDE_DIRS}) + add_dependency_external_projects(oglplus) + find_package(OGLPLUS REQUIRED) + target_include_directories(${TARGET_NAME} PUBLIC ${OGLPLUS_INCLUDE_DIRS}) +endif() \ No newline at end of file From e5a9fa8cdcabe8dc99cee9f9bf82988dfcf55fba Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 9 Jun 2015 11:20:13 -0700 Subject: [PATCH 34/34] Fixing broken declarations --- interface/src/devices/OculusManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index ef3a906878..271d77bcde 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -199,12 +199,12 @@ float OculusManager::CALIBRATION_DELTA_MINIMUM_LENGTH = 0.02f; float OculusManager::CALIBRATION_DELTA_MINIMUM_ANGLE = 5.0f * RADIANS_PER_DEGREE; float OculusManager::CALIBRATION_ZERO_MAXIMUM_LENGTH = 0.01f; float OculusManager::CALIBRATION_ZERO_MAXIMUM_ANGLE = 2.0f * RADIANS_PER_DEGREE; -uint64_t OculusManager::CALIBRATION_ZERO_HOLD_TIME = 3000000; // usec +quint64 OculusManager::CALIBRATION_ZERO_HOLD_TIME = 3000000; // usec float OculusManager::CALIBRATION_MESSAGE_DISTANCE = 2.5f; OculusManager::CalibrationState OculusManager::_calibrationState; glm::vec3 OculusManager::_calibrationPosition; glm::quat OculusManager::_calibrationOrientation; -uint64_t OculusManager::_calibrationStartTime; +quint64 OculusManager::_calibrationStartTime; int OculusManager::_calibrationMessage = 0; glm::vec3 OculusManager::_eyePositions[ovrEye_Count]; // TODO expose this as a developer toggle