diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8faf8d2002..eefbc69d25 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -428,10 +428,14 @@ void Application::resizeGL(int width, int height) { glViewport(0, 0, width, height); // shouldn't this account for the menu??? + updateProjectionMatrix(); + glLoadIdentity(); +} + +void Application::updateProjectionMatrix() { glMatrixMode(GL_PROJECTION); glLoadIdentity(); - // On window reshape, we need to tell OpenGL about our new setting float left, right, bottom, top, nearVal, farVal; glm::vec4 nearClipPlane, farClipPlane; _viewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); @@ -445,7 +449,6 @@ void Application::resizeGL(int width, int height) { glFrustum(left, right, bottom, top, nearVal, farVal); glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); } void Application::controlledBroadcastToNodes(unsigned char* broadcastData, size_t dataBytes, @@ -613,7 +616,7 @@ void Application::keyPressEvent(QKeyEvent* event) { } else { _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0, 0.001, 0)); } - resizeGL(_glWidget->width(), _glWidget->height()); + updateProjectionMatrix(); break; case Qt::Key_K: @@ -623,7 +626,7 @@ void Application::keyPressEvent(QKeyEvent* event) { } else { _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0, -0.001, 0)); } - resizeGL(_glWidget->width(), _glWidget->height()); + updateProjectionMatrix(); break; case Qt::Key_J: @@ -633,7 +636,7 @@ void Application::keyPressEvent(QKeyEvent* event) { } else { _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(-0.001, 0, 0)); } - resizeGL(_glWidget->width(), _glWidget->height()); + updateProjectionMatrix(); break; case Qt::Key_M: @@ -643,7 +646,7 @@ void Application::keyPressEvent(QKeyEvent* event) { } else { _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0.001, 0, 0)); } - resizeGL(_glWidget->width(), _glWidget->height()); + updateProjectionMatrix(); break; case Qt::Key_U: @@ -653,7 +656,7 @@ void Application::keyPressEvent(QKeyEvent* event) { } else { _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0, 0, -0.001)); } - resizeGL(_glWidget->width(), _glWidget->height()); + updateProjectionMatrix(); break; case Qt::Key_Y: @@ -663,7 +666,7 @@ void Application::keyPressEvent(QKeyEvent* event) { } else { _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0, 0, 0.001)); } - resizeGL(_glWidget->width(), _glWidget->height()); + updateProjectionMatrix(); break; case Qt::Key_H: Menu::getInstance()->triggerOption(MenuOption::Mirror); @@ -1800,6 +1803,20 @@ void Application::update(float deltaTime) { _myCamera.setModeShiftRate(1.0f); } } + + if (Menu::getInstance()->isOptionChecked(MenuOption::OffAxisProjection)) { + if (_faceshift.isActive()) { + const float EYE_OFFSET_SCALE = 0.005f; + glm::vec3 position = _faceshift.getHeadTranslation() * EYE_OFFSET_SCALE; + _myCamera.setEyeOffsetPosition(glm::vec3(-position.x, position.y, position.z)); + updateProjectionMatrix(); + + } else if (_webcam.isActive()) { + const float EYE_OFFSET_SCALE = 5.0f; + _myCamera.setEyeOffsetPosition(_webcam.getEstimatedPosition() * EYE_OFFSET_SCALE); + updateProjectionMatrix(); + } + } } // Update bandwidth dialog, if any @@ -1898,6 +1915,7 @@ void Application::updateAvatar(float deltaTime) { _myAvatar.setCameraAspectRatio(_viewFrustum.getAspectRatio()); _myAvatar.setCameraNearClip(_viewFrustum.getNearClip()); _myAvatar.setCameraFarClip(_viewFrustum.getFarClip()); + _myAvatar.setCameraEyeOffsetPosition(_viewFrustum.getEyeOffsetPosition()); NodeList* nodeList = NodeList::getInstance(); if (nodeList->getOwnerID() != UNKNOWN_NODE_ID) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 2d88bca73c..0630d3cbca 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -178,6 +178,7 @@ private slots: private: void resetCamerasOnResizeGL(Camera& camera, int width, int height); + void updateProjectionMatrix(); static bool sendVoxelsOperation(VoxelNode* node, void* extraData); static void processAvatarVoxelURLMessage(unsigned char* packetData, size_t dataBytes); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 36dad85f60..f96b45207c 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -210,6 +210,11 @@ Menu::Menu() : false, appInstance->getWebcam()->getGrabber(), SLOT(setLEDTrackingOn(bool))); + + addCheckableActionToQMenuAndActionHash(viewMenu, + MenuOption::OffAxisProjection, + 0, + false); addDisabledActionAndSeparator(viewMenu, "Stats"); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Stats, Qt::Key_Slash); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index bb2b1e6fc0..da773ad39e 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -170,6 +170,7 @@ namespace MenuOption { const QString LowRes = "Lower Resolution While Moving"; const QString Mirror = "Mirror"; const QString OcclusionCulling = "Occlusion Culling"; + const QString OffAxisProjection = "Off-Axis Projection"; const QString Oscilloscope = "Audio Oscilloscope"; const QString Pair = "Pair"; const QString PasteVoxels = "Paste"; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index d7aae578d5..2efb8d3da0 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -165,6 +165,8 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _cameraAspectRatio); destinationBuffer += packClipValueToTwoByte(destinationBuffer, _cameraNearClip); destinationBuffer += packClipValueToTwoByte(destinationBuffer, _cameraFarClip); + memcpy(destinationBuffer, &_cameraEyeOffsetPosition, sizeof(_cameraEyeOffsetPosition)); + destinationBuffer += sizeof(_cameraEyeOffsetPosition); // chat message *destinationBuffer++ = _chatMessage.size(); @@ -274,6 +276,8 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { sourceBuffer += unpackFloatRatioFromTwoByte(sourceBuffer,_cameraAspectRatio); sourceBuffer += unpackClipValueFromTwoByte(sourceBuffer,_cameraNearClip); sourceBuffer += unpackClipValueFromTwoByte(sourceBuffer,_cameraFarClip); + memcpy(&_cameraEyeOffsetPosition, sourceBuffer, sizeof(_cameraEyeOffsetPosition)); + sourceBuffer += sizeof(_cameraEyeOffsetPosition); // the rest is a chat message int chatMessageSize = *sourceBuffer++; diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 4f5e503cf4..7a65893e01 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -88,6 +88,7 @@ public: float getCameraAspectRatio() const { return _cameraAspectRatio; } float getCameraNearClip() const { return _cameraNearClip; } float getCameraFarClip() const { return _cameraFarClip; } + const glm::vec3& getCameraEyeOffsetPosition() const { return _cameraEyeOffsetPosition; } glm::vec3 calculateCameraDirection() const; @@ -98,6 +99,7 @@ public: void setCameraAspectRatio(float aspectRatio) { _cameraAspectRatio = aspectRatio; } void setCameraNearClip(float nearClip) { _cameraNearClip = nearClip; } void setCameraFarClip(float farClip) { _cameraFarClip = farClip; } + void setCameraEyeOffsetPosition(const glm::vec3& eyeOffsetPosition) { _cameraEyeOffsetPosition = eyeOffsetPosition; } // key state void setKeyState(KeyState s) { _keyState = s; } @@ -151,6 +153,7 @@ protected: float _cameraAspectRatio; float _cameraNearClip; float _cameraFarClip; + glm::vec3 _cameraEyeOffsetPosition; // key state KeyState _keyState; diff --git a/libraries/shared/src/PacketHeaders.cpp b/libraries/shared/src/PacketHeaders.cpp index 5a1c3f9b4c..8eb82cea4d 100644 --- a/libraries/shared/src/PacketHeaders.cpp +++ b/libraries/shared/src/PacketHeaders.cpp @@ -20,7 +20,7 @@ PACKET_VERSION versionForPacketType(PACKET_TYPE type) { return 1; case PACKET_TYPE_HEAD_DATA: - return 4; + return 5; case PACKET_TYPE_AVATAR_FACE_VIDEO: return 1; diff --git a/voxel-server/src/VoxelNodeData.cpp b/voxel-server/src/VoxelNodeData.cpp index 443edaaf2c..bdc1de69dc 100644 --- a/voxel-server/src/VoxelNodeData.cpp +++ b/voxel-server/src/VoxelNodeData.cpp @@ -73,6 +73,7 @@ bool VoxelNodeData::updateCurrentViewFrustum() { newestViewFrustum.setAspectRatio(getCameraAspectRatio()); newestViewFrustum.setNearClip(getCameraNearClip()); newestViewFrustum.setFarClip(getCameraFarClip()); + newestViewFrustum.setEyeOffsetPosition(getCameraEyeOffsetPosition()); // if there has been a change, then recalculate if (!newestViewFrustum.matches(_currentViewFrustum)) {