diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 54f6be1ceb..1ba9db8a99 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -316,7 +316,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _previousScriptLocation("LastScriptLocation"), _scriptsLocationHandle("scriptsLocation"), _fieldOfView("fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES), - _viewTransform(), _scaleMirror(1.0f), _rotateMirror(0.0f), _raiseMirror(0.0f), @@ -878,7 +877,7 @@ void Application::paintGL() { // Sync up the View Furstum with the camera // FIXME: it's happening again in the updateSHadow and it shouldn't, this should be the place - loadViewFrustum(_myCamera, _viewFrustum); + _myCamera.loadViewFrustum(_viewFrustum); if (getShadowsEnabled()) { updateShadowMap(); @@ -891,43 +890,40 @@ void Application::paintGL() { auto finalFbo = primaryFbo; glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFbo)); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glPushMatrix(); { // Viewport is assigned to the size of the framebuffer QSize size = DependencyManager::get()->getFrameBufferSize(); if (displayPlugin->isStereo()) { QRect r(QPoint(0, 0), QSize(size.width() / 2, size.height())); glEnable(GL_SCISSOR_TEST); - for (int i = 0; i < 2; ++i) { + for_each_eye([&](Eye eye){ + // FIXME we need to let the display plugin decide how the geometry works for stereo rendering + // for instance, an interleaved display should have half the vertical resolution, while a side + // by side display for a temporal interleave should have full resolution glViewport(r.x(), r.y(), r.width(), r.height()); glScissor(r.x(), r.y(), r.width(), r.height()); - glMatrixMode(GL_PROJECTION); - // FIXME Fetch the projection matrix from the plugin - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); + // Load the view frustum, used by meshes Camera eyeCamera; - eyeCamera.setRotation(_myCamera.getRotation()); - eyeCamera.setPosition(_myCamera.getPosition()); + eyeCamera.setTransform(displayPlugin->getModelview(eye, _myCamera.getTransform())); + eyeCamera.setProjection(displayPlugin->getProjection(eye, _myCamera.getProjection())); + displaySide(eyeCamera); - glPopMatrix(); + if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { glm::vec2 mpos = getActiveDisplayPlugin()->getUiMousePosition(); _rearMirrorTools->render(true, QPoint(mpos.x, mpos.y)); } else if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { renderRearViewMirror(_mirrorViewRect); } + }, [&] { r.moveLeft(r.width()); - } + }); glDisable(GL_SCISSOR_TEST); } else { glViewport(0, 0, size.width(), size.height()); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); displaySide(_myCamera); - glPopMatrix(); if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { glm::vec2 mpos = getActiveDisplayPlugin()->getUiMousePosition(); _rearMirrorTools->render(true, QPoint(mpos.x, mpos.y)); @@ -938,6 +934,8 @@ void Application::paintGL() { finalFbo = DependencyManager::get()->render(); } + glPopMatrix(); + // This might not be needed *right now*. We want to ensure that the FBO rendering // has completed before we start trying to read from it in another context. However // once we have multi-threaded rendering, this will almost certainly be critical, @@ -984,19 +982,6 @@ void Application::showEditEntitiesHelp() { InfoView::show(INFO_EDIT_ENTITIES_PATH); } -void Application::resetCamerasOnResizeGL(Camera& camera, const glm::uvec2& size) { -#if 0 - if (OculusManager::isConnected()) { - OculusManager::configureCamera(camera); - } else if (TV3DManager::isConnected()) { - TV3DManager::configureCamera(camera, size.x, size.y); - } else { -#endif - camera.setProjection(glm::perspective(glm::radians(_fieldOfView.get()), (float)size.x / size.y, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); -#if 0 - } -#endif -} void Application::resizeEvent(QResizeEvent * event) { resizeGL(); @@ -1014,12 +999,9 @@ void Application::resizeGL() { _renderResolution = toGlm(renderSize); DependencyManager::get()->setFrameBufferSize(renderSize); - resetCamerasOnResizeGL(_myCamera, _renderResolution); - glViewport(0, 0, _renderResolution.x, _renderResolution.y); // shouldn't this account for the menu??? - - updateProjectionMatrix(); - glLoadIdentity(); + _myCamera.setProjection(glm::perspective(glm::radians(_fieldOfView.get()), + aspect(getCanvasSize()), DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); auto offscreenUi = DependencyManager::get(); offscreenUi->resize(fromGlm(getCanvasSize())); @@ -1031,24 +1013,6 @@ void Application::resizeGL() { Stats::getInstance()->resetWidth(_renderResolution.x, horizontalOffset); } -void Application::updateProjectionMatrix() { - updateProjectionMatrix(_myCamera); -} - -void Application::updateProjectionMatrix(Camera& camera, bool updateViewFrustum) { - _projectionMatrix = camera.getProjection(); - - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(glm::value_ptr(_projectionMatrix)); - - // Tell our viewFrustum about this change, using the application camera - if (updateViewFrustum) { - loadViewFrustum(camera, _viewFrustum); - } - - glMatrixMode(GL_MODELVIEW); -} - void Application::controlledBroadcastToNodes(const QByteArray& packet, const NodeSet& destinationNodeTypes) { foreach(NodeType_t type, destinationNodeTypes) { // Perform the broadcast for one type @@ -2205,7 +2169,7 @@ void Application::updateMouseRay() { PerformanceWarning warn(showWarnings, "Application::updateMouseRay()"); // make sure the frustum is up-to-date - loadViewFrustum(_myCamera, _viewFrustum); + _myCamera.loadViewFrustum(_viewFrustum); PickRay pickRay = computePickRay(getTrueMouseX(), getTrueMouseY()); _mouseRayOrigin = pickRay.origin; @@ -2491,7 +2455,7 @@ void Application::update(float deltaTime) { // to the server. { PerformanceTimer perfTimer("loadViewFrustum"); - loadViewFrustum(_myCamera, _viewFrustum); + _myCamera.loadViewFrustum(_viewFrustum); } quint64 now = usecTimestampNow(); @@ -2826,24 +2790,6 @@ QRect Application::getDesirableApplicationGeometry() { return applicationGeometry; } -///////////////////////////////////////////////////////////////////////////////////// -// loadViewFrustum() -// -// Description: this will load the view frustum bounds for EITHER the head -// or the "myCamera". -// -void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) { - // We will use these below, from either the camera or head vectors calculated above - viewFrustum.setProjection(camera.getProjection()); - - // Set the viewFrustum up with the correct position and orientation of the camera - viewFrustum.setPosition(camera.getPosition()); - viewFrustum.setOrientation(camera.getRotation()); - - // Ask the ViewFrustum class to calculate our corners - viewFrustum.calculate(); -} - glm::vec3 Application::getSunDirection() { // Sun direction is in fact just the location of the sun relative to the origin auto skyStage = DependencyManager::get()->getSkyStage(); @@ -2872,7 +2818,7 @@ void Application::updateShadowMap() { glm::vec2(0.0f, 0.5f), glm::vec2(0.5f, 0.5f) }; float frustumScale = 1.0f / (_viewFrustum.getFarClip() - _viewFrustum.getNearClip()); - loadViewFrustum(_myCamera, _viewFrustum); + _myCamera.loadViewFrustum(_viewFrustum); int matrixCount = 1; //int targetSize = fbo->width(); @@ -2944,28 +2890,18 @@ void Application::updateShadowMap() { glMatrixMode(GL_PROJECTION); glPushMatrix(); - glLoadIdentity(); - glOrtho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z); - - glm::mat4 projAgain; - glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat*)&projAgain); - + glm::mat4 proj = glm::ortho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z); + glLoadMatrixf(glm::value_ptr(proj)); glMatrixMode(GL_MODELVIEW); glPushMatrix(); - glLoadIdentity(); - glm::vec3 axis = glm::axis(inverseRotation); - glRotatef(glm::degrees(glm::angle(inverseRotation)), axis.x, axis.y, axis.z); + glLoadMatrixf(glm::value_ptr(glm::mat4_cast(inverseRotation))); - // store view matrix without translation, which we'll use for precision-sensitive objects - updateUntranslatedViewMatrix(); - // Equivalent to what is happening with _untranslatedViewMatrix and the _viewMatrixTranslation // the viewTransofmr object is updatded with the correct values and saved, // this is what is used for rendering the Entities and avatars Transform viewTransform; viewTransform.setRotation(rotation); - // viewTransform.postTranslate(shadowFrustumCenter); setViewTransform(viewTransform); @@ -3003,7 +2939,6 @@ void Application::updateShadowMap() { glMatrixMode(GL_MODELVIEW); } -// glViewport(0, 0, _glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); activeRenderingThread = nullptr; } @@ -3118,16 +3053,23 @@ const ViewFrustum* Application::getDisplayViewFrustum() const { return &_displayViewFrustum; } -void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs::RenderSide renderSide) { +void Application::displaySide(const Camera& theCamera, bool selfAvatarOnly) { activeRenderingThread = QThread::currentThread(); PROFILE_RANGE(__FUNCTION__); PerformanceTimer perfTimer("display"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide()"); - // transform by eye offset // load the view frustum - loadViewFrustum(theCamera, _displayViewFrustum); + theCamera.loadViewFrustum(_displayViewFrustum); + // Load the legacy GL stacks, used by entities (for now) + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(glm::value_ptr(theCamera.getProjection())); + + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(glm::value_ptr(glm::inverse(theCamera.getTransform()))); + + // FIXME just flip the texture coordinates // flip x if in mirror mode (also requires reversing winding order for backface culling) if (theCamera.getMode() == CAMERA_MODE_MIRROR) { glScalef(-1.0f, 1.0f, 1.0f); @@ -3137,17 +3079,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs glFrontFace(GL_CCW); } - // transform view according to theCamera - // could be myCamera (if in normal mode) - // or could be viewFrustumOffsetCamera if in offset mode - glm::quat rotation = theCamera.getRotation(); - glm::vec3 axis = glm::axis(rotation); - glRotatef(-glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - - // store view matrix without translation, which we'll use for precision-sensitive objects - updateUntranslatedViewMatrix(-theCamera.getPosition()); - // Equivalent to what is happening with _untranslatedViewMatrix and the _viewMatrixTranslation // the viewTransofmr object is updatded with the correct values and saved, // this is what is used for rendering the Entities and avatars @@ -3157,17 +3089,8 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs if (theCamera.getMode() == CAMERA_MODE_MIRROR) { viewTransform.setScale(Transform::Vec3(-1.0f, 1.0f, 1.0f)); } - if (renderSide != RenderArgs::MONO) { - glm::mat4 invView = glm::inverse(_untranslatedViewMatrix); - - viewTransform.evalFromRawMatrix(invView); - viewTransform.preTranslate(_viewMatrixTranslation); - } - setViewTransform(viewTransform); - glTranslatef(_viewMatrixTranslation.x, _viewMatrixTranslation.y, _viewMatrixTranslation.z); - // Setup 3D lights (after the camera transform, so that they are positioned in world space) { PerformanceTimer perfTimer("lights"); @@ -3208,7 +3131,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs if (Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) { // TODO: handle this correctly for zones - const EnvironmentData& closestData = _environment.getClosestData(theCamera.getPosition()); + const EnvironmentData& closestData = _environment.getClosestData(_displayViewFrustum.getPosition()); if (closestData.getHasStars()) { const float APPROXIMATE_DISTANCE_FROM_HORIZON = 0.1f; @@ -3216,7 +3139,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs glm::vec3 sunDirection = (getAvatarPosition() - closestData.getSunLocation()) / closestData.getAtmosphereOuterRadius(); - float height = glm::distance(theCamera.getPosition(), closestData.getAtmosphereCenter()); + float height = glm::distance(_displayViewFrustum.getPosition(), closestData.getAtmosphereCenter()); if (height < closestData.getAtmosphereInnerRadius()) { // If we're inside the atmosphere, then determine if our keyLight is below the horizon alpha = 0.0f; @@ -3255,7 +3178,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs PerformanceTimer perfTimer("atmosphere"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide() ... atmosphere..."); - _environment.renderAtmospheres(theCamera); + _environment.renderAtmospheres(_displayViewFrustum.getPosition()); } } @@ -3303,7 +3226,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs if (theCamera.getMode() == CAMERA_MODE_MIRROR) { renderMode = RenderArgs::MIRROR_RENDER_MODE; } - _entities.render(renderMode, renderSide, renderDebugFlags); + _entities.render(renderMode, RenderArgs::MONO, renderDebugFlags); if (!Menu::getInstance()->isOptionChecked(MenuOption::Wireframe)) { // Restaure polygon mode @@ -3327,7 +3250,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs } bool mirrorMode = (theCamera.getMode() == CAMERA_MODE_MIRROR); - + { PerformanceTimer perfTimer("avatars"); DependencyManager::get()->renderAvatars(mirrorMode ? RenderArgs::MIRROR_RENDER_MODE : RenderArgs::NORMAL_RENDER_MODE, @@ -3362,7 +3285,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs _nodeBoundsDisplay.draw(); // Render the world box - if (theCamera.getMode() != CAMERA_MODE_MIRROR && Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { + if (!mirrorMode && Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { PerformanceTimer perfTimer("worldBox"); renderWorldBox(); } @@ -3405,33 +3328,32 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs activeRenderingThread = nullptr; } -void Application::updateUntranslatedViewMatrix(const glm::vec3& viewMatrixTranslation) { - glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat*)&_untranslatedViewMatrix); - _viewMatrixTranslation = viewMatrixTranslation; -} - void Application::setViewTransform(const Transform& view) { _viewTransform = view; } -void Application::loadTranslatedViewMatrix(const glm::vec3& translation) { - glLoadMatrixf((const GLfloat*)&_untranslatedViewMatrix); - glTranslatef(translation.x + _viewMatrixTranslation.x, translation.y + _viewMatrixTranslation.y, - translation.z + _viewMatrixTranslation.z); -} +//void Application::updateUntranslatedViewMatrix(const glm::vec3& viewMatrixTranslation) { +// glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat*)&_untranslatedViewMatrix); +// _viewMatrixTranslation = viewMatrixTranslation; +//} +// +//void Application::loadTranslatedViewMatrix(const glm::vec3& translation) { +// glLoadMatrixf((const GLfloat*)&_untranslatedViewMatrix); +// glTranslatef(translation.x + _viewMatrixTranslation.x, translation.y + _viewMatrixTranslation.y, +// translation.z + _viewMatrixTranslation.z); +//} +// +//void Application::getModelViewMatrix(glm::dmat4* modelViewMatrix) { +// (*modelViewMatrix) =_untranslatedViewMatrix; +// (*modelViewMatrix)[3] = _untranslatedViewMatrix * glm::vec4(_viewMatrixTranslation, 1); +//} void Application::getModelViewMatrix(glm::dmat4* modelViewMatrix) { - (*modelViewMatrix) =_untranslatedViewMatrix; - (*modelViewMatrix)[3] = _untranslatedViewMatrix * glm::vec4(_viewMatrixTranslation, 1); + (*modelViewMatrix) = glm::inverse(_displayViewFrustum.getView()); } void Application::getProjectionMatrix(glm::dmat4* projectionMatrix) { - *projectionMatrix = _projectionMatrix; -} - -void Application::computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal, - float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const { - _displayViewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); + *projectionMatrix = _displayViewFrustum.getProjection(); } bool Application::getShadowsEnabled() { @@ -3497,8 +3419,6 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { glViewport(x, size.height() - y - height, width, height); glScissor(x, size.height() - y - height, width, height); } - bool updateViewFrustum = false; - updateProjectionMatrix(_mirrorCamera, updateViewFrustum); glEnable(GL_SCISSOR_TEST); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -3511,11 +3431,9 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { glm::vec2 mpos = getActiveDisplayPlugin()->getUiMousePosition(); _rearMirrorTools->render(false, QPoint(mpos.x, mpos.y)); } - // reset Viewport and projection matrix glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); glDisable(GL_SCISSOR_TEST); - updateProjectionMatrix(_myCamera, updateViewFrustum); } void Application::resetSensors() { @@ -4598,11 +4516,11 @@ void Application::shutdownPlugins() { } glm::vec3 Application::getHeadPosition() const { - return getActiveDisplayPlugin()->headTranslation(); + return glm::vec3(getActiveDisplayPlugin()->getHeadPose()[3]); } glm::quat Application::getHeadOrientation() const { - return getActiveDisplayPlugin()->headOrientation(); + return glm::quat_cast(getActiveDisplayPlugin()->getHeadPose()); } glm::uvec2 Application::getCanvasSize() const { diff --git a/interface/src/Application.h b/interface/src/Application.h index 5c03df953e..a94859263a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -249,10 +249,11 @@ public: Overlays& getOverlays() { return _overlays; } float getFps() const { return _fps; } - const glm::vec3& getViewMatrixTranslation() const { return _viewMatrixTranslation; } - void setViewMatrixTranslation(const glm::vec3& translation) { _viewMatrixTranslation = translation; } + //const glm::vec3& getViewMatrixTranslation() const { return _viewMatrixTranslation; } + //void setViewMatrixTranslation(const glm::vec3& translation) { _viewMatrixTranslation = translation; } virtual const Transform& getViewTransform() const { return _viewTransform; } + virtual Transform& getViewTransform() { return _viewTransform; } void setViewTransform(const Transform& view); float getFieldOfView() { return _fieldOfView.get(); } @@ -278,8 +279,9 @@ public: QImage renderAvatarBillboard(); - void displaySide(Camera& whichCamera, bool selfAvatarOnly = false, RenderArgs::RenderSide renderSide = RenderArgs::MONO); + void displaySide(const Camera& camera, bool selfAvatarOnly = false); +/* /// Stores the current modelview matrix as the untranslated view matrix to use for transforms and the supplied vector as /// the view matrix translation. void updateUntranslatedViewMatrix(const glm::vec3& viewMatrixTranslation = glm::vec3()); @@ -289,16 +291,11 @@ public: /// Loads a view matrix that incorporates the specified model translation without the precision issues that can /// result from matrix multiplication at high translation magnitudes. void loadTranslatedViewMatrix(const glm::vec3& translation); - +*/ void getModelViewMatrix(glm::dmat4* modelViewMatrix); void getProjectionMatrix(glm::dmat4* projectionMatrix); virtual const glm::vec3& getShadowDistances() const { return _shadowDistances; } - - /// Computes the off-axis frustum parameters for the view frustum, taking mirroring into account. - virtual void computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal, - float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const; - virtual ViewFrustum* getCurrentViewFrustum() { return getDisplayViewFrustum(); } virtual bool getShadowsEnabled(); virtual bool getCascadeShadowsEnabled(); @@ -476,10 +473,6 @@ private slots: void setCursorVisible(bool visible); private: - void resetCamerasOnResizeGL(Camera& camera, const glm::uvec2& size); - void updateProjectionMatrix(); - void updateProjectionMatrix(Camera& camera, bool updateViewFrustum = true); - void updateCursorVisibility(); void sendPingPackets(); @@ -505,7 +498,6 @@ private: void renderLookatIndicator(glm::vec3 pointOfInterest); void queryOctree(NodeType_t serverType, PacketType packetType, NodeToJurisdictionMap& jurisdictions); - void loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum); glm::vec3 getSunDirection(); @@ -579,9 +571,11 @@ private: Setting::Handle _fieldOfView; Transform _viewTransform; + glm::mat4 _projectionMatrix; +/* glm::mat4 _untranslatedViewMatrix; glm::vec3 _viewMatrixTranslation; - glm::mat4 _projectionMatrix; +*/ float _scaleMirror; float _rotateMirror; diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp index e501b91dea..39ae70cd5b 100644 --- a/interface/src/Camera.cpp +++ b/interface/src/Camera.cpp @@ -46,13 +46,7 @@ QString modeToString(CameraMode mode) { } Camera::Camera() : - _mode(CAMERA_MODE_THIRD_PERSON), - _position(0.0f, 0.0f, 0.0f), - _projection(glm::perspective(glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES), 16.0f/9.0f, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)), - _hmdPosition(), - _hmdRotation(), - _isKeepLookingAt(false), - _lookingAt(0.0f, 0.0f, 0.0f) + _projection(glm::perspective(glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES), 16.0f/9.0f, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)) { } @@ -63,26 +57,33 @@ void Camera::update(float deltaTime) { return; } +void Camera::recompose() { + mat4 orientation = glm::mat4_cast(_rotation); + mat4 translation = glm::translate(mat4(), _position); + _transform = translation * orientation; +} + +void Camera::decompose() { + _position = vec3(_transform[3]); + _rotation = glm::quat_cast(_transform); +} + +void Camera::setTransform(const glm::mat4& transform) { + _transform = transform; + decompose(); +} + void Camera::setPosition(const glm::vec3& position) { - _position = position; + _position = position; + recompose(); + if (_isKeepLookingAt) { + lookAt(_lookingAt); + } } void Camera::setRotation(const glm::quat& rotation) { _rotation = rotation; - if (_isKeepLookingAt) { - lookAt(_lookingAt); - } -} - -void Camera::setHmdPosition(const glm::vec3& hmdPosition) { - _hmdPosition = hmdPosition; - if (_isKeepLookingAt) { - lookAt(_lookingAt); - } -} - -void Camera::setHmdRotation(const glm::quat& hmdRotation) { - _hmdRotation = hmdRotation; + recompose(); if (_isKeepLookingAt) { lookAt(_lookingAt); } @@ -143,3 +144,21 @@ void Camera::keepLookingAt(const glm::vec3& point) { _isKeepLookingAt = true; _lookingAt = point; } + +void Camera::loadViewFrustum(ViewFrustum& frustum) const { + // We will use these below, from either the camera or head vectors calculated above + frustum.setProjection(getProjection()); + + // Set the viewFrustum up with the correct position and orientation of the camera + frustum.setPosition(getPosition()); + frustum.setOrientation(getRotation()); + + // Ask the ViewFrustum class to calculate our corners + frustum.calculate(); +} + +ViewFrustum Camera::toViewFrustum() const { + ViewFrustum result; + loadViewFrustum(result); + return result; +} diff --git a/interface/src/Camera.h b/interface/src/Camera.h index fc1dbcaf00..c4ba67ec5d 100644 --- a/interface/src/Camera.h +++ b/interface/src/Camera.h @@ -43,28 +43,31 @@ public: void update( float deltaTime ); - void setRotation(const glm::quat& rotation); - void setProjection(const glm::mat4 & projection); - void setHmdPosition(const glm::vec3& hmdPosition); - void setHmdRotation(const glm::quat& hmdRotation); + CameraMode getMode() const { return _mode; } void setMode(CameraMode m); - glm::quat getRotation() const { return _rotation * _hmdRotation; } const glm::mat4& getProjection() const { return _projection; } - const glm::vec3& getHmdPosition() const { return _hmdPosition; } - const glm::quat& getHmdRotation() const { return _hmdRotation; } - CameraMode getMode() const { return _mode; } + void setProjection(const glm::mat4& projection); + + void loadViewFrustum(ViewFrustum& frustum) const; + ViewFrustum toViewFrustum() const; public slots: QString getModeString() const; void setModeString(const QString& mode); - glm::vec3 getPosition() const { return _position + _hmdPosition; } + const glm::quat getRotation() const { return _rotation; } + void setRotation(const glm::quat& rotation); + + const glm::vec3 getPosition() const { return _position; } void setPosition(const glm::vec3& position); + const glm::quat getOrientation() const { return getRotation(); } void setOrientation(const glm::quat& orientation) { setRotation(orientation); } - glm::quat getOrientation() const { return getRotation(); } - + + const glm::mat4 getTransform() const { return _transform; } + void setTransform(const glm::mat4& transform); + PickRay computePickRay(float x, float y); // These only work on independent cameras @@ -82,13 +85,17 @@ signals: void modeUpdated(const QString& newMode); private: - CameraMode _mode; + void recompose(); + void decompose(); + + CameraMode _mode{ CAMERA_MODE_THIRD_PERSON }; + glm::mat4 _transform; + glm::mat4 _projection; + + // derived glm::vec3 _position; glm::quat _rotation; - glm::mat4 _projection; - glm::vec3 _hmdPosition; - glm::quat _hmdRotation; - bool _isKeepLookingAt; + bool _isKeepLookingAt{ false }; glm::vec3 _lookingAt; }; diff --git a/interface/src/Environment.cpp b/interface/src/Environment.cpp index a2b78c2ff5..a4af31f6c7 100644 --- a/interface/src/Environment.cpp +++ b/interface/src/Environment.cpp @@ -68,17 +68,17 @@ void Environment::resetToDefault() { _data[HifiSockAddr()][0]; } -void Environment::renderAtmospheres(Camera& camera) { +void Environment::renderAtmospheres(const glm::vec3& position) { // get the lock for the duration of the call QMutexLocker locker(&_mutex); if (_environmentIsOverridden) { - renderAtmosphere(camera, _overrideData); + renderAtmosphere(position, _overrideData); } else { foreach (const ServerData& serverData, _data) { // TODO: do something about EnvironmentData foreach (const EnvironmentData& environmentData, serverData) { - renderAtmosphere(camera, environmentData); + renderAtmosphere(position, environmentData); } } } @@ -228,13 +228,13 @@ ProgramObject* Environment::createSkyProgram(const char* from, int* locations) { return program; } -void Environment::renderAtmosphere(Camera& camera, const EnvironmentData& data) { +void Environment::renderAtmosphere(const glm::vec3& position, const EnvironmentData& data) { glm::vec3 center = data.getAtmosphereCenter(); glPushMatrix(); glTranslatef(center.x, center.y, center.z); - glm::vec3 relativeCameraPos = camera.getPosition() - center; + glm::vec3 relativeCameraPos = position - center; float height = glm::length(relativeCameraPos); // use the appropriate shader depending on whether we're inside or outside diff --git a/interface/src/Environment.h b/interface/src/Environment.h index 1a46a10175..fac5aa26ca 100644 --- a/interface/src/Environment.h +++ b/interface/src/Environment.h @@ -29,7 +29,7 @@ public: void init(); void resetToDefault(); - void renderAtmospheres(Camera& camera); + void renderAtmospheres(const glm::vec3& camera); void override(const EnvironmentData& overrideData) { _overrideData = overrideData; _environmentIsOverridden = true; } void endOverride() { _environmentIsOverridden = false; } @@ -46,7 +46,7 @@ private: ProgramObject* createSkyProgram(const char* from, int* locations); - void renderAtmosphere(Camera& camera, const EnvironmentData& data); + void renderAtmosphere(const glm::vec3& position, const EnvironmentData& data); bool _initialized; ProgramObject* _skyFromAtmosphereProgram; diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 8c52c79ca0..c2c30b37f7 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -767,6 +767,7 @@ void SkeletonModel::resetShapePositionsToDefaultPose() { void SkeletonModel::renderBoundingCollisionShapes(float alpha) { const int BALL_SUBDIVISIONS = 10; +#if 0 if (_shapes.isEmpty()) { // the bounding shape has not been propery computed // so no need to render it @@ -797,6 +798,7 @@ void SkeletonModel::renderBoundingCollisionShapes(float alpha) { Avatar::renderJointConnectingCone( origin, axis, _boundingShape.getRadius(), _boundingShape.getRadius(), glm::vec4(0.6f, 0.8f, 0.6f, alpha)); glPopMatrix(); +#endif } bool SkeletonModel::hasSkeleton() { diff --git a/interface/src/devices/TV3DManager.cpp b/interface/src/devices/TV3DManager.cpp index 5ae0107a46..f2de97856e 100644 --- a/interface/src/devices/TV3DManager.cpp +++ b/interface/src/devices/TV3DManager.cpp @@ -120,7 +120,7 @@ void TV3DManager::display(Camera& whichCamera) { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - qApp->displaySide(eyeCamera, false, RenderArgs::MONO); + qApp->displaySide(eyeCamera, false); #if 0 qApp->getApplicationOverlay().displayOverlayTextureStereo(whichCamera, _aspect, fov); #endif diff --git a/interface/src/plugins/Plugin.h b/interface/src/plugins/Plugin.h index d22fc52c3d..a49c7487b8 100644 --- a/interface/src/plugins/Plugin.h +++ b/interface/src/plugins/Plugin.h @@ -6,7 +6,7 @@ class Plugin : public QObject { public: virtual const QString & getName() = 0; - virtual bool isSupported() { return true; } + virtual bool isSupported() const { return true; } virtual void init() {} virtual void deinit() {} diff --git a/interface/src/plugins/display/DisplayPlugin.h b/interface/src/plugins/display/DisplayPlugin.h index b68edf5f6a..e620b5e04a 100644 --- a/interface/src/plugins/display/DisplayPlugin.h +++ b/interface/src/plugins/display/DisplayPlugin.h @@ -21,14 +21,34 @@ #include #include +enum class Eye { + Left, + Right, + Mono +}; + +/* + * Helper method to iterate over each eye + */ +template +void for_each_eye(F f) { + f(Left); + f(Right); +} + +/* + * Helper method to iterate over each eye, with an additional lambda to take action between the eyes + */ +template +void for_each_eye(F f, FF ff) { + f(Eye::Left); + ff(); + f(Eye::Right); +} + class DisplayPlugin : public Plugin { Q_OBJECT public: - enum class Eye { - Left, - Right, - Mono - }; virtual bool isHmd() const { return false; } virtual bool isStereo() const { return false; } virtual bool isThrottled() const { return false; } @@ -76,23 +96,24 @@ public: }; virtual bool isMouseOnScreen() const; + // Stereo specific methods - virtual glm::mat4 getProjection(Eye eye) const { - return glm::mat4(); + virtual glm::mat4 getProjection(Eye eye, const glm::mat4& baseProjection) const { + return baseProjection; + } + + virtual glm::mat4 getModelview(Eye eye, const glm::mat4& baseModelview) const { + return glm::inverse(getEyePose(eye)) * baseModelview; } // HMD specific methods // TODO move these into another class - virtual glm::mat4 headPose() const { + virtual glm::mat4 getEyePose(Eye eye) const { static const glm::mat4 pose; return pose; } - virtual glm::quat headOrientation() const { - static const glm::quat orientation; return orientation; - } - - virtual glm::vec3 headTranslation() const { - static const glm::vec3 tranlsation; return tranlsation; + virtual glm::mat4 getHeadPose() const { + static const glm::mat4 pose; return pose; } virtual void abandonCalibration() {} @@ -108,3 +129,4 @@ protected: virtual void doneCurrent() {} virtual void swapBuffers() {} }; + diff --git a/interface/src/plugins/display/LegacyDisplayPlugin.cpp b/interface/src/plugins/display/LegacyDisplayPlugin.cpp index 00d922c37a..a6b79fa5ef 100644 --- a/interface/src/plugins/display/LegacyDisplayPlugin.cpp +++ b/interface/src/plugins/display/LegacyDisplayPlugin.cpp @@ -45,6 +45,8 @@ void LegacyDisplayPlugin::activate() { _window->installEventFilter(qApp); _window->installEventFilter(DependencyManager::get().data()); + + DependencyManager::get()->setProxyWindow(_window->windowHandle()); SimpleDisplayPlugin::activate(); } diff --git a/interface/src/plugins/display/Tv3dDisplayPlugin.cpp b/interface/src/plugins/display/Tv3dDisplayPlugin.cpp index 5b35478b57..efd6c055c9 100644 --- a/interface/src/plugins/display/Tv3dDisplayPlugin.cpp +++ b/interface/src/plugins/display/Tv3dDisplayPlugin.cpp @@ -60,6 +60,11 @@ Tv3dDisplayPlugin::Tv3dDisplayPlugin() { }); } +bool Tv3dDisplayPlugin::isSupported() const { + // FIXME this should attempt to do a scan for supported 3D output + return true; +} + gpu::TexturePointer _crosshairTexture; @@ -238,210 +243,3 @@ void Tv3dDisplayPlugin::deactivate() { _timer.stop(); GlWindowDisplayPlugin::deactivate(); } -/* -std::function Tv3dDisplayPlugin::getMouseTranslator() { - return [=](const QPointF& point){ - QPointF result{ point }; - QSize size = getDeviceSize(); - result.rx() *= 2.0f; - if (result.x() > size.width()) { - result.rx() -= size.width(); - } - return result; - }; -} - -glm::ivec2 Tv3dDisplayPlugin::trueMouseToUiMouse(const glm::ivec2 & position) const { - ivec2 result{ position }; - uvec2 size = getCanvasSize(); - result.x *= 2; - result.x %= size.x; - return result; -} - -*/ - -/* -void Tv3dDisplayPlugin::activate() { - GlWindowDisplayPlugin::activate(); - _window->setPosition(100, 100); - _window->resize(512, 512); - _window->setVisible(true); - _window->show(); -} - -void Tv3dDisplayPlugin::deactivate() { - GlWindowDisplayPlugin::deactivate(); -} -*/ - -/* -glm::ivec2 LegacyDisplayPlugin::getCanvasSize() const { - return toGlm(_window->size()); -} - -bool LegacyDisplayPlugin::hasFocus() const { - return _window->hasFocus(); -} - -PickRay LegacyDisplayPlugin::computePickRay(const glm::vec2 & pos) const { - return PickRay(); -} - -bool isMouseOnScreen() { - return false; -} - -void LegacyDisplayPlugin::preDisplay() { - SimpleDisplayPlugin::preDisplay(); - auto size = toGlm(_window->size()); - glViewport(0, 0, size.x, size.y); -} - -bool LegacyDisplayPlugin::isThrottled() const { - return _window->isThrottleRendering(); - - - */ - -#if 0 - -int TV3DManager::_screenWidth = 1; -int TV3DManager::_screenHeight = 1; -double TV3DManager::_aspect = 1.0; -eyeFrustum TV3DManager::_leftEye; -eyeFrustum TV3DManager::_rightEye; -eyeFrustum* TV3DManager::_activeEye = NULL; - - -bool TV3DManager::isConnected() { - return Menu::getInstance()->isOptionChecked(MenuOption::Enable3DTVMode); -} - -void TV3DManager::connect() { - auto deviceSize = qApp->getDeviceSize(); - configureCamera(*(qApp->getCamera()), deviceSize.width(), deviceSize.height()); -} - - -// The basic strategy of this stereoscopic rendering is explained here: -// http://www.orthostereo.com/geometryopengl.html -void TV3DManager::setFrustum(const Camera& whichCamera) { - const double DTR = 0.0174532925; // degree to radians - const double IOD = 0.05; //intraocular distance - double fovy = DEFAULT_FIELD_OF_VIEW_DEGREES; // field of view in y-axis - double nearZ = DEFAULT_NEAR_CLIP; // near clipping plane - double screenZ = 0.25f; // screen projection plane - - double top = nearZ * tan(DTR * fovy / 2.0); //sets top of frustum based on fovy and near clipping plane - double right = _aspect * top; // sets right of frustum based on aspect ratio - double frustumshift = (IOD / 2) * nearZ / screenZ; - - _leftEye.top = top; - _leftEye.bottom = -top; - _leftEye.left = -right + frustumshift; - _leftEye.right = right + frustumshift; - _leftEye.modelTranslation = IOD / 2; - - _rightEye.top = top; - _rightEye.bottom = -top; - _rightEye.left = -right - frustumshift; - _rightEye.right = right - frustumshift; - _rightEye.modelTranslation = -IOD / 2; -} - -void TV3DManager::configureCamera(Camera& whichCamera_, int screenWidth, int screenHeight) { - const Camera& whichCamera = whichCamera_; - - if (screenHeight == 0) { - screenHeight = 1; // prevent divide by 0 - } - _screenWidth = screenWidth; - _screenHeight = screenHeight; - _aspect = (double)_screenWidth / (double)_screenHeight; - setFrustum(whichCamera); - - glViewport(0, 0, _screenWidth, _screenHeight); // sets drawing viewport - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); -} - -void TV3DManager::display(Camera& whichCamera) { - double nearZ = DEFAULT_NEAR_CLIP; // near clipping plane - double farZ = DEFAULT_FAR_CLIP; // far clipping plane - - // left eye portal - int portalX = 0; - int portalY = 0; - QSize deviceSize = qApp->getDeviceSize() * - qApp->getRenderResolutionScale(); - int portalW = deviceSize.width() / 2; - int portalH = deviceSize.height(); - - - DependencyManager::get()->prepare(); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - Camera eyeCamera; - eyeCamera.setRotation(whichCamera.getRotation()); - eyeCamera.setPosition(whichCamera.getPosition()); - - glEnable(GL_SCISSOR_TEST); - glPushMatrix(); - forEachEye([&](eyeFrustum& eye) { - _activeEye = &eye; - glViewport(portalX, portalY, portalW, portalH); - glScissor(portalX, portalY, portalW, portalH); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); // reset projection matrix - glFrustum(eye.left, eye.right, eye.bottom, eye.top, nearZ, farZ); // set left view frustum - GLfloat p[4][4]; - // Really? - glGetFloatv(GL_PROJECTION_MATRIX, &(p[0][0])); - float cotangent = p[1][1]; - GLfloat fov = atan(1.0f / cotangent); - glTranslatef(eye.modelTranslation, 0.0, 0.0); // translate to cancel parallax - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - qApp->displaySide(eyeCamera, false, RenderArgs::MONO); -#if 0 - qApp->getApplicationOverlay().displayOverlayTextureStereo(whichCamera, _aspect, fov); -#endif - _activeEye = NULL; - }, [&] { - // render right side view - portalX = deviceSize.width() / 2; - }); - glPopMatrix(); - glDisable(GL_SCISSOR_TEST); - - auto finalFbo = DependencyManager::get()->render(); - auto fboSize = finalFbo->getSize(); - // Get the ACTUAL device size for the BLIT - deviceSize = qApp->getDeviceSize(); - - glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(finalFbo)); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - glBlitFramebuffer(0, 0, fboSize.x, fboSize.y, - 0, 0, deviceSize.width(), deviceSize.height(), - GL_COLOR_BUFFER_BIT, GL_NEAREST); - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - - // reset the viewport to how we started - glViewport(0, 0, deviceSize.width(), deviceSize.height()); -} - -void TV3DManager::overrideOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal, - float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) { - if (_activeEye) { - left = _activeEye->left; - right = _activeEye->right; - bottom = _activeEye->bottom; - top = _activeEye->top; - } -} - -#endif diff --git a/interface/src/plugins/display/Tv3dDisplayPlugin.h b/interface/src/plugins/display/Tv3dDisplayPlugin.h index a748870abb..ad2ccc7369 100644 --- a/interface/src/plugins/display/Tv3dDisplayPlugin.h +++ b/interface/src/plugins/display/Tv3dDisplayPlugin.h @@ -20,6 +20,7 @@ public: virtual const QString & getName(); Tv3dDisplayPlugin(); virtual bool isStereo() const final { return true; } + virtual bool isSupported() const final; void display(GLuint sceneTexture, const glm::uvec2& sceneSize, GLuint overlayTexture, const glm::uvec2& overlaySize); virtual void activate(); diff --git a/interface/src/plugins/display/WindowDisplayPlugin.cpp b/interface/src/plugins/display/WindowDisplayPlugin.cpp index b904a9d141..25162e9343 100644 --- a/interface/src/plugins/display/WindowDisplayPlugin.cpp +++ b/interface/src/plugins/display/WindowDisplayPlugin.cpp @@ -9,16 +9,17 @@ // #include "WindowDisplayPlugin.h" #include "RenderUtil.h" - -#include +#include "Application.h" WindowDisplayPlugin::WindowDisplayPlugin() { connect(&_timer, &QTimer::timeout, this, [&] { - emit requestRender(); +// if (qApp->getActiveDisplayPlugin() == this) { + emit requestRender(); +// } }); } -const QString WindowDisplayPlugin::NAME("WindowDisplayPlugin"); +const QString WindowDisplayPlugin::NAME("QWindow 2D Renderer"); const QString & WindowDisplayPlugin::getName() { return NAME; @@ -35,417 +36,3 @@ void WindowDisplayPlugin::deactivate() { GlWindowDisplayPlugin::deactivate(); } - -#if 0 - -// -// MainWindow.h -// interface -// -// Created by Mohammed Nafees on 04/06/2014. -// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef __hifi__MainWindow__ -#define __hifi__MainWindow__ - -#include -#include - -#include - -#define MSECS_PER_FRAME_WHEN_THROTTLED 66 - -class MainWindow : public QWindow { -public: - explicit MainWindow(QWindow* parent = NULL); - - // Some helpers for compatiblity with QMainWindow - void activateWindow() { - requestActivate(); - } - - bool isMinimized() const { - return windowState() == Qt::WindowMinimized; - } - - void stopFrameTimer(); - - bool isThrottleRendering() const; - - int getDeviceWidth() const; - int getDeviceHeight() const; - QSize getDeviceSize() const { return QSize(getDeviceWidth(), getDeviceHeight()); } - - /* - - - - private slots: - void activeChanged(Qt::ApplicationState state); - void throttleRender(); - bool eventFilter(QObject*, QEvent* event); - */ - public slots: - void restoreGeometry(); - void saveGeometry(); - -signals: - void windowGeometryChanged(QRect geometry); - void windowShown(bool shown); - -protected: - virtual void moveEvent(QMoveEvent* event); - virtual void resizeEvent(QResizeEvent* event); - virtual void showEvent(QShowEvent* event); - virtual void hideEvent(QHideEvent* event); - virtual void changeEvent(QEvent* event); - virtual void windowStateChanged(Qt::WindowState windowState); - virtual void activeChanged(); - - virtual void initializeGL(); - virtual void paintGL(); - virtual void resizeGL(int width, int height); - -private: - Setting::Handle _windowGeometry; - Setting::Handle _windowState; - Qt::WindowState _lastState{ Qt::WindowNoState }; - QOpenGLContext * _context{ nullptr }; - QTimer _frameTimer; - bool _throttleRendering{ false }; - int _idleRenderInterval{ MSECS_PER_FRAME_WHEN_THROTTLED }; -}; - -#endif /* defined(__hifi__MainWindow__) */ - - - - -// -// MainWindow.cpp -// interface -// -// Created by Mohammed Nafees on 04/06/2014. -// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Application.h" - -#include "MainWindow.h" -#include "Menu.h" -#include "Util.h" - -#include - - -MainWindow::MainWindow(QWindow * parent) : -QWindow(parent), -_windowGeometry("WindowGeometry"), -_windowState("WindowState", 0) { - setSurfaceType(QSurface::OpenGLSurface); - - QSurfaceFormat format; - // Qt Quick may need a depth and stencil buffer. Always make sure these are available. - format.setDepthBufferSize(16); - format.setStencilBufferSize(8); - format.setVersion(4, 1); - // Ugh.... - format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile); - setFormat(format); - - _context = new QOpenGLContext; - _context->setFormat(format); - _context->create(); - - show(); -} - -void MainWindow::restoreGeometry() { - QRect geometry = _windowGeometry.get(qApp->desktop()->availableGeometry()); - setGeometry(geometry); - - // Restore to maximized or full screen after restoring to windowed so that going windowed goes to good position and sizes. - int state = _windowState.get(Qt::WindowNoState) & ~Qt::WindowActive; - if (state != Qt::WindowNoState) { - setWindowState((Qt::WindowState)state); - } -} - -void MainWindow::saveGeometry() { - // Did not use geometry() on purpose, - // see http://doc.qt.io/qt-5/qsettings.html#restoring-the-state-of-a-gui-application - _windowState.set((int)windowState()); - - // Save position and size only if windowed so that have good values for windowed after starting maximized or full screen. - if (windowState() == Qt::WindowNoState) { - _windowGeometry.set(geometry()); - } -} - -void MainWindow::moveEvent(QMoveEvent* event) { - emit windowGeometryChanged(QRect(event->pos(), size())); - QWindow::moveEvent(event); -} - -void MainWindow::resizeEvent(QResizeEvent* event) { - emit windowGeometryChanged(QRect(QPoint(x(), y()), event->size())); - QWindow::resizeEvent(event); -} - -void MainWindow::showEvent(QShowEvent* event) { - if (event->spontaneous()) { - emit windowShown(true); - } - QWindow::showEvent(event); -} - -void MainWindow::hideEvent(QHideEvent* event) { - if (event->spontaneous()) { - emit windowShown(false); - } - QWindow::hideEvent(event); -} - -void MainWindow::windowStateChanged(Qt::WindowState windowState) { - // If we're changing from minimized to non-minimized or vice versas, emit - // a windowShown signal (i.e. don't emit the signal if we're going from - // fullscreen to nostate - if ((_lastState == Qt::WindowMinimized) ^ (windowState == Qt::WindowMinimized)) { - emit windowShown(windowState != Qt::WindowMinimized); - } - - bool fullscreen = windowState == Qt::WindowFullScreen; - if (fullscreen != Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)) { - Menu::getInstance()->setIsOptionChecked(MenuOption::Fullscreen, fullscreen); - } - - _lastState = windowState; - QWindow::windowStateChanged(windowState); -} - -void MainWindow::activeChanged() { - if (isActive()) { - emit windowShown(true); - } else { - emit windowShown(false); - } - QWindow::activeChanged(); -} - -void MainWindow::stopFrameTimer() { - _frameTimer.stop(); -} - -bool MainWindow::isThrottleRendering() const { - return _throttleRendering || isMinimized(); -} - - -int MainWindow::getDeviceWidth() const { - return width() * devicePixelRatio(); -} - -int MainWindow::getDeviceHeight() const { - return height() * devicePixelRatio(); -} - - - -void MainWindow::initializeGL() { - Application::getInstance()->initializeGL(); - // setAttribute(Qt::WA_AcceptTouchEvents); - // setAcceptDrops(true); - connect(Application::getInstance(), SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(activeChanged(Qt::ApplicationState))); - connect(&_frameTimer, SIGNAL(timeout()), this, SLOT(throttleRender())); -} - -void GLCanvas::resizeGL(int width, int height) { - Application::getInstance()->resizeGL(width, height); -} - -void GLCanvas::paintGL() { - if (!_throttleRendering && !Application::getInstance()->getWindow()->isMinimized()) { - //Need accurate frame timing for the oculus rift - if (OculusManager::isConnected()) { - OculusManager::beginFrameTiming(); - } - - Application::getInstance()->paintGL(); - - if (!OculusManager::isConnected()) { - swapBuffers(); - } else { - if (OculusManager::allowSwap()) { - swapBuffers(); - } - OculusManager::endFrameTiming(); - } - } -} - - - -/* - -GLCanvas::GLCanvas() : QGLWidget(QGL::NoDepthBuffer | QGL::NoStencilBuffer), -#ifdef Q_OS_LINUX -// Cause GLCanvas::eventFilter to be called. -// It wouldn't hurt to do this on Mac and PC too; but apparently it's only needed on linux. -qApp->installEventFilter(this); -#endif -} - -void GLCanvas::keyPressEvent(QKeyEvent* event) { -Application::getInstance()->keyPressEvent(event); -} - -void GLCanvas::keyReleaseEvent(QKeyEvent* event) { -Application::getInstance()->keyReleaseEvent(event); -} - -void GLCanvas::focusOutEvent(QFocusEvent* event) { -Application::getInstance()->focusOutEvent(event); -} - -void GLCanvas::mouseMoveEvent(QMouseEvent* event) { -Application::getInstance()->mouseMoveEvent(event); -} - -void GLCanvas::mousePressEvent(QMouseEvent* event) { -Application::getInstance()->mousePressEvent(event); -} - -void GLCanvas::mouseReleaseEvent(QMouseEvent* event) { -Application::getInstance()->mouseReleaseEvent(event); -} - -void GLCanvas::activeChanged(Qt::ApplicationState state) { -switch (state) { -case Qt::ApplicationActive: -// If we're active, stop the frame timer and the throttle. -_frameTimer.stop(); -_throttleRendering = false; -break; - -case Qt::ApplicationSuspended: -case Qt::ApplicationHidden: -// If we're hidden or are about to suspend, don't render anything. -_throttleRendering = false; -_frameTimer.stop(); -break; - -default: -// Otherwise, throttle. -if (!_throttleRendering && !Application::getInstance()->isAboutToQuit()) { -_frameTimer.start(_idleRenderInterval); -_throttleRendering = true; -} -break; -} -} - -void GLCanvas::throttleRender() { -_frameTimer.start(_idleRenderInterval); -if (!Application::getInstance()->getWindow()->isMinimized()) { -//Need accurate frame timing for the oculus rift -if (OculusManager::isConnected()) { -OculusManager::beginFrameTiming(); -} - -Application::getInstance()->paintGL(); -swapBuffers(); - -if (OculusManager::isConnected()) { -OculusManager::endFrameTiming(); -} -} -} - -int updateTime = 0; -bool GLCanvas::event(QEvent* event) { -switch (event->type()) { -case QEvent::TouchBegin: -Application::getInstance()->touchBeginEvent(static_cast(event)); -event->accept(); -return true; -case QEvent::TouchEnd: -Application::getInstance()->touchEndEvent(static_cast(event)); -return true; -case QEvent::TouchUpdate: -Application::getInstance()->touchUpdateEvent(static_cast(event)); -return true; -default: -break; -} -return QGLWidget::event(event); -} - -void GLCanvas::wheelEvent(QWheelEvent* event) { -Application::getInstance()->wheelEvent(event); -} - -void GLCanvas::dragEnterEvent(QDragEnterEvent* event) { -const QMimeData* mimeData = event->mimeData(); -foreach(QUrl url, mimeData->urls()) { -auto urlString = url.toString(); -if (Application::getInstance()->canAcceptURL(urlString)) { -event->acceptProposedAction(); -break; -} -} -} - -void GLCanvas::dropEvent(QDropEvent* event) { -Application::getInstance()->dropEvent(event); -} - -// Pressing Alt (and Meta) key alone activates the menubar because its style inherits the -// SHMenuBarAltKeyNavigation from QWindowsStyle. This makes it impossible for a scripts to -// receive keyPress events for the Alt (and Meta) key in a reliable manner. -// -// This filter catches events before QMenuBar can steal the keyboard focus. -// The idea was borrowed from -// http://www.archivum.info/qt-interest@trolltech.com/2006-09/00053/Re-(Qt4)-Alt-key-focus-QMenuBar-(solved).html - -bool GLCanvas::eventFilter(QObject*, QEvent* event) { -switch (event->type()) { -case QEvent::KeyPress: -case QEvent::KeyRelease: -case QEvent::ShortcutOverride: -{ -QKeyEvent* keyEvent = static_cast(event); -if (keyEvent->key() == Qt::Key_Alt || keyEvent->key() == Qt::Key_Meta) { -if (event->type() == QEvent::KeyPress) { -keyPressEvent(keyEvent); -} else if (event->type() == QEvent::KeyRelease) { -keyReleaseEvent(keyEvent); -} else { -QGLWidget::event(event); -} -return true; -} -} -default: -break; -} -return false; -} - -*/ -#endif diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 7c77c72f13..7441a24ddb 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -394,7 +394,6 @@ void ApplicationOverlay::displayOverlayTextureHmd(Camera& whichCamera) { glEnable(GL_LIGHTING); } glPopMatrix(); } -#endif // Draws the FBO texture for 3DTV. void ApplicationOverlay::displayOverlayTextureStereo(Camera& whichCamera, float aspectRatio, float fov) { @@ -489,6 +488,7 @@ void ApplicationOverlay::displayOverlayTextureStereo(Camera& whichCamera, float glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); glEnable(GL_LIGHTING); } +#endif void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const { @@ -501,13 +501,13 @@ void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origi glm::vec3 overlaySpaceDirection = glm::normalize(orientation * IDENTITY_FRONT); - const glm::vec3& hmdPosition = qApp->getCamera()->getHmdPosition(); - const glm::quat& hmdOrientation = qApp->getCamera()->getHmdRotation(); + glm::vec3 hmdPosition; // = qApp->getCamera()->getHmdPosition(); + glm::quat hmdOrientation; // = qApp->getCamera()->getHmdRotation(); - // We need the RAW camera orientation and position, because this is what the overlay is + // We need the camera orientation and position, because this is what the overlay is // rendered relative to - const glm::vec3 overlayPosition = qApp->getCamera()->getPosition() - hmdPosition; - const glm::quat overlayOrientation = qApp->getCamera()->getRotation() * glm::inverse(hmdOrientation); + const glm::vec3 overlayPosition = qApp->getCamera()->getPosition(); + const glm::quat overlayOrientation = qApp->getCamera()->getRotation(); // Intersection UI overlay space glm::vec3 worldSpaceDirection = overlayOrientation * overlaySpaceDirection; diff --git a/interface/src/ui/overlays/LocalModelsOverlay.cpp b/interface/src/ui/overlays/LocalModelsOverlay.cpp index e6fae4ff3d..7390ea4310 100644 --- a/interface/src/ui/overlays/LocalModelsOverlay.cpp +++ b/interface/src/ui/overlays/LocalModelsOverlay.cpp @@ -38,23 +38,18 @@ void LocalModelsOverlay::render(RenderArgs* args) { if (_visible) { float glowLevel = getGlowLevel(); - Glower* glower = NULL; + QSharedPointer glower; if (glowLevel > 0.0f) { - glower = new Glower(glowLevel); + glower = QSharedPointer(new Glower(glowLevel)); } glPushMatrix(); { Application* app = Application::getInstance(); - glm::vec3 oldTranslation = app->getViewMatrixTranslation(); - app->setViewMatrixTranslation(oldTranslation + _position); + Transform originalTransform = qApp->getViewTransform(); + qApp->getViewTransform().postTranslate(_position); _entityTreeRenderer->render(); - Application::getInstance()->setViewMatrixTranslation(oldTranslation); + qApp->setViewTransform(originalTransform); } glPopMatrix(); - - if (glower) { - delete glower; - } - } } diff --git a/libraries/octree/src/ViewFrustum.cpp b/libraries/octree/src/ViewFrustum.cpp index 2694314b57..80f0023970 100644 --- a/libraries/octree/src/ViewFrustum.cpp +++ b/libraries/octree/src/ViewFrustum.cpp @@ -27,14 +27,17 @@ using namespace std; -ViewFrustum::ViewFrustum() { -} - void ViewFrustum::setOrientation(const glm::quat& orientationAsQuaternion) { _orientation = orientationAsQuaternion; _right = glm::vec3(orientationAsQuaternion * glm::vec4(IDENTITY_RIGHT, 0.0f)); _up = glm::vec3(orientationAsQuaternion * glm::vec4(IDENTITY_UP, 0.0f)); _direction = glm::vec3(orientationAsQuaternion * glm::vec4(IDENTITY_FRONT, 0.0f)); + _view = glm::translate(mat4(), _position) * glm::mat4_cast(_orientation); +} + +void ViewFrustum::setPosition(const glm::vec3& position) { + _position = position; + _view = glm::translate(mat4(), _position) * glm::mat4_cast(_orientation); } // Order cooresponds to the order defined in the BoxVertex enum. diff --git a/libraries/octree/src/ViewFrustum.h b/libraries/octree/src/ViewFrustum.h index 0422120e51..43bc1d992e 100644 --- a/libraries/octree/src/ViewFrustum.h +++ b/libraries/octree/src/ViewFrustum.h @@ -36,11 +36,9 @@ const float DEFAULT_FAR_CLIP = (float)TREE_SCALE; class ViewFrustum { public: - ViewFrustum(); - // setters for camera attributes - void setPosition(const glm::vec3& p) { _position = p; } - void setOrientation(const glm::quat& orientationAsQuaternion); + void setPosition(const glm::vec3& position); + void setOrientation(const glm::quat& orientation); // getters for camera attributes const glm::vec3& getPosition() const { return _position; } @@ -54,7 +52,8 @@ public: void getFocalLength(float focalLength) { _focalLength = focalLength; } // getters for lens attributes - const glm::mat4 getProjection() const { return _projection; }; + const glm::mat4& getProjection() const { return _projection; }; + const glm::mat4& getView() const { return _view; }; float getWidth() const { return _width; } float getHeight() const { return _height; } float getFieldOfView() const { return _fieldOfView; } @@ -120,6 +119,7 @@ private: // camera location/orientation attributes glm::vec3 _position; // the position in world-frame glm::quat _orientation; + glm::mat4 _view; // Lens attributes glm::mat4 _projection; diff --git a/libraries/render-utils/src/AbstractViewStateInterface.h b/libraries/render-utils/src/AbstractViewStateInterface.h index a1447293b7..a0cd103804 100644 --- a/libraries/render-utils/src/AbstractViewStateInterface.h +++ b/libraries/render-utils/src/AbstractViewStateInterface.h @@ -30,10 +30,6 @@ public: /// Returns the shadow distances for the current view state virtual const glm::vec3& getShadowDistances() const = 0; - /// Computes the off-axis frustum parameters for the view frustum, taking mirroring into account. - virtual void computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal, - float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const = 0; - /// gets the current view frustum for rendering the view state virtual ViewFrustum* getCurrentViewFrustum() = 0; diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index f58419ec6e..ee53578a9e 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -18,6 +18,7 @@ #include #include +#include #include "AbstractViewStateInterface.h" #include "AmbientOcclusionEffect.h" @@ -112,7 +113,8 @@ void AmbientOcclusionEffect::render() { float left, right, bottom, top, nearVal, farVal; glm::vec4 nearClipPlane, farClipPlane; - _viewState->computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); + auto viewFrustum = _viewState->getCurrentViewFrustum(); + viewFrustum->computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); int viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 54e5388ec8..ff1c965b44 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -319,9 +319,10 @@ void DeferredLightingEffect::render() { glUniformMatrix4fv(locations->invViewMat, 1, false, reinterpret_cast< const GLfloat* >(&invViewMat)); } + auto viewFrustum = _viewState->getCurrentViewFrustum(); float left, right, bottom, top, nearVal, farVal; glm::vec4 nearClipPlane, farClipPlane; - _viewState->computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); + viewFrustum->computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); program->setUniformValue(locations->nearLocation, nearVal); float depthScale = (farVal - nearVal) / farVal; program->setUniformValue(locations->depthScale, depthScale); @@ -363,8 +364,8 @@ void DeferredLightingEffect::render() { // enlarge the scales slightly to account for tesselation const float SCALE_EXPANSION = 0.05f; - const glm::vec3& eyePoint = _viewState->getCurrentViewFrustum()->getPosition(); - float nearRadius = glm::distance(eyePoint, _viewState->getCurrentViewFrustum()->getNearTopLeft()); + const glm::vec3& eyePoint = viewFrustum->getPosition(); + float nearRadius = glm::distance(eyePoint, viewFrustum->getNearTopLeft()); auto geometryCache = DependencyManager::get();