From 151a6edfb42fd530a01f2a608fcee0fe7f66bb52 Mon Sep 17 00:00:00 2001 From: Geenz Date: Thu, 6 Jun 2013 19:31:55 -0400 Subject: [PATCH 01/17] Check if our canvas has focus. If not, then ignore events passed to it. --- interface/src/Application.cpp | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c85e8ecd96..5329848adc 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -104,27 +104,39 @@ void GLCanvas::resizeGL(int width, int height) { } void GLCanvas::keyPressEvent(QKeyEvent* event) { - Application::getInstance()->keyPressEvent(event); + if (hasFocus()) { + Application::getInstance()->keyPressEvent(event); + } } void GLCanvas::keyReleaseEvent(QKeyEvent* event) { - Application::getInstance()->keyReleaseEvent(event); + if (hasFocus()) { + Application::getInstance()->keyReleaseEvent(event); + } } void GLCanvas::mouseMoveEvent(QMouseEvent* event) { - Application::getInstance()->mouseMoveEvent(event); + if (hasFocus()) { + Application::getInstance()->mouseMoveEvent(event); + } } void GLCanvas::mousePressEvent(QMouseEvent* event) { - Application::getInstance()->mousePressEvent(event); + if (hasFocus()) { + Application::getInstance()->mousePressEvent(event); + } } void GLCanvas::mouseReleaseEvent(QMouseEvent* event) { - Application::getInstance()->mouseReleaseEvent(event); + if (hasFocus()) { + Application::getInstance()->mouseReleaseEvent(event); + } } void GLCanvas::wheelEvent(QWheelEvent* event) { - Application::getInstance()->wheelEvent(event); + if (hasFocus()) { + Application::getInstance()->wheelEvent(event); + } } Application::Application(int& argc, char** argv, timeval &startup_time) : From 51340452df140b43eb2e46e67fccf17173d483fc Mon Sep 17 00:00:00 2001 From: Geenz Date: Thu, 6 Jun 2013 19:47:01 -0400 Subject: [PATCH 02/17] Use _mouseX and _mouseY for mouse look instead of the global mouse position when idle (prevents mouse look from accidentally triggering when the window is inactive). --- interface/src/Application.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5329848adc..3dec30204f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -104,37 +104,37 @@ void GLCanvas::resizeGL(int width, int height) { } void GLCanvas::keyPressEvent(QKeyEvent* event) { - if (hasFocus()) { + if (Application::activeWindow() != 0) { Application::getInstance()->keyPressEvent(event); } } void GLCanvas::keyReleaseEvent(QKeyEvent* event) { - if (hasFocus()) { + if (Application::activeWindow() != 0) { Application::getInstance()->keyReleaseEvent(event); } } void GLCanvas::mouseMoveEvent(QMouseEvent* event) { - if (hasFocus()) { + if (Application::activeWindow() != 0) { Application::getInstance()->mouseMoveEvent(event); } } void GLCanvas::mousePressEvent(QMouseEvent* event) { - if (hasFocus()) { + if (Application::activeWindow() != 0) { Application::getInstance()->mousePressEvent(event); } } void GLCanvas::mouseReleaseEvent(QMouseEvent* event) { - if (hasFocus()) { + if (Application::activeWindow() != 0) { Application::getInstance()->mouseReleaseEvent(event); } } void GLCanvas::wheelEvent(QWheelEvent* event) { - if (hasFocus()) { + if (Application::activeWindow() != 0) { Application::getInstance()->wheelEvent(event); } } @@ -888,7 +888,7 @@ void Application::idle() { // Update from Mouse if (_mouseLook->isChecked()) { - QPoint mouse = QCursor::pos(); + QPoint mouse = QPoint(_mouseX, _mouseY); _myAvatar.updateFromMouse(_glWidget->mapFromGlobal(mouse).x(), _glWidget->mapFromGlobal(mouse).y(), _glWidget->width(), From 7cefa3fe7b691f8f8416f697ecb9b42e0a58c2b9 Mon Sep 17 00:00:00 2001 From: Geenz Date: Thu, 6 Jun 2013 19:58:33 -0400 Subject: [PATCH 03/17] Check if our main window is our application window within Application's event handling functions. --- interface/src/Application.cpp | 602 +++++++++++++++++----------------- 1 file changed, 301 insertions(+), 301 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3dec30204f..12cf003f82 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -104,39 +104,27 @@ void GLCanvas::resizeGL(int width, int height) { } void GLCanvas::keyPressEvent(QKeyEvent* event) { - if (Application::activeWindow() != 0) { - Application::getInstance()->keyPressEvent(event); - } + Application::getInstance()->keyPressEvent(event); } void GLCanvas::keyReleaseEvent(QKeyEvent* event) { - if (Application::activeWindow() != 0) { - Application::getInstance()->keyReleaseEvent(event); - } + Application::getInstance()->keyReleaseEvent(event); } void GLCanvas::mouseMoveEvent(QMouseEvent* event) { - if (Application::activeWindow() != 0) { - Application::getInstance()->mouseMoveEvent(event); - } + Application::getInstance()->mouseMoveEvent(event); } void GLCanvas::mousePressEvent(QMouseEvent* event) { - if (Application::activeWindow() != 0) { - Application::getInstance()->mousePressEvent(event); - } + Application::getInstance()->mousePressEvent(event); } void GLCanvas::mouseReleaseEvent(QMouseEvent* event) { - if (Application::activeWindow() != 0) { - Application::getInstance()->mouseReleaseEvent(event); - } + Application::getInstance()->mouseReleaseEvent(event); } void GLCanvas::wheelEvent(QWheelEvent* event) { - if (Application::activeWindow() != 0) { - Application::getInstance()->wheelEvent(event); - } + Application::getInstance()->wheelEvent(event); } Application::Application(int& argc, char** argv, timeval &startup_time) : @@ -433,314 +421,326 @@ static void sendVoxelServerAddScene() { } void Application::keyPressEvent(QKeyEvent* event) { - if (_chatEntryOn) { - if (_chatEntry.keyPressEvent(event)) { - _myAvatar.setKeyState(event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete ? - DELETE_KEY_DOWN : INSERT_KEY_DOWN); - _myAvatar.setChatMessage(string(_chatEntry.getContents().size(), SOLID_BLOCK_CHAR)); - - } else { - _myAvatar.setChatMessage(_chatEntry.getContents()); - _chatEntry.clear(); - _chatEntryOn = false; - setMenuShortcutsEnabled(true); + if (activeWindow() == _window) { + if (_chatEntryOn) { + if (_chatEntry.keyPressEvent(event)) { + _myAvatar.setKeyState(event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete ? + DELETE_KEY_DOWN : INSERT_KEY_DOWN); + _myAvatar.setChatMessage(string(_chatEntry.getContents().size(), SOLID_BLOCK_CHAR)); + + } else { + _myAvatar.setChatMessage(_chatEntry.getContents()); + _chatEntry.clear(); + _chatEntryOn = false; + setMenuShortcutsEnabled(true); + } + return; } - return; - } - - bool shifted = event->modifiers().testFlag(Qt::ShiftModifier); - switch (event->key()) { - case Qt::Key_BracketLeft: - _viewFrustumOffsetYaw -= 0.5; - break; - - case Qt::Key_BracketRight: - _viewFrustumOffsetYaw += 0.5; - break; - case Qt::Key_BraceLeft: - _viewFrustumOffsetPitch -= 0.5; - break; - - case Qt::Key_BraceRight: - _viewFrustumOffsetPitch += 0.5; - break; - - case Qt::Key_ParenLeft: - _viewFrustumOffsetRoll -= 0.5; - break; - - case Qt::Key_ParenRight: - _viewFrustumOffsetRoll += 0.5; - break; - - case Qt::Key_Less: - _viewFrustumOffsetDistance -= 0.5; - break; - - case Qt::Key_Greater: - _viewFrustumOffsetDistance += 0.5; - break; - - case Qt::Key_Comma: - _viewFrustumOffsetUp -= 0.05; - break; - - case Qt::Key_Period: - _viewFrustumOffsetUp += 0.05; - break; - - case Qt::Key_Ampersand: - _paintOn = !_paintOn; - setupPaintingVoxel(); - break; - - case Qt::Key_AsciiCircum: - shiftPaintingColor(); - break; - - case Qt::Key_Percent: - sendVoxelServerAddScene(); - break; - - case Qt::Key_Semicolon: - _audio.startEchoTest(); - break; - - case Qt::Key_L: - _displayLevels = !_displayLevels; - break; - - case Qt::Key_E: - _myAvatar.setDriveKeys(UP, 1); - break; - - case Qt::Key_C: - _myAvatar.setDriveKeys(DOWN, 1); - break; - - case Qt::Key_W: - _myAvatar.setDriveKeys(FWD, 1); - break; - - case Qt::Key_S: - _myAvatar.setDriveKeys(BACK, 1); - break; - - case Qt::Key_Space: - resetSensors(); - break; - - case Qt::Key_G: - goHome(); - break; - - case Qt::Key_A: - _myAvatar.setDriveKeys(ROT_LEFT, 1); - break; - - case Qt::Key_D: - _myAvatar.setDriveKeys(ROT_RIGHT, 1); - break; - - case Qt::Key_Return: - case Qt::Key_Enter: - _chatEntryOn = true; - _myAvatar.setKeyState(NO_KEY_DOWN); - _myAvatar.setChatMessage(string()); - setMenuShortcutsEnabled(false); - break; - - case Qt::Key_Up: - _myAvatar.setDriveKeys(shifted ? UP : FWD, 1); - break; - - case Qt::Key_Down: - _myAvatar.setDriveKeys(shifted ? DOWN : BACK, 1); - break; - - case Qt::Key_Left: - _myAvatar.setDriveKeys(shifted ? LEFT : ROT_LEFT, 1); - break; - - case Qt::Key_Right: - _myAvatar.setDriveKeys(shifted ? RIGHT : ROT_RIGHT, 1); - break; - - case Qt::Key_I: - if (shifted) { - _myCamera.setEyeOffsetOrientation(glm::normalize( - glm::quat(glm::vec3(0.002f, 0, 0)) * _myCamera.getEyeOffsetOrientation())); - } else { - _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0, 0.001, 0)); - } - resizeGL(_glWidget->width(), _glWidget->height()); - break; - - case Qt::Key_K: - if (shifted) { - _myCamera.setEyeOffsetOrientation(glm::normalize( - glm::quat(glm::vec3(-0.002f, 0, 0)) * _myCamera.getEyeOffsetOrientation())); - } else { - _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0, -0.001, 0)); - } - resizeGL(_glWidget->width(), _glWidget->height()); - break; - - case Qt::Key_J: - if (shifted) { - _myCamera.setEyeOffsetOrientation(glm::normalize( - glm::quat(glm::vec3(0, 0.002f, 0)) * _myCamera.getEyeOffsetOrientation())); - } else { - _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(-0.001, 0, 0)); - } - resizeGL(_glWidget->width(), _glWidget->height()); - break; - - case Qt::Key_M: - if (shifted) { - _myCamera.setEyeOffsetOrientation(glm::normalize( - glm::quat(glm::vec3(0, -0.002f, 0)) * _myCamera.getEyeOffsetOrientation())); - } else { - _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0.001, 0, 0)); - } - resizeGL(_glWidget->width(), _glWidget->height()); - break; - - case Qt::Key_U: - if (shifted) { - _myCamera.setEyeOffsetOrientation(glm::normalize( - glm::quat(glm::vec3(0, 0, -0.002f)) * _myCamera.getEyeOffsetOrientation())); - } else { - _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0, 0, -0.001)); - } - resizeGL(_glWidget->width(), _glWidget->height()); - break; - - case Qt::Key_Y: - if (shifted) { - _myCamera.setEyeOffsetOrientation(glm::normalize( - glm::quat(glm::vec3(0, 0, 0.002f)) * _myCamera.getEyeOffsetOrientation())); - } else { - _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0, 0, 0.001)); - } - resizeGL(_glWidget->width(), _glWidget->height()); - break; - case Qt::Key_Backspace: - case Qt::Key_Delete: - if (_selectVoxelMode->isChecked()) { - deleteVoxelUnderCursor(); - } - break; - - default: - event->ignore(); - break; + bool shifted = event->modifiers().testFlag(Qt::ShiftModifier); + switch (event->key()) { + case Qt::Key_BracketLeft: + _viewFrustumOffsetYaw -= 0.5; + break; + + case Qt::Key_BracketRight: + _viewFrustumOffsetYaw += 0.5; + break; + + case Qt::Key_BraceLeft: + _viewFrustumOffsetPitch -= 0.5; + break; + + case Qt::Key_BraceRight: + _viewFrustumOffsetPitch += 0.5; + break; + + case Qt::Key_ParenLeft: + _viewFrustumOffsetRoll -= 0.5; + break; + + case Qt::Key_ParenRight: + _viewFrustumOffsetRoll += 0.5; + break; + + case Qt::Key_Less: + _viewFrustumOffsetDistance -= 0.5; + break; + + case Qt::Key_Greater: + _viewFrustumOffsetDistance += 0.5; + break; + + case Qt::Key_Comma: + _viewFrustumOffsetUp -= 0.05; + break; + + case Qt::Key_Period: + _viewFrustumOffsetUp += 0.05; + break; + + case Qt::Key_Ampersand: + _paintOn = !_paintOn; + setupPaintingVoxel(); + break; + + case Qt::Key_AsciiCircum: + shiftPaintingColor(); + break; + + case Qt::Key_Percent: + sendVoxelServerAddScene(); + break; + + case Qt::Key_Semicolon: + _audio.startEchoTest(); + break; + + case Qt::Key_L: + _displayLevels = !_displayLevels; + break; + + case Qt::Key_E: + _myAvatar.setDriveKeys(UP, 1); + break; + + case Qt::Key_C: + _myAvatar.setDriveKeys(DOWN, 1); + break; + + case Qt::Key_W: + _myAvatar.setDriveKeys(FWD, 1); + break; + + case Qt::Key_S: + _myAvatar.setDriveKeys(BACK, 1); + break; + + case Qt::Key_Space: + resetSensors(); + break; + + case Qt::Key_G: + goHome(); + break; + + case Qt::Key_A: + _myAvatar.setDriveKeys(ROT_LEFT, 1); + break; + + case Qt::Key_D: + _myAvatar.setDriveKeys(ROT_RIGHT, 1); + break; + + case Qt::Key_Return: + case Qt::Key_Enter: + _chatEntryOn = true; + _myAvatar.setKeyState(NO_KEY_DOWN); + _myAvatar.setChatMessage(string()); + setMenuShortcutsEnabled(false); + break; + + case Qt::Key_Up: + _myAvatar.setDriveKeys(shifted ? UP : FWD, 1); + break; + + case Qt::Key_Down: + _myAvatar.setDriveKeys(shifted ? DOWN : BACK, 1); + break; + + case Qt::Key_Left: + _myAvatar.setDriveKeys(shifted ? LEFT : ROT_LEFT, 1); + break; + + case Qt::Key_Right: + _myAvatar.setDriveKeys(shifted ? RIGHT : ROT_RIGHT, 1); + break; + + case Qt::Key_I: + if (shifted) { + _myCamera.setEyeOffsetOrientation(glm::normalize( + glm::quat(glm::vec3(0.002f, 0, 0)) * _myCamera.getEyeOffsetOrientation())); + } else { + _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0, 0.001, 0)); + } + resizeGL(_glWidget->width(), _glWidget->height()); + break; + + case Qt::Key_K: + if (shifted) { + _myCamera.setEyeOffsetOrientation(glm::normalize( + glm::quat(glm::vec3(-0.002f, 0, 0)) * _myCamera.getEyeOffsetOrientation())); + } else { + _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0, -0.001, 0)); + } + resizeGL(_glWidget->width(), _glWidget->height()); + break; + + case Qt::Key_J: + if (shifted) { + _myCamera.setEyeOffsetOrientation(glm::normalize( + glm::quat(glm::vec3(0, 0.002f, 0)) * _myCamera.getEyeOffsetOrientation())); + } else { + _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(-0.001, 0, 0)); + } + resizeGL(_glWidget->width(), _glWidget->height()); + break; + + case Qt::Key_M: + if (shifted) { + _myCamera.setEyeOffsetOrientation(glm::normalize( + glm::quat(glm::vec3(0, -0.002f, 0)) * _myCamera.getEyeOffsetOrientation())); + } else { + _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0.001, 0, 0)); + } + resizeGL(_glWidget->width(), _glWidget->height()); + break; + + case Qt::Key_U: + if (shifted) { + _myCamera.setEyeOffsetOrientation(glm::normalize( + glm::quat(glm::vec3(0, 0, -0.002f)) * _myCamera.getEyeOffsetOrientation())); + } else { + _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0, 0, -0.001)); + } + resizeGL(_glWidget->width(), _glWidget->height()); + break; + + case Qt::Key_Y: + if (shifted) { + _myCamera.setEyeOffsetOrientation(glm::normalize( + glm::quat(glm::vec3(0, 0, 0.002f)) * _myCamera.getEyeOffsetOrientation())); + } else { + _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0, 0, 0.001)); + } + resizeGL(_glWidget->width(), _glWidget->height()); + break; + case Qt::Key_Backspace: + case Qt::Key_Delete: + if (_selectVoxelMode->isChecked()) { + deleteVoxelUnderCursor(); + } + break; + + default: + event->ignore(); + break; + } } } void Application::keyReleaseEvent(QKeyEvent* event) { - if (_chatEntryOn) { - _myAvatar.setKeyState(NO_KEY_DOWN); - return; - } - - switch (event->key()) { - case Qt::Key_E: - _myAvatar.setDriveKeys(UP, 0); - break; + if (activeWindow() == _window) { + if (_chatEntryOn) { + _myAvatar.setKeyState(NO_KEY_DOWN); + return; + } - case Qt::Key_C: - _myAvatar.setDriveKeys(DOWN, 0); - break; - - case Qt::Key_W: - _myAvatar.setDriveKeys(FWD, 0); - break; - - case Qt::Key_S: - _myAvatar.setDriveKeys(BACK, 0); - break; - - case Qt::Key_A: - _myAvatar.setDriveKeys(ROT_LEFT, 0); - break; + switch (event->key()) { + case Qt::Key_E: + _myAvatar.setDriveKeys(UP, 0); + break; - case Qt::Key_D: - _myAvatar.setDriveKeys(ROT_RIGHT, 0); - break; - - case Qt::Key_Up: - _myAvatar.setDriveKeys(FWD, 0); - _myAvatar.setDriveKeys(UP, 0); - break; - - case Qt::Key_Down: - _myAvatar.setDriveKeys(BACK, 0); - _myAvatar.setDriveKeys(DOWN, 0); - break; - - case Qt::Key_Left: - _myAvatar.setDriveKeys(LEFT, 0); - _myAvatar.setDriveKeys(ROT_LEFT, 0); - break; - - case Qt::Key_Right: - _myAvatar.setDriveKeys(RIGHT, 0); - _myAvatar.setDriveKeys(ROT_RIGHT, 0); - break; - - default: - event->ignore(); - break; + case Qt::Key_C: + _myAvatar.setDriveKeys(DOWN, 0); + break; + + case Qt::Key_W: + _myAvatar.setDriveKeys(FWD, 0); + break; + + case Qt::Key_S: + _myAvatar.setDriveKeys(BACK, 0); + break; + + case Qt::Key_A: + _myAvatar.setDriveKeys(ROT_LEFT, 0); + break; + + case Qt::Key_D: + _myAvatar.setDriveKeys(ROT_RIGHT, 0); + break; + + case Qt::Key_Up: + _myAvatar.setDriveKeys(FWD, 0); + _myAvatar.setDriveKeys(UP, 0); + break; + + case Qt::Key_Down: + _myAvatar.setDriveKeys(BACK, 0); + _myAvatar.setDriveKeys(DOWN, 0); + break; + + case Qt::Key_Left: + _myAvatar.setDriveKeys(LEFT, 0); + _myAvatar.setDriveKeys(ROT_LEFT, 0); + break; + + case Qt::Key_Right: + _myAvatar.setDriveKeys(RIGHT, 0); + _myAvatar.setDriveKeys(ROT_RIGHT, 0); + break; + + default: + event->ignore(); + break; + } } } void Application::mouseMoveEvent(QMouseEvent* event) { - _mouseX = event->x(); - _mouseY = event->y(); - - // detect drag - glm::vec3 mouseVoxelPos(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z); - if (!_justEditedVoxel && mouseVoxelPos != _lastMouseVoxelPos) { - if (event->buttons().testFlag(Qt::LeftButton)) { - maybeEditVoxelUnderCursor(); + if (activeWindow() == _window) { + _mouseX = event->x(); + _mouseY = event->y(); + + // detect drag + glm::vec3 mouseVoxelPos(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z); + if (!_justEditedVoxel && mouseVoxelPos != _lastMouseVoxelPos) { + if (event->buttons().testFlag(Qt::LeftButton)) { + maybeEditVoxelUnderCursor(); - } else if (event->buttons().testFlag(Qt::RightButton) && checkedVoxelModeAction() != 0) { - deleteVoxelUnderCursor(); + } else if (event->buttons().testFlag(Qt::RightButton) && checkedVoxelModeAction() != 0) { + deleteVoxelUnderCursor(); + } } } } void Application::mousePressEvent(QMouseEvent* event) { - if (event->button() == Qt::LeftButton) { - _mouseX = event->x(); - _mouseY = event->y(); - _mousePressed = true; - maybeEditVoxelUnderCursor(); - - } else if (event->button() == Qt::RightButton && checkedVoxelModeAction() != 0) { - deleteVoxelUnderCursor(); + if (activeWindow() == _window) { + if (event->button() == Qt::LeftButton) { + _mouseX = event->x(); + _mouseY = event->y(); + _mousePressed = true; + maybeEditVoxelUnderCursor(); + + } else if (event->button() == Qt::RightButton && checkedVoxelModeAction() != 0) { + deleteVoxelUnderCursor(); + } } } void Application::mouseReleaseEvent(QMouseEvent* event) { - if (event->button() == Qt::LeftButton) { - _mouseX = event->x(); - _mouseY = event->y(); - _mousePressed = false; + if (activeWindow() == _window) { + if (event->button() == Qt::LeftButton) { + _mouseX = event->x(); + _mouseY = event->y(); + _mousePressed = false; + } } } void Application::wheelEvent(QWheelEvent* event) { - if (checkedVoxelModeAction() == 0) { - event->ignore(); - return; - } - if (event->delta() > 0) { - increaseVoxelSize(); - } else { - decreaseVoxelSize(); + if (activeWindow() == _window) { + if (checkedVoxelModeAction() == 0) { + event->ignore(); + return; + } + if (event->delta() > 0) { + increaseVoxelSize(); + } else { + decreaseVoxelSize(); + } } } @@ -888,7 +888,7 @@ void Application::idle() { // Update from Mouse if (_mouseLook->isChecked()) { - QPoint mouse = QPoint(_mouseX, _mouseY); + QPoint mouse(_mouseX, _mouseY); _myAvatar.updateFromMouse(_glWidget->mapFromGlobal(mouse).x(), _glWidget->mapFromGlobal(mouse).y(), _glWidget->width(), From dc8a6c2725e50388c7f227f59ffdb0f67210d3fc Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 7 Jun 2013 11:30:41 -0700 Subject: [PATCH 04/17] Store the avatar voxel URL along with the rest of the avatar settings. --- interface/src/Application.cpp | 9 +++------ interface/src/Avatar.cpp | 4 ++++ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index acb82412ca..745e788232 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1023,7 +1023,7 @@ void Application::editPreferences() { QFormLayout* form = new QFormLayout(); layout->addLayout(form, 1); - QLineEdit* avatarURL = new QLineEdit(_settings->value("avatarURL").toString()); + QLineEdit* avatarURL = new QLineEdit(_myAvatar.getVoxels()->getVoxelURL().toString()); avatarURL->setMinimumWidth(400); form->addRow("Avatar URL:", avatarURL); @@ -1040,7 +1040,6 @@ void Application::editPreferences() { return; } QUrl url(avatarURL->text()); - _settings->setValue("avatarURL", url); _myAvatar.getVoxels()->setVoxelURL(url); sendAvatarVoxelURLMessage(url); @@ -1532,10 +1531,6 @@ void Application::init() { _myCamera.setModeShiftRate(1.0f); _myAvatar.setDisplayingLookatVectors(false); - QUrl avatarURL = _settings->value("avatarURL").toUrl(); - _myAvatar.getVoxels()->setVoxelURL(avatarURL); - sendAvatarVoxelURLMessage(avatarURL); - QCursor::setPos(_headMouseX, _headMouseY); OculusManager::connect(); @@ -1547,6 +1542,8 @@ void Application::init() { gettimeofday(&_lastTimeIdle, NULL); loadSettings(); + + sendAvatarVoxelURLMessage(_myAvatar.getVoxels()->getVoxelURL()); } void Application::updateAvatar(float deltaTime) { diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 918cd02c78..e5c5a76a70 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -1225,6 +1225,8 @@ void Avatar::loadData(QSettings* set) { _position.y = set->value("position_y", _position.y).toFloat(); _position.z = set->value("position_z", _position.z).toFloat(); + _voxels.setVoxelURL(set->value("voxelURL").toUrl()); + set->endGroup(); } @@ -1244,6 +1246,8 @@ void Avatar::saveData(QSettings* set) { set->setValue("position_y", _position.y); set->setValue("position_z", _position.z); + set->setValue("voxelURL", _voxels.getVoxelURL()); + set->endGroup(); } From a5c24b5333e3e8b395bcc486335980271a2d5c2b Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 7 Jun 2013 11:32:26 -0700 Subject: [PATCH 05/17] OK, we don't need this sync. Clearly the problem I was seeing on OS X lies elsewhere. --- interface/src/Application.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 745e788232..8c636bb061 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2536,8 +2536,6 @@ void Application::saveSettings(QSettings* set) { set->setValue("headCameraPitchYawScale", _headCameraPitchYawScale); scanMenuBar(&Application::saveAction, set); getAvatar()->saveData(set); - - set->sync(); } void Application::importSettings() { From 953aec35e68749e262835000f8bc730747e17b3d Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 7 Jun 2013 11:48:29 -0700 Subject: [PATCH 06/17] Use the default QSettings constructor and let it get the application info from the QCoreApplication properties. --- interface/src/Application.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8c636bb061..3aac8f5667 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -227,8 +227,11 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _glWidget->setMouseTracking(true); // initialization continues in initializeGL when OpenGL context is ready - - QCoreApplication::setOrganizationDomain("highfidelity.io"); // Used by QSettings on OS X + + // these are used, for example, to identify the application's preferences + setApplicationName("Interface"); + setOrganizationDomain("highfidelity.io"); + setOrganizationName("High Fidelity"); } void Application::initializeGL() { @@ -1476,7 +1479,7 @@ void Application::initMenu() { settingsMenu->addAction("Export settings", this, SLOT(exportSettings())); _networkAccessManager = new QNetworkAccessManager(this); - _settings = new QSettings("High Fidelity", "Interface", this); + _settings = new QSettings(this); } void Application::updateFrustumRenderModeAction() { From 86316bc674241c53985ab5909422ebe42d308a00 Mon Sep 17 00:00:00 2001 From: Geenz Date: Fri, 7 Jun 2013 16:00:13 -0400 Subject: [PATCH 07/17] Don't render the voxel selection when we're moving over a maximum velocity. --- interface/src/Application.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 12cf003f82..0d3c5284a6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -694,6 +694,7 @@ void Application::mouseMoveEvent(QMouseEvent* event) { _mouseY = event->y(); // detect drag + printLog("Avatar velocity x, y, z: %f, %f, %f\n", _myAvatar.getVelocity().x, _myAvatar.getVelocity().y, _myAvatar.getVelocity().z); glm::vec3 mouseVoxelPos(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z); if (!_justEditedVoxel && mouseVoxelPos != _lastMouseVoxelPos) { if (event->buttons().testFlag(Qt::LeftButton)) { @@ -2283,6 +2284,9 @@ void Application::shiftPaintingColor() { void Application::maybeEditVoxelUnderCursor() { + if (_myAvatar.getVelocity().x > 0.5) { + printLog("We're going faster than 1 m/s!\n"); + } if (_addVoxelMode->isChecked() || _colorVoxelMode->isChecked()) { if (_mouseVoxel.s != 0) { PACKET_HEADER message = (_destructiveAddVoxel->isChecked() ? From 82db3885520bd71cd1568b4cfee8dad26e04f968 Mon Sep 17 00:00:00 2001 From: Geenz Date: Fri, 7 Jun 2013 16:08:27 -0400 Subject: [PATCH 08/17] Real max velocity stuff. --- interface/src/Application.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9b59ff045b..d8a9d8f7a0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -695,7 +695,6 @@ void Application::mouseMoveEvent(QMouseEvent* event) { _mouseY = event->y(); // detect drag - printLog("Avatar velocity x, y, z: %f, %f, %f\n", _myAvatar.getVelocity().x, _myAvatar.getVelocity().y, _myAvatar.getVelocity().z); glm::vec3 mouseVoxelPos(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z); if (!_justEditedVoxel && mouseVoxelPos != _lastMouseVoxelPos) { if (event->buttons().testFlag(Qt::LeftButton)) { @@ -786,6 +785,8 @@ static glm::vec3 getFaceVector(BoxFace face) { } } +const float MAX_AVATAR_EDIT_VELOCITY = 1.0f; + void Application::idle() { timeval check; gettimeofday(&check, NULL); @@ -821,7 +822,10 @@ void Application::idle() { _myAvatar.setMouseRay(mouseRayOrigin, mouseRayDirection); _mouseVoxel.s = 0.0f; - if (checkedVoxelModeAction() != 0) { + if (checkedVoxelModeAction() != 0 && + _myAvatar.getVelocity().x < MAX_AVATAR_EDIT_VELOCITY && + _myAvatar.getVelocity().y < MAX_AVATAR_EDIT_VELOCITY && + _myAvatar.getVelocity().z < MAX_AVATAR_EDIT_VELOCITY) { float distance; BoxFace face; if (_voxels.findRayIntersection(mouseRayOrigin, mouseRayDirection, _mouseVoxel, distance, face)) { @@ -2276,9 +2280,6 @@ void Application::shiftPaintingColor() { void Application::maybeEditVoxelUnderCursor() { - if (_myAvatar.getVelocity().x > 0.5) { - printLog("We're going faster than 1 m/s!\n"); - } if (_addVoxelMode->isChecked() || _colorVoxelMode->isChecked()) { if (_mouseVoxel.s != 0) { PACKET_HEADER message = (_destructiveAddVoxel->isChecked() ? From 9da10df9f2dcefb47aa9fe232cfe2f96bbc8897d Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 7 Jun 2013 13:12:59 -0700 Subject: [PATCH 09/17] We need to set these before initMenu, as that's where we create the QSettings. --- interface/src/Application.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3aac8f5667..ee66d13afd 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -215,6 +215,11 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _window->setCentralWidget(_glWidget); + // these are used, for example, to identify the application's preferences + setApplicationName("Interface"); + setOrganizationDomain("highfidelity.io"); + setOrganizationName("High Fidelity"); + initMenu(); QRect available = desktop()->availableGeometry(); @@ -227,11 +232,6 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _glWidget->setMouseTracking(true); // initialization continues in initializeGL when OpenGL context is ready - - // these are used, for example, to identify the application's preferences - setApplicationName("Interface"); - setOrganizationDomain("highfidelity.io"); - setOrganizationName("High Fidelity"); } void Application::initializeGL() { From 1c8d4f7717adaf4c39f0e74babb9239a2334f908 Mon Sep 17 00:00:00 2001 From: Geenz Date: Fri, 7 Jun 2013 16:20:51 -0400 Subject: [PATCH 10/17] Get the average velocity of the avatar. --- interface/src/Application.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d8a9d8f7a0..95b2d3824e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -820,12 +820,13 @@ void Application::idle() { // tell my avatar the posiion and direction of the ray projected ino the world based on the mouse position _myAvatar.setMouseRay(mouseRayOrigin, mouseRayDirection); - + _mouseVoxel.s = 0.0f; if (checkedVoxelModeAction() != 0 && - _myAvatar.getVelocity().x < MAX_AVATAR_EDIT_VELOCITY && - _myAvatar.getVelocity().y < MAX_AVATAR_EDIT_VELOCITY && - _myAvatar.getVelocity().z < MAX_AVATAR_EDIT_VELOCITY) { + (fabs(_myAvatar.getVelocity().x) + + fabs(_myAvatar.getVelocity().y) + + fabs(_myAvatar.getVelocity().z)) / 3 < MAX_AVATAR_EDIT_VELOCITY) { + float distance; BoxFace face; if (_voxels.findRayIntersection(mouseRayOrigin, mouseRayDirection, _mouseVoxel, distance, face)) { From 65ec02044ef7911f095bde9f76e346be1c19b65a Mon Sep 17 00:00:00 2001 From: Geenz Date: Fri, 7 Jun 2013 16:34:10 -0400 Subject: [PATCH 11/17] Add a distance check for selected voxels. --- interface/src/Application.cpp | 53 ++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 95b2d3824e..a9b76084cc 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -786,6 +786,7 @@ static glm::vec3 getFaceVector(BoxFace face) { } const float MAX_AVATAR_EDIT_VELOCITY = 1.0f; +const float MAX_VOXEL_EDIT_DISTANCE = 20.0f; void Application::idle() { timeval check; @@ -829,32 +830,38 @@ void Application::idle() { float distance; BoxFace face; - if (_voxels.findRayIntersection(mouseRayOrigin, mouseRayDirection, _mouseVoxel, distance, face)) { - // find the nearest voxel with the desired scale - if (_mouseVoxelScale > _mouseVoxel.s) { - // choose the larger voxel that encompasses the one selected - _mouseVoxel.x = _mouseVoxelScale * floorf(_mouseVoxel.x / _mouseVoxelScale); - _mouseVoxel.y = _mouseVoxelScale * floorf(_mouseVoxel.y / _mouseVoxelScale); - _mouseVoxel.z = _mouseVoxelScale * floorf(_mouseVoxel.z / _mouseVoxelScale); - _mouseVoxel.s = _mouseVoxelScale; + if (_voxels.findRayIntersection(mouseRayOrigin, mouseRayDirection, _mouseVoxel, distance, face)) { - } else { - glm::vec3 faceVector = getFaceVector(face); - if (_mouseVoxelScale < _mouseVoxel.s) { - // find the closest contained voxel - glm::vec3 pt = (mouseRayOrigin + mouseRayDirection * distance) / (float)TREE_SCALE - - faceVector * (_mouseVoxelScale * 0.5f); - _mouseVoxel.x = _mouseVoxelScale * floorf(pt.x / _mouseVoxelScale); - _mouseVoxel.y = _mouseVoxelScale * floorf(pt.y / _mouseVoxelScale); - _mouseVoxel.z = _mouseVoxelScale * floorf(pt.z / _mouseVoxelScale); + if (distance < MAX_VOXEL_EDIT_DISTANCE) { + // find the nearest voxel with the desired scale + if (_mouseVoxelScale > _mouseVoxel.s) { + // choose the larger voxel that encompasses the one selected + _mouseVoxel.x = _mouseVoxelScale * floorf(_mouseVoxel.x / _mouseVoxelScale); + _mouseVoxel.y = _mouseVoxelScale * floorf(_mouseVoxel.y / _mouseVoxelScale); + _mouseVoxel.z = _mouseVoxelScale * floorf(_mouseVoxel.z / _mouseVoxelScale); _mouseVoxel.s = _mouseVoxelScale; + + } else { + glm::vec3 faceVector = getFaceVector(face); + if (_mouseVoxelScale < _mouseVoxel.s) { + // find the closest contained voxel + glm::vec3 pt = (mouseRayOrigin + mouseRayDirection * distance) / (float)TREE_SCALE - + faceVector * (_mouseVoxelScale * 0.5f); + _mouseVoxel.x = _mouseVoxelScale * floorf(pt.x / _mouseVoxelScale); + _mouseVoxel.y = _mouseVoxelScale * floorf(pt.y / _mouseVoxelScale); + _mouseVoxel.z = _mouseVoxelScale * floorf(pt.z / _mouseVoxelScale); + _mouseVoxel.s = _mouseVoxelScale; + } + if (_addVoxelMode->isChecked()) { + // use the face to determine the side on which to create a neighbor + _mouseVoxel.x += faceVector.x * _mouseVoxel.s; + _mouseVoxel.y += faceVector.y * _mouseVoxel.s; + _mouseVoxel.z += faceVector.z * _mouseVoxel.s; + } } - if (_addVoxelMode->isChecked()) { - // use the face to determine the side on which to create a neighbor - _mouseVoxel.x += faceVector.x * _mouseVoxel.s; - _mouseVoxel.y += faceVector.y * _mouseVoxel.s; - _mouseVoxel.z += faceVector.z * _mouseVoxel.s; - } + } else { + // We're not within range. Don't render the selection. + _mouseVoxel.s = 0; } } else if (_addVoxelMode->isChecked() || _selectVoxelMode->isChecked()) { // place the voxel a fixed distance away From 89ef026ce8ee6411ae4fae38bd5aadd9962594fc Mon Sep 17 00:00:00 2001 From: Geenz Date: Fri, 7 Jun 2013 16:42:22 -0400 Subject: [PATCH 12/17] Remove seemingly unnecessary coordinate space conversion. --- interface/src/Application.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a9b76084cc..4a4e59f6b5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -902,9 +902,8 @@ void Application::idle() { // Update from Mouse if (_mouseLook->isChecked()) { - QPoint mouse(_mouseX, _mouseY); - _myAvatar.updateFromMouse(_glWidget->mapFromGlobal(mouse).x(), - _glWidget->mapFromGlobal(mouse).y(), + _myAvatar.updateFromMouse(_mouseX, + _mouseY, _glWidget->width(), _glWidget->height()); } From 75c89f2c2277a942a9db4531ecd5ffecc660a497 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 7 Jun 2013 13:42:49 -0700 Subject: [PATCH 13/17] OK, I found the problem: duplication of state for the "autosave" option. Let's just use the QAction, as does everything else. --- interface/src/Application.cpp | 10 +++------- interface/src/Application.h | 3 --- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ee66d13afd..49e91f6352 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -215,7 +215,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _window->setCentralWidget(_glWidget); - // these are used, for example, to identify the application's preferences + // these are used, for example, to identify the application settings setApplicationName("Interface"); setOrganizationDomain("highfidelity.io"); setOrganizationName("High Fidelity"); @@ -968,7 +968,7 @@ void Application::terminate() { // Close serial port // close(serial_fd); - if (_autosave) { + if (_settingsAutosave->isChecked()) { saveSettings(); _settings->sync(); } @@ -1471,7 +1471,7 @@ void Application::initMenu() { debugMenu->addAction("Wants View Delta Sending", this, SLOT(setWantsDelta(bool)))->setCheckable(true); QMenu* settingsMenu = menuBar->addMenu("Settings"); - (_settingsAutosave = settingsMenu->addAction("Autosave", this, SLOT(setAutosave(bool))))->setCheckable(true); + (_settingsAutosave = settingsMenu->addAction("Autosave"))->setCheckable(true); _settingsAutosave->setChecked(true); settingsMenu->addAction("Load settings", this, SLOT(loadSettings())); settingsMenu->addAction("Save settings", this, SLOT(saveSettings())); @@ -2521,10 +2521,6 @@ void Application::saveAction(QSettings* set, QAction* action) { set->setValue(action->text(), action->isChecked()); } -void Application::setAutosave(bool wantsAutosave) { - _autosave = wantsAutosave; -} - void Application::loadSettings(QSettings* set) { if (!set) set = getSettings(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 3fe1e8e4b5..2316f23dc0 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -112,7 +112,6 @@ private slots: void decreaseVoxelSize(); void increaseVoxelSize(); void chooseVoxelPaintColor(); - void setAutosave(bool wantsAutosave); void loadSettings(QSettings* set = NULL); void saveSettings(QSettings* set = NULL); void importSettings(); @@ -293,8 +292,6 @@ private: int _packetsPerSecond; int _bytesPerSecond; int _bytesCount; - - bool _autosave; // True if the autosave is on. }; #endif /* defined(__interface__Application__) */ From ac2b7d7f48b89021350415aeef5873cf7383863c Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 7 Jun 2013 15:20:26 -0700 Subject: [PATCH 14/17] Fix for initial camera transition. --- interface/src/Application.cpp | 354 +++++++++++++++++----------------- interface/src/Application.h | 1 + interface/src/Camera.cpp | 2 +- 3 files changed, 181 insertions(+), 176 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 49e91f6352..05f780b422 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -292,6 +292,9 @@ void Application::initializeGL() { printLog("%s", title); _window->setWindowTitle(title); } + + // update before the first render + update(0.0f); } void Application::paintGL() { @@ -783,181 +786,7 @@ void Application::idle() { // Only run simulation code if more than IDLE_SIMULATE_MSECS have passed since last time we ran if (diffclock(&_lastTimeIdle, &check) > IDLE_SIMULATE_MSECS) { - - float deltaTime = 1.f/_fps; - - // Use Transmitter Hand to move hand if connected, else use mouse - if (_myTransmitter.isConnected()) { - const float HAND_FORCE_SCALING = 0.01f; - glm::vec3 estimatedRotation = _myTransmitter.getEstimatedRotation(); - glm::vec3 handForce(-estimatedRotation.z, -estimatedRotation.x, estimatedRotation.y); - _myAvatar.setMovedHandOffset(handForce * HAND_FORCE_SCALING); - } else { - // update behaviors for avatar hand movement: handControl takes mouse values as input, - // and gives back 3D values modulated for smooth transitioning between interaction modes. - _handControl.update(_mouseX, _mouseY); - _myAvatar.setMovedHandOffset(_handControl.getValues()); - } - - // tell my avatar if the mouse is being pressed... - _myAvatar.setMousePressed(_mousePressed); - - // check what's under the mouse and update the mouse voxel - glm::vec3 mouseRayOrigin, mouseRayDirection; - _viewFrustum.computePickRay(_mouseX / (float)_glWidget->width(), - _mouseY / (float)_glWidget->height(), mouseRayOrigin, mouseRayDirection); - - // tell my avatar the posiion and direction of the ray projected ino the world based on the mouse position - _myAvatar.setMouseRay(mouseRayOrigin, mouseRayDirection); - - _mouseVoxel.s = 0.0f; - if (checkedVoxelModeAction() != 0) { - float distance; - BoxFace face; - if (_voxels.findRayIntersection(mouseRayOrigin, mouseRayDirection, _mouseVoxel, distance, face)) { - // find the nearest voxel with the desired scale - if (_mouseVoxelScale > _mouseVoxel.s) { - // choose the larger voxel that encompasses the one selected - _mouseVoxel.x = _mouseVoxelScale * floorf(_mouseVoxel.x / _mouseVoxelScale); - _mouseVoxel.y = _mouseVoxelScale * floorf(_mouseVoxel.y / _mouseVoxelScale); - _mouseVoxel.z = _mouseVoxelScale * floorf(_mouseVoxel.z / _mouseVoxelScale); - _mouseVoxel.s = _mouseVoxelScale; - - } else { - glm::vec3 faceVector = getFaceVector(face); - if (_mouseVoxelScale < _mouseVoxel.s) { - // find the closest contained voxel - glm::vec3 pt = (mouseRayOrigin + mouseRayDirection * distance) / (float)TREE_SCALE - - faceVector * (_mouseVoxelScale * 0.5f); - _mouseVoxel.x = _mouseVoxelScale * floorf(pt.x / _mouseVoxelScale); - _mouseVoxel.y = _mouseVoxelScale * floorf(pt.y / _mouseVoxelScale); - _mouseVoxel.z = _mouseVoxelScale * floorf(pt.z / _mouseVoxelScale); - _mouseVoxel.s = _mouseVoxelScale; - } - if (_addVoxelMode->isChecked()) { - // use the face to determine the side on which to create a neighbor - _mouseVoxel.x += faceVector.x * _mouseVoxel.s; - _mouseVoxel.y += faceVector.y * _mouseVoxel.s; - _mouseVoxel.z += faceVector.z * _mouseVoxel.s; - } - } - } else if (_addVoxelMode->isChecked() || _selectVoxelMode->isChecked()) { - // place the voxel a fixed distance away - float worldMouseVoxelScale = _mouseVoxelScale * TREE_SCALE; - glm::vec3 pt = mouseRayOrigin + mouseRayDirection * (2.0f + worldMouseVoxelScale * 0.5f); - _mouseVoxel.x = _mouseVoxelScale * floorf(pt.x / worldMouseVoxelScale); - _mouseVoxel.y = _mouseVoxelScale * floorf(pt.y / worldMouseVoxelScale); - _mouseVoxel.z = _mouseVoxelScale * floorf(pt.z / worldMouseVoxelScale); - _mouseVoxel.s = _mouseVoxelScale; - } - - if (_deleteVoxelMode->isChecked()) { - // red indicates deletion - _mouseVoxel.red = 255; - _mouseVoxel.green = _mouseVoxel.blue = 0; - } else if (_selectVoxelMode->isChecked()) { - // yellow indicates deletion - _mouseVoxel.red = _mouseVoxel.green = 255; - _mouseVoxel.blue = 0; - } else { // _addVoxelMode->isChecked() || _colorVoxelMode->isChecked() - QColor paintColor = _voxelPaintColor->data().value(); - _mouseVoxel.red = paintColor.red(); - _mouseVoxel.green = paintColor.green(); - _mouseVoxel.blue = paintColor.blue(); - } - - // if we just edited, use the currently selected voxel as the "last" for drag detection - if (_justEditedVoxel) { - _lastMouseVoxelPos = glm::vec3(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z); - _justEditedVoxel = false; - } - } - - // walking triggers the handControl to stop - if (_myAvatar.getMode() == AVATAR_MODE_WALKING) { - _handControl.stop(); - } - - // Update from Mouse - if (_mouseLook->isChecked()) { - QPoint mouse = QCursor::pos(); - _myAvatar.updateFromMouse(_glWidget->mapFromGlobal(mouse).x(), - _glWidget->mapFromGlobal(mouse).y(), - _glWidget->width(), - _glWidget->height()); - } - - // Read serial port interface devices - if (_serialHeadSensor.active) { - _serialHeadSensor.readData(deltaTime); - } - - // Update transmitter - - // Sample hardware, update view frustum if needed, and send avatar data to mixer/agents - updateAvatar(deltaTime); - - // read incoming packets from network - if (!_enableNetworkThread) { - networkReceive(0); - } - - //loop through all the other avatars and simulate them... - AgentList* agentList = AgentList::getInstance(); - agentList->lock(); - for(AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { - if (agent->getLinkedData() != NULL) { - Avatar *avatar = (Avatar *)agent->getLinkedData(); - if (!avatar->isInitialized()) { - avatar->init(); - } - avatar->simulate(deltaTime, NULL); - avatar->setMouseRay(mouseRayOrigin, mouseRayDirection); - } - } - agentList->unlock(); - - // Simulate myself - _myAvatar.setGravity(_environment.getGravity(_myAvatar.getPosition())); - if (_transmitterDrives->isChecked() && _myTransmitter.isConnected()) { - _myAvatar.simulate(deltaTime, &_myTransmitter); - } else { - _myAvatar.simulate(deltaTime, NULL); - } - - if (TESTING_AVATAR_TOUCH) { - if (_myCamera.getMode() != CAMERA_MODE_THIRD_PERSON) { - _myCamera.setMode(CAMERA_MODE_THIRD_PERSON); - _myCamera.setModeShiftRate(1.0f); - } - } else { - if (_myCamera.getMode() != CAMERA_MODE_MIRROR && !OculusManager::isConnected()) { - if (_manualFirstPerson) { - if (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON ) { - _myCamera.setMode(CAMERA_MODE_FIRST_PERSON); - _myCamera.setModeShiftRate(1.0f); - } - } else { - if (_myAvatar.getIsNearInteractingOther()) { - if (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON) { - _myCamera.setMode(CAMERA_MODE_FIRST_PERSON); - _myCamera.setModeShiftRate(1.0f); - } - } else { - if (_myCamera.getMode() != CAMERA_MODE_THIRD_PERSON) { - _myCamera.setMode(CAMERA_MODE_THIRD_PERSON); - _myCamera.setModeShiftRate(1.0f); - } - } - } - } - } - - // Update audio stats for procedural sounds - #ifndef _WIN32 - _audio.setLastAcceleration(_myAvatar.getThrust()); - _audio.setLastVelocity(_myAvatar.getVelocity()); - #endif + update(1.0f / _fps); _glWidget->updateGL(); _lastTimeIdle = check; @@ -1549,6 +1378,181 @@ void Application::init() { sendAvatarVoxelURLMessage(_myAvatar.getVoxels()->getVoxelURL()); } +void Application::update(float deltaTime) { + // Use Transmitter Hand to move hand if connected, else use mouse + if (_myTransmitter.isConnected()) { + const float HAND_FORCE_SCALING = 0.01f; + glm::vec3 estimatedRotation = _myTransmitter.getEstimatedRotation(); + glm::vec3 handForce(-estimatedRotation.z, -estimatedRotation.x, estimatedRotation.y); + _myAvatar.setMovedHandOffset(handForce * HAND_FORCE_SCALING); + } else { + // update behaviors for avatar hand movement: handControl takes mouse values as input, + // and gives back 3D values modulated for smooth transitioning between interaction modes. + _handControl.update(_mouseX, _mouseY); + _myAvatar.setMovedHandOffset(_handControl.getValues()); + } + + // tell my avatar if the mouse is being pressed... + _myAvatar.setMousePressed(_mousePressed); + + // check what's under the mouse and update the mouse voxel + glm::vec3 mouseRayOrigin, mouseRayDirection; + _viewFrustum.computePickRay(_mouseX / (float)_glWidget->width(), + _mouseY / (float)_glWidget->height(), mouseRayOrigin, mouseRayDirection); + + // tell my avatar the posiion and direction of the ray projected ino the world based on the mouse position + _myAvatar.setMouseRay(mouseRayOrigin, mouseRayDirection); + + _mouseVoxel.s = 0.0f; + if (checkedVoxelModeAction() != 0) { + float distance; + BoxFace face; + if (_voxels.findRayIntersection(mouseRayOrigin, mouseRayDirection, _mouseVoxel, distance, face)) { + // find the nearest voxel with the desired scale + if (_mouseVoxelScale > _mouseVoxel.s) { + // choose the larger voxel that encompasses the one selected + _mouseVoxel.x = _mouseVoxelScale * floorf(_mouseVoxel.x / _mouseVoxelScale); + _mouseVoxel.y = _mouseVoxelScale * floorf(_mouseVoxel.y / _mouseVoxelScale); + _mouseVoxel.z = _mouseVoxelScale * floorf(_mouseVoxel.z / _mouseVoxelScale); + _mouseVoxel.s = _mouseVoxelScale; + + } else { + glm::vec3 faceVector = getFaceVector(face); + if (_mouseVoxelScale < _mouseVoxel.s) { + // find the closest contained voxel + glm::vec3 pt = (mouseRayOrigin + mouseRayDirection * distance) / (float)TREE_SCALE - + faceVector * (_mouseVoxelScale * 0.5f); + _mouseVoxel.x = _mouseVoxelScale * floorf(pt.x / _mouseVoxelScale); + _mouseVoxel.y = _mouseVoxelScale * floorf(pt.y / _mouseVoxelScale); + _mouseVoxel.z = _mouseVoxelScale * floorf(pt.z / _mouseVoxelScale); + _mouseVoxel.s = _mouseVoxelScale; + } + if (_addVoxelMode->isChecked()) { + // use the face to determine the side on which to create a neighbor + _mouseVoxel.x += faceVector.x * _mouseVoxel.s; + _mouseVoxel.y += faceVector.y * _mouseVoxel.s; + _mouseVoxel.z += faceVector.z * _mouseVoxel.s; + } + } + } else if (_addVoxelMode->isChecked() || _selectVoxelMode->isChecked()) { + // place the voxel a fixed distance away + float worldMouseVoxelScale = _mouseVoxelScale * TREE_SCALE; + glm::vec3 pt = mouseRayOrigin + mouseRayDirection * (2.0f + worldMouseVoxelScale * 0.5f); + _mouseVoxel.x = _mouseVoxelScale * floorf(pt.x / worldMouseVoxelScale); + _mouseVoxel.y = _mouseVoxelScale * floorf(pt.y / worldMouseVoxelScale); + _mouseVoxel.z = _mouseVoxelScale * floorf(pt.z / worldMouseVoxelScale); + _mouseVoxel.s = _mouseVoxelScale; + } + + if (_deleteVoxelMode->isChecked()) { + // red indicates deletion + _mouseVoxel.red = 255; + _mouseVoxel.green = _mouseVoxel.blue = 0; + } else if (_selectVoxelMode->isChecked()) { + // yellow indicates deletion + _mouseVoxel.red = _mouseVoxel.green = 255; + _mouseVoxel.blue = 0; + } else { // _addVoxelMode->isChecked() || _colorVoxelMode->isChecked() + QColor paintColor = _voxelPaintColor->data().value(); + _mouseVoxel.red = paintColor.red(); + _mouseVoxel.green = paintColor.green(); + _mouseVoxel.blue = paintColor.blue(); + } + + // if we just edited, use the currently selected voxel as the "last" for drag detection + if (_justEditedVoxel) { + _lastMouseVoxelPos = glm::vec3(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z); + _justEditedVoxel = false; + } + } + + // walking triggers the handControl to stop + if (_myAvatar.getMode() == AVATAR_MODE_WALKING) { + _handControl.stop(); + } + + // Update from Mouse + if (_mouseLook->isChecked()) { + QPoint mouse = QCursor::pos(); + _myAvatar.updateFromMouse(_glWidget->mapFromGlobal(mouse).x(), + _glWidget->mapFromGlobal(mouse).y(), + _glWidget->width(), + _glWidget->height()); + } + + // Read serial port interface devices + if (_serialHeadSensor.active) { + _serialHeadSensor.readData(deltaTime); + } + + // Update transmitter + + // Sample hardware, update view frustum if needed, and send avatar data to mixer/agents + updateAvatar(deltaTime); + + // read incoming packets from network + if (!_enableNetworkThread) { + networkReceive(0); + } + + //loop through all the other avatars and simulate them... + AgentList* agentList = AgentList::getInstance(); + agentList->lock(); + for(AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { + if (agent->getLinkedData() != NULL) { + Avatar *avatar = (Avatar *)agent->getLinkedData(); + if (!avatar->isInitialized()) { + avatar->init(); + } + avatar->simulate(deltaTime, NULL); + avatar->setMouseRay(mouseRayOrigin, mouseRayDirection); + } + } + agentList->unlock(); + + // Simulate myself + _myAvatar.setGravity(_environment.getGravity(_myAvatar.getPosition())); + if (_transmitterDrives->isChecked() && _myTransmitter.isConnected()) { + _myAvatar.simulate(deltaTime, &_myTransmitter); + } else { + _myAvatar.simulate(deltaTime, NULL); + } + + if (TESTING_AVATAR_TOUCH) { + if (_myCamera.getMode() != CAMERA_MODE_THIRD_PERSON) { + _myCamera.setMode(CAMERA_MODE_THIRD_PERSON); + _myCamera.setModeShiftRate(1.0f); + } + } else { + if (_myCamera.getMode() != CAMERA_MODE_MIRROR && !OculusManager::isConnected()) { + if (_manualFirstPerson) { + if (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON ) { + _myCamera.setMode(CAMERA_MODE_FIRST_PERSON); + _myCamera.setModeShiftRate(1.0f); + } + } else { + if (_myAvatar.getIsNearInteractingOther()) { + if (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON) { + _myCamera.setMode(CAMERA_MODE_FIRST_PERSON); + _myCamera.setModeShiftRate(1.0f); + } + } else { + if (_myCamera.getMode() != CAMERA_MODE_THIRD_PERSON) { + _myCamera.setMode(CAMERA_MODE_THIRD_PERSON); + _myCamera.setModeShiftRate(1.0f); + } + } + } + } + } + + // Update audio stats for procedural sounds + #ifndef _WIN32 + _audio.setLastAcceleration(_myAvatar.getThrust()); + _audio.setLastVelocity(_myAvatar.getVelocity()); + #endif +} + void Application::updateAvatar(float deltaTime) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 2316f23dc0..53807e993e 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -131,6 +131,7 @@ private: void initDisplay(); void init(); + void update(float deltaTime); void updateAvatar(float deltaTime); void loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum); diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp index 9fc0033fc4..84655226d8 100644 --- a/interface/src/Camera.cpp +++ b/interface/src/Camera.cpp @@ -71,7 +71,7 @@ void Camera::updateFollowMode(float deltaTime) { _distance = _previousDistance * (1.0f - _modeShift) + _newDistance * _modeShift; _tightness = _previousTightness * (1.0f - _modeShift) + _newTightness * _modeShift; - if (_linearModeShift > 1.0f ) { + if (_needsToInitialize || _linearModeShift > 1.0f) { _linearModeShift = 1.0f; _modeShift = 1.0f; _upShift = _newUpShift; From 46c66c39e573b7ad695cab2e924ee9da5569eea6 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 7 Jun 2013 17:23:23 -0700 Subject: [PATCH 15/17] implement keyhole frustum --- interface/src/Application.cpp | 16 ++- interface/src/Application.h | 2 +- libraries/voxels/src/AABox.h | 3 +- libraries/voxels/src/ViewFrustum.cpp | 207 +++++++++++++++++---------- libraries/voxels/src/ViewFrustum.h | 93 ++++++------ 5 files changed, 203 insertions(+), 118 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index acb82412ca..1e4fc5459f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1498,6 +1498,9 @@ void Application::updateFrustumRenderModeAction() { case FRUSTUM_DRAW_MODE_FAR_PLANE: _frustumRenderModeAction->setText("Render Mode - Far"); break; + case FRUSTUM_DRAW_MODE_KEYHOLE: + _frustumRenderModeAction->setText("Render Mode - Keyhole"); + break; } } @@ -2237,9 +2240,20 @@ void Application::renderViewFrustum(ViewFrustum& viewFrustum) { glVertex3f(viewFrustum.getNearTopLeft().x, viewFrustum.getNearTopLeft().y, viewFrustum.getNearTopLeft().z); glVertex3f(viewFrustum.getFarTopLeft().x, viewFrustum.getFarTopLeft().y, viewFrustum.getFarTopLeft().z); } - glEnd(); glEnable(GL_LIGHTING); + + if (_frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || _frustumDrawingMode == FRUSTUM_DRAW_MODE_KEYHOLE) { + // Draw the keyhole + float keyholeRadius = viewFrustum.getKeyholeRadius(); + if (keyholeRadius > 0.0f) { + glPushMatrix(); + glColor4f(1,1,0,1); + glTranslatef(position.x, position.y, position.z); // where we actually want it! + glutWireSphere(keyholeRadius, 20, 20); + glPopMatrix(); + } + } } void Application::setupPaintingVoxel() { diff --git a/interface/src/Application.h b/interface/src/Application.h index 3fe1e8e4b5..974a43e3fe 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -226,7 +226,7 @@ private: ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc. enum FrustumDrawMode { FRUSTUM_DRAW_MODE_ALL, FRUSTUM_DRAW_MODE_VECTORS, FRUSTUM_DRAW_MODE_PLANES, - FRUSTUM_DRAW_MODE_NEAR_PLANE, FRUSTUM_DRAW_MODE_FAR_PLANE, FRUSTUM_DRAW_MODE_COUNT }; + FRUSTUM_DRAW_MODE_NEAR_PLANE, FRUSTUM_DRAW_MODE_FAR_PLANE, FRUSTUM_DRAW_MODE_KEYHOLE, FRUSTUM_DRAW_MODE_COUNT }; FrustumDrawMode _frustumDrawingMode; float _viewFrustumOffsetYaw; // the following variables control yaw, pitch, roll and distance form regular diff --git a/libraries/voxels/src/AABox.h b/libraries/voxels/src/AABox.h index f0d8e005aa..6ac9fc2f2e 100644 --- a/libraries/voxels/src/AABox.h +++ b/libraries/voxels/src/AABox.h @@ -29,7 +29,8 @@ class AABox public: - AABox(const glm::vec3& corner, float x, float y, float z) : _corner(corner), _size(x,y,z) { }; + AABox(const glm::vec3& corner, float size) : _corner(corner), _size(size, size, size) { }; + AABox(const glm::vec3& corner, float x, float y, float z) : _corner(corner), _size(x, y, z) { }; AABox(const glm::vec3& corner, const glm::vec3& size) : _corner(corner), _size(size) { }; AABox() : _corner(0,0,0), _size(0,0,0) { } ~AABox() { } diff --git a/libraries/voxels/src/ViewFrustum.cpp b/libraries/voxels/src/ViewFrustum.cpp index b3c890ed07..b47199310c 100644 --- a/libraries/voxels/src/ViewFrustum.cpp +++ b/libraries/voxels/src/ViewFrustum.cpp @@ -29,6 +29,7 @@ ViewFrustum::ViewFrustum() : _aspectRatio(1.0), _nearClip(0.1), _farClip(500.0), + _keyholeRadius(DEFAULT_KEYHOLE_RADIUS), _farTopLeft(0,0,0), _farTopRight(0,0,0), _farBottomLeft(0,0,0), @@ -36,7 +37,9 @@ ViewFrustum::ViewFrustum() : _nearTopLeft(0,0,0), _nearTopRight(0,0,0), _nearBottomLeft(0,0,0), - _nearBottomRight(0,0,0) { } + _nearBottomRight(0,0,0) +{ +} void ViewFrustum::setOrientation(const glm::quat& orientationAsQuaternion) { _orientation = orientationAsQuaternion; @@ -114,42 +117,6 @@ void ViewFrustum::calculate() { } -void ViewFrustum::dump() const { - - printLog("position.x=%f, position.y=%f, position.z=%f\n", _position.x, _position.y, _position.z); - printLog("direction.x=%f, direction.y=%f, direction.z=%f\n", _direction.x, _direction.y, _direction.z); - printLog("up.x=%f, up.y=%f, up.z=%f\n", _up.x, _up.y, _up.z); - printLog("right.x=%f, right.y=%f, right.z=%f\n", _right.x, _right.y, _right.z); - - printLog("farDist=%f\n", _farClip); - - printLog("nearDist=%f\n", _nearClip); - - printLog("eyeOffsetPosition=%f,%f,%f\n", _eyeOffsetPosition.x, _eyeOffsetPosition.y, _eyeOffsetPosition.z); - - printLog("eyeOffsetOrientation=%f,%f,%f,%f\n", _eyeOffsetOrientation.x, _eyeOffsetOrientation.y, - _eyeOffsetOrientation.z, _eyeOffsetOrientation.w); - - printLog("farTopLeft.x=%f, farTopLeft.y=%f, farTopLeft.z=%f\n", - _farTopLeft.x, _farTopLeft.y, _farTopLeft.z); - printLog("farTopRight.x=%f, farTopRight.y=%f, farTopRight.z=%f\n", - _farTopRight.x, _farTopRight.y, _farTopRight.z); - printLog("farBottomLeft.x=%f, farBottomLeft.y=%f, farBottomLeft.z=%f\n", - _farBottomLeft.x, _farBottomLeft.y, _farBottomLeft.z); - printLog("farBottomRight.x=%f, farBottomRight.y=%f, farBottomRight.z=%f\n", - _farBottomRight.x, _farBottomRight.y, _farBottomRight.z); - - printLog("nearTopLeft.x=%f, nearTopLeft.y=%f, nearTopLeft.z=%f\n", - _nearTopLeft.x, _nearTopLeft.y, _nearTopLeft.z); - printLog("nearTopRight.x=%f, nearTopRight.y=%f, nearTopRight.z=%f\n", - _nearTopRight.x, _nearTopRight.y, _nearTopRight.z); - printLog("nearBottomLeft.x=%f, nearBottomLeft.y=%f, nearBottomLeft.z=%f\n", - _nearBottomLeft.x, _nearBottomLeft.y, _nearBottomLeft.z); - printLog("nearBottomRight.x=%f, nearBottomRight.y=%f, nearBottomRight.z=%f\n", - _nearBottomRight.x, _nearBottomRight.y, _nearBottomRight.z); -} - - //enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE }; const char* ViewFrustum::debugPlaneName (int plane) const { switch (plane) { @@ -163,52 +130,147 @@ const char* ViewFrustum::debugPlaneName (int plane) const { return "Unknown"; } +ViewFrustum::location ViewFrustum::pointInSphere(const glm::vec3& point, const glm::vec3& center, float radius ) const { -ViewFrustum::location ViewFrustum::pointInFrustum(const glm::vec3& point) const { - - //printf("ViewFrustum::pointInFrustum() point=%f,%f,%f\n",point.x,point.y,point.z); - //dump(); - - ViewFrustum::location result = INSIDE; - for(int i=0; i < 6; i++) { - float distance = _planes[i].distance(point); - - //printf("plane[%d] %s -- distance=%f \n",i,debugPlaneName(i),distance); + ViewFrustum::location result = INTERSECT; - if (distance < 0) { - return OUTSIDE; + float distance = glm::distance(point, center); + if (distance > radius) { + result = OUTSIDE; + } else if (distance < radius) { + result = INSIDE; + } + + return result; +} + +// To determine if two spheres intersect, simply calculate the distance between the centers of the two spheres. +// If the distance is greater than the sum of the two sphere radii, they don’t intersect. Otherwise they intersect. +// If the distance plus the radius of sphere A is less than the radius of sphere B then, sphere A is inside of sphere B +ViewFrustum::location ViewFrustum::sphereInSphere(const glm::vec3& centerA, float radiusA, + const glm::vec3& centerB, float radiusB ) const { + + ViewFrustum::location result = INTERSECT; + + float distanceFromAtoB = glm::distance(centerA, centerB); + if (distanceFromAtoB > (radiusA + radiusB)) { + result = OUTSIDE; + } else if ((distanceFromAtoB + radiusA) < radiusB) { + result = INSIDE; + } + + return result; +} + + +// A box is inside a sphere if all of its corners are inside the sphere +// A box intersects a sphere if any of its edges (as rays) interesect the sphere +// A box is outside a sphere if none of its edges (as rays) interesect the sphere +ViewFrustum::location ViewFrustum::boxInSphere(const AABox& box, const glm::vec3& center, float radius) const { + glm::vec3 penetration; + bool intersects = box.findSpherePenetration(center, radius, penetration); + + ViewFrustum::location result = OUTSIDE; + + // if the box intersects the sphere, then it may also be inside... calculate further + if (intersects) { + result = INTERSECT; + + // test all the corners, if they are all inside the sphere, the entire box is in the sphere + glm::vec3 testPoint = box.getCorner(); + glm::vec3 size = box.getSize(); + if (pointInSphere(testPoint, center, radius)) { + testPoint = box.getCorner() + glm::vec3(size.x, 0.0f, 0.0f); + if (pointInSphere(testPoint, center, radius)) { + testPoint = box.getCorner() + glm::vec3(0.0f, 0.0f, size.z); + if (pointInSphere(testPoint, center, radius)) { + testPoint = box.getCorner() + glm::vec3(size.x, 0.0f, size.z); + if (pointInSphere(testPoint, center, radius)) { + testPoint = box.getCorner() + glm::vec3(0.0f, size.y, 0.0f); + if (pointInSphere(testPoint, center, radius)) { + testPoint = box.getCorner() + glm::vec3(size.x, size.y, 0.0f); + if (pointInSphere(testPoint, center, radius)) { + testPoint = box.getCorner() + glm::vec3(0.0f, size.y, size.z); + if (pointInSphere(testPoint, center, radius)) { + testPoint = box.getCorner() + glm::vec3(size.x, size.y, size.z); + if (pointInSphere(testPoint, center, radius)) { + result = INSIDE; + } + } + } + } + } + } + } } } - return(result); + + return result; +} + +ViewFrustum::location ViewFrustum::pointInFrustum(const glm::vec3& point) const { + ViewFrustum::location regularResult = INSIDE; + ViewFrustum::location keyholeResult = OUTSIDE; + + // If we have a keyholeRadius, check that first, since it's cheaper + if (_keyholeRadius >= 0.0f) { + keyholeResult = pointInSphere(point, _position, _keyholeRadius); + } + if (keyholeResult == INSIDE) { + return keyholeResult; + } + + // If we're not known to be INSIDE the keyhole, then check the regular frustum + for(int i=0; i < 6; i++) { + float distance = _planes[i].distance(point); + if (distance < 0) { + return keyholeResult; // escape early will be the value from checking the keyhole + } + } + + return regularResult; } ViewFrustum::location ViewFrustum::sphereInFrustum(const glm::vec3& center, float radius) const { - ViewFrustum::location result = INSIDE; + ViewFrustum::location regularResult = INSIDE; + ViewFrustum::location keyholeResult = OUTSIDE; + + // If we have a keyholeRadius, check that first, since it's cheaper + if (_keyholeRadius >= 0.0f) { + keyholeResult = sphereInSphere(center, radius, _position, _keyholeRadius); + } + if (keyholeResult == INSIDE) { + return keyholeResult; + } + float distance; for(int i=0; i < 6; i++) { distance = _planes[i].distance(center); - if (distance < -radius) - return OUTSIDE; - else if (distance < radius) - result = INTERSECT; + if (distance < -radius) { + // This is outside the regular frustum, so just return the value from checking the keyhole + return keyholeResult; + } else if (distance < radius) { + regularResult = INTERSECT; + } } - return(result); + + return regularResult; } ViewFrustum::location ViewFrustum::boxInFrustum(const AABox& box) const { + ViewFrustum::location regularResult = INSIDE; + ViewFrustum::location keyholeResult = OUTSIDE; + + // If we have a keyholeRadius, check that first, since it's cheaper + if (_keyholeRadius >= 0.0f) { + keyholeResult = boxInSphere(box, _position, _keyholeRadius); + } + if (keyholeResult == INSIDE) { + return keyholeResult; + } - //printf("ViewFrustum::boxInFrustum() box.corner=%f,%f,%f x=%f\n", - // box.getCorner().x,box.getCorner().y,box.getCorner().z,box.getSize().x); - ViewFrustum::location result = INSIDE; for(int i=0; i < 6; i++) { - - //printf("plane[%d] -- point(%f,%f,%f) normal(%f,%f,%f) d=%f \n",i, - // _planes[i].getPoint().x, _planes[i].getPoint().y, _planes[i].getPoint().z, - // _planes[i].getNormal().x, _planes[i].getNormal().y, _planes[i].getNormal().z, - // _planes[i].getDCoefficient() - //); - glm::vec3 normal = _planes[i].getNormal(); glm::vec3 boxVertexP = box.getVertexP(normal); float planeToBoxVertexPDistance = _planes[i].distance(boxVertexP); @@ -216,19 +278,14 @@ ViewFrustum::location ViewFrustum::boxInFrustum(const AABox& box) const { glm::vec3 boxVertexN = box.getVertexN(normal); float planeToBoxVertexNDistance = _planes[i].distance(boxVertexN); - //printf("plane[%d] normal=(%f,%f,%f) bVertexP=(%f,%f,%f) planeToBoxVertexPDistance=%f boxVertexN=(%f,%f,%f) planeToBoxVertexNDistance=%f\n",i, - // normal.x,normal.y,normal.z, - // boxVertexP.x,boxVertexP.y,boxVertexP.z,planeToBoxVertexPDistance, - // boxVertexN.x,boxVertexN.y,boxVertexN.z,planeToBoxVertexNDistance - // ); - if (planeToBoxVertexPDistance < 0) { - return OUTSIDE; + // This is outside the regular frustum, so just return the value from checking the keyhole + return keyholeResult; } else if (planeToBoxVertexNDistance < 0) { - result = INTERSECT; + regularResult = INTERSECT; } } - return(result); + return regularResult; } bool testMatches(glm::quat lhs, glm::quat rhs) { diff --git a/libraries/voxels/src/ViewFrustum.h b/libraries/voxels/src/ViewFrustum.h index 1c61160566..d23f2db897 100644 --- a/libraries/voxels/src/ViewFrustum.h +++ b/libraries/voxels/src/ViewFrustum.h @@ -16,44 +16,9 @@ #include "Plane.h" #include "AABox.h" +const float DEFAULT_KEYHOLE_RADIUS = 2.0f; + class ViewFrustum { -private: - - // camera location/orientation attributes - glm::vec3 _position; - glm::quat _orientation; - - // calculated for orientation - glm::vec3 _direction; - glm::vec3 _up; - glm::vec3 _right; - - // Lens attributes - float _fieldOfView; - float _aspectRatio; - float _nearClip; - float _farClip; - glm::vec3 _eyeOffsetPosition; - glm::quat _eyeOffsetOrientation; - - // Calculated values - glm::vec3 _offsetPosition; - glm::vec3 _offsetDirection; - glm::vec3 _offsetUp; - glm::vec3 _offsetRight; - glm::vec3 _farTopLeft; - glm::vec3 _farTopRight; - glm::vec3 _farBottomLeft; - glm::vec3 _farBottomRight; - glm::vec3 _nearTopLeft; - glm::vec3 _nearTopRight; - glm::vec3 _nearBottomLeft; - glm::vec3 _nearBottomRight; - enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE }; - Plane _planes[6]; // How will this be used? - - const char* debugPlaneName (int plane) const; - public: // setters for camera attributes void setPosition (const glm::vec3& p) { _position = p; }; @@ -74,7 +39,6 @@ public: void setEyeOffsetPosition (const glm::vec3& p) { _eyeOffsetPosition = p; }; void setEyeOffsetOrientation (const glm::quat& o) { _eyeOffsetOrientation = o; }; - // getters for lens attributes float getFieldOfView() const { return _fieldOfView; }; float getAspectRatio() const { return _aspectRatio; }; @@ -98,12 +62,14 @@ public: const glm::vec3& getNearBottomLeft() const { return _nearBottomLeft; }; const glm::vec3& getNearBottomRight() const { return _nearBottomRight;}; + // get/set for keyhole attribute + void setKeyholeRadius(float keyholdRadius) { _keyholeRadius = keyholdRadius; }; + float getKeyholeRadius() const { return _keyholeRadius; }; + void calculate(); ViewFrustum(); - void dump() const; - typedef enum {OUTSIDE, INTERSECT, INSIDE} location; ViewFrustum::location pointInFrustum(const glm::vec3& point) const; @@ -120,6 +86,53 @@ public: glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const; void printDebugDetails() const; + +private: + + // Used for keyhole calculations + ViewFrustum::location pointInSphere(const glm::vec3& point, const glm::vec3& center, float radius) const; + ViewFrustum::location sphereInSphere(const glm::vec3& centerA, float radiusA, const glm::vec3& centerB, float radiusB) const; + ViewFrustum::location boxInSphere(const AABox& box, const glm::vec3& center, float radius) const; + + // camera location/orientation attributes + glm::vec3 _position; + glm::quat _orientation; + + // calculated for orientation + glm::vec3 _direction; + glm::vec3 _up; + glm::vec3 _right; + + // Lens attributes + float _fieldOfView; + float _aspectRatio; + float _nearClip; + float _farClip; + glm::vec3 _eyeOffsetPosition; + glm::quat _eyeOffsetOrientation; + + // keyhole attributes + float _keyholeRadius; + + + // Calculated values + glm::vec3 _offsetPosition; + glm::vec3 _offsetDirection; + glm::vec3 _offsetUp; + glm::vec3 _offsetRight; + glm::vec3 _farTopLeft; + glm::vec3 _farTopRight; + glm::vec3 _farBottomLeft; + glm::vec3 _farBottomRight; + glm::vec3 _nearTopLeft; + glm::vec3 _nearTopRight; + glm::vec3 _nearBottomLeft; + glm::vec3 _nearBottomRight; + enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE }; + Plane _planes[6]; // How will this be used? + + const char* debugPlaneName (int plane) const; + }; From a175ad8fdade0d135bba979e75d9d7fbca28b8a5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 7 Jun 2013 17:25:05 -0700 Subject: [PATCH 16/17] fix spacing --- libraries/voxels/src/AABox.h | 40 ++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/libraries/voxels/src/AABox.h b/libraries/voxels/src/AABox.h index 6ac9fc2f2e..7acf2d54f1 100644 --- a/libraries/voxels/src/AABox.h +++ b/libraries/voxels/src/AABox.h @@ -24,29 +24,29 @@ enum BoxFace { const int FACE_COUNT = 6; -class AABox + class AABox { public: AABox(const glm::vec3& corner, float size) : _corner(corner), _size(size, size, size) { }; - AABox(const glm::vec3& corner, float x, float y, float z) : _corner(corner), _size(x, y, z) { }; - AABox(const glm::vec3& corner, const glm::vec3& size) : _corner(corner), _size(size) { }; + AABox(const glm::vec3& corner, float x, float y, float z) : _corner(corner), _size(x, y, z) { }; + AABox(const glm::vec3& corner, const glm::vec3& size) : _corner(corner), _size(size) { }; AABox() : _corner(0,0,0), _size(0,0,0) { } ~AABox() { } - void setBox(const glm::vec3& corner, float x, float y, float z) { setBox(corner,glm::vec3(x,y,z)); }; - void setBox(const glm::vec3& corner, const glm::vec3& size); + void setBox(const glm::vec3& corner, float x, float y, float z) { setBox(corner,glm::vec3(x,y,z)); }; + void setBox(const glm::vec3& corner, const glm::vec3& size); - // for use in frustum computations - glm::vec3 getVertexP(const glm::vec3& normal) const; - glm::vec3 getVertexN(const glm::vec3& normal) const; - - void scale(float scale); - - const glm::vec3& getCorner() const { return _corner; }; - const glm::vec3& getSize() const { return _size; }; - const glm::vec3& getCenter() const { return _center; }; + // for use in frustum computations + glm::vec3 getVertexP(const glm::vec3& normal) const; + glm::vec3 getVertexN(const glm::vec3& normal) const; + + void scale(float scale); + + const glm::vec3& getCorner() const { return _corner; }; + const glm::vec3& getSize() const { return _size; }; + const glm::vec3& getCenter() const { return _center; }; bool contains(const glm::vec3& point) const; bool expandedContains(const glm::vec3& point, float expansion) const; @@ -56,16 +56,16 @@ public: bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) const; private: - + glm::vec3 getClosestPointOnFace(const glm::vec3& point, BoxFace face) const; glm::vec3 getClosestPointOnFace(const glm::vec4& origin, const glm::vec4& direction, BoxFace face) const; glm::vec4 getPlane(BoxFace face) const; - + static BoxFace getOppositeFace(BoxFace face); - - glm::vec3 _corner; - glm::vec3 _center; - glm::vec3 _size; + + glm::vec3 _corner; + glm::vec3 _center; + glm::vec3 _size; }; From b69cfd4e067fe90fe50a42ed3cb70b1fe6110bfa Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 8 Jun 2013 17:27:48 -0700 Subject: [PATCH 17/17] fixed CR spacing issue --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1e4fc5459f..3bfc5ae72c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2248,7 +2248,7 @@ void Application::renderViewFrustum(ViewFrustum& viewFrustum) { float keyholeRadius = viewFrustum.getKeyholeRadius(); if (keyholeRadius > 0.0f) { glPushMatrix(); - glColor4f(1,1,0,1); + glColor4f(1, 1, 0, 1); glTranslatef(position.x, position.y, position.z); // where we actually want it! glutWireSphere(keyholeRadius, 20, 20); glPopMatrix();