From d3b37684cd0d14948529328004b9f00fdd84d33a Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 2 Oct 2014 20:02:51 -0700 Subject: [PATCH 01/43] Add VR display auto-calibration logic --- interface/src/Application.cpp | 4 ++ interface/src/Application.h | 3 +- interface/src/devices/OculusManager.cpp | 79 +++++++++++++++++++++++++ interface/src/devices/OculusManager.h | 21 +++++++ 4 files changed, 106 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d41b50a232..da7dd5bb25 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1082,6 +1082,9 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_Equal: _myAvatar->resetSize(); break; + case Qt::Key_Escape: + OculusManager::abandonCalibration(); + break; default: event->ignore(); break; @@ -1474,6 +1477,7 @@ void Application::setEnableVRMode(bool enableVRMode) { OculusManager::disconnect(); OculusManager::connect(); } + OculusManager::recalibrate(); } resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); diff --git a/interface/src/Application.h b/interface/src/Application.h index ca26cffab8..fa0733f5e3 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -365,6 +365,8 @@ public slots: void domainSettingsReceived(const QJsonObject& domainSettingsObject); + void resetSensors(); + private slots: void timer(); void idle(); @@ -381,7 +383,6 @@ private slots: void closeMirrorView(); void restoreMirrorView(); void shrinkMirrorView(); - void resetSensors(); void parseVersionXml(); diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 65518b839c..99892e98be 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -55,6 +55,16 @@ bool OculusManager::_programInitialized = false; Camera* OculusManager::_camera = NULL; int OculusManager::_activeEyeIndex = -1; +float OculusManager::CALIBRATION_DELTA_MINIMUM_LENGTH = 0.02f; +float OculusManager::CALIBRATION_DELTA_MINIMUM_ANGLE = 5.f * RADIANS_PER_DEGREE; +float OculusManager::CALIBRATION_ZERO_MAXIMUM_LENGTH = 0.01f; +float OculusManager::CALIBRATION_ZERO_MAXIMUM_ANGLE = 0.5f * RADIANS_PER_DEGREE; +quint64 OculusManager::CALIBRATION_ZERO_HOLD_TIME = 3000000; // usec +OculusManager::CalibrationState OculusManager::_calibrationState; +glm::vec3 OculusManager::_calibrationPosition; +glm::quat OculusManager::_calibrationOrientation; +quint64 OculusManager::_calibrationStartTime; + #endif glm::vec3 OculusManager::_leftEyePosition = glm::vec3(); @@ -62,6 +72,8 @@ glm::vec3 OculusManager::_rightEyePosition = glm::vec3(); void OculusManager::connect() { #ifdef HAVE_LIBOVR + _calibrationState = UNCALIBRATED; + ovr_Initialize(); _ovrHmd = ovrHmd_Create(0); @@ -172,6 +184,67 @@ void OculusManager::disconnect() { #endif } +void OculusManager::calibrate(glm::vec3 position, glm::quat orientation) { +#ifdef HAVE_LIBOVR + switch (_calibrationState) { + + case UNCALIBRATED: + if (position != glm::vec3() && orientation != glm::quat()) { // Handle zero values at start-up. + _calibrationPosition = position; + _calibrationOrientation = orientation; + _calibrationState = WAITING_FOR_DELTA; + } + break; + + case WAITING_FOR_DELTA: + if (glm::length(position - _calibrationPosition) > CALIBRATION_DELTA_MINIMUM_LENGTH + || glm::angle(orientation * glm::inverse(_calibrationOrientation)) > CALIBRATION_DELTA_MINIMUM_ANGLE) { + _calibrationPosition = position; + _calibrationOrientation = orientation; + _calibrationState = WAITING_FOR_ZERO; + } + break; + + case WAITING_FOR_ZERO: + if (glm::length(position - _calibrationPosition) < CALIBRATION_ZERO_MAXIMUM_LENGTH + && glm::angle(orientation * glm::inverse(_calibrationOrientation)) < CALIBRATION_ZERO_MAXIMUM_ANGLE) { + _calibrationStartTime = usecTimestampNow(); + _calibrationState = WAITING_FOR_ZERO_HELD; + } else { + _calibrationPosition = position; + _calibrationOrientation = orientation; + } + break; + + case WAITING_FOR_ZERO_HELD: + if (glm::length(position - _calibrationPosition) < CALIBRATION_ZERO_MAXIMUM_LENGTH + && glm::angle(orientation * glm::inverse(_calibrationOrientation)) < CALIBRATION_ZERO_MAXIMUM_ANGLE) { + if ((usecTimestampNow() - _calibrationStartTime) > CALIBRATION_ZERO_HOLD_TIME) { + _calibrationState = CALIBRATED; + Application::getInstance()->resetSensors(); + } + } else { + _calibrationPosition = position; + _calibrationOrientation = orientation; + _calibrationState = WAITING_FOR_ZERO; + } + break; + } +#endif +} + +void OculusManager::recalibrate() { +#ifdef HAVE_LIBOVR + _calibrationState = UNCALIBRATED; +#endif +} + +void OculusManager::abandonCalibration() { +#ifdef HAVE_LIBOVR + _calibrationState = CALIBRATED; +#endif +} + #ifdef HAVE_LIBOVR void OculusManager::generateDistortionMesh() { @@ -330,6 +403,12 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p trackerPosition = glm::vec3(ovrHeadPosition.x, ovrHeadPosition.y, ovrHeadPosition.z); trackerPosition = bodyOrientation * trackerPosition; + + if (_calibrationState != CALIBRATED) { + ovrQuatf ovrHeadOrientation = ts.HeadPose.ThePose.Orientation; + orientation = glm::quat(ovrHeadOrientation.w, ovrHeadOrientation.x, ovrHeadOrientation.y, ovrHeadOrientation.z); + calibrate(trackerPosition, orientation); + } #endif //Render each eye into an fbo diff --git a/interface/src/devices/OculusManager.h b/interface/src/devices/OculusManager.h index 604580a24e..15d5c73b7b 100644 --- a/interface/src/devices/OculusManager.h +++ b/interface/src/devices/OculusManager.h @@ -30,6 +30,8 @@ public: static void connect(); static void disconnect(); static bool isConnected(); + static void recalibrate(); + static void abandonCalibration(); static void beginFrameTiming(); static void endFrameTiming(); static void configureCamera(Camera& camera, int screenWidth, int screenHeight); @@ -99,6 +101,25 @@ private: static bool _programInitialized; static Camera* _camera; static int _activeEyeIndex; + + static void calibrate(glm::vec3 position, glm::quat orientation); + enum CalibrationState { + UNCALIBRATED, + WAITING_FOR_DELTA, + WAITING_FOR_ZERO, + WAITING_FOR_ZERO_HELD, + CALIBRATED + }; + static float CALIBRATION_DELTA_MINIMUM_LENGTH; + static float CALIBRATION_DELTA_MINIMUM_ANGLE; + static float CALIBRATION_ZERO_MAXIMUM_LENGTH; + static float CALIBRATION_ZERO_MAXIMUM_ANGLE; + static quint64 CALIBRATION_ZERO_HOLD_TIME; + static CalibrationState _calibrationState; + static glm::vec3 _calibrationPosition; + static glm::quat _calibrationOrientation; + static quint64 _calibrationStartTime; + #endif static glm::vec3 _leftEyePosition; From 0a4bc2bc4883a92035c2abbf2d87b482fa1d99b2 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 3 Oct 2014 13:14:39 -0700 Subject: [PATCH 02/43] Add VR display auto-calibration user message calculations --- interface/src/devices/OculusManager.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 99892e98be..59283dbc67 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -186,6 +186,8 @@ void OculusManager::disconnect() { void OculusManager::calibrate(glm::vec3 position, glm::quat orientation) { #ifdef HAVE_LIBOVR + static QString progressMessage; + switch (_calibrationState) { case UNCALIBRATED: @@ -210,6 +212,8 @@ void OculusManager::calibrate(glm::vec3 position, glm::quat orientation) { && glm::angle(orientation * glm::inverse(_calibrationOrientation)) < CALIBRATION_ZERO_MAXIMUM_ANGLE) { _calibrationStartTime = usecTimestampNow(); _calibrationState = WAITING_FOR_ZERO_HELD; + qDebug() << "Progress box: Hold still to calibrate"; + progressMessage = ""; } else { _calibrationPosition = position; _calibrationOrientation = orientation; @@ -221,7 +225,19 @@ void OculusManager::calibrate(glm::vec3 position, glm::quat orientation) { && glm::angle(orientation * glm::inverse(_calibrationOrientation)) < CALIBRATION_ZERO_MAXIMUM_ANGLE) { if ((usecTimestampNow() - _calibrationStartTime) > CALIBRATION_ZERO_HOLD_TIME) { _calibrationState = CALIBRATED; + qDebug() << "Delete progress box"; Application::getInstance()->resetSensors(); + } else { + // 3...2...1... + quint64 quarterSeconds = (usecTimestampNow() - _calibrationStartTime) / 250000; + if (quarterSeconds + 1 > progressMessage.length()) { + if (quarterSeconds == 4 * (quarterSeconds / 4)) { + progressMessage += QString::number(CALIBRATION_ZERO_HOLD_TIME / 1000000 - quarterSeconds / 4); + } else { + progressMessage += "."; + } + qDebug() << progressMessage; + } } } else { _calibrationPosition = position; From fc24d96947bcdf65608284b88defe596c1871b53 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 4 Oct 2014 19:31:52 -0700 Subject: [PATCH 03/43] Make overlays accessible from C++ code --- interface/src/ui/overlays/Overlays.cpp | 73 ++++++++------------------ interface/src/ui/overlays/Overlays.h | 3 ++ 2 files changed, 24 insertions(+), 52 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index fe9a9edca0..922c6a0408 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -124,90 +124,59 @@ void Overlays::render3D() { unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& properties) { unsigned int thisID = 0; - bool created = false; - bool is3D = false; Overlay* thisOverlay = NULL; + bool created = true; if (type == "image") { thisOverlay = new ImageOverlay(); - thisOverlay->init(_parent); - thisOverlay->setProperties(properties); - created = true; } else if (type == "text") { thisOverlay = new TextOverlay(); - thisOverlay->init(_parent); - thisOverlay->setProperties(properties); - created = true; } else if (type == "cube") { thisOverlay = new Cube3DOverlay(); - thisOverlay->init(_parent); - thisOverlay->setProperties(properties); - created = true; - is3D = true; } else if (type == "sphere") { thisOverlay = new Sphere3DOverlay(); - thisOverlay->init(_parent); - thisOverlay->setProperties(properties); - created = true; - is3D = true; } else if (type == "circle3d") { thisOverlay = new Circle3DOverlay(); - thisOverlay->init(_parent); - thisOverlay->setProperties(properties); - created = true; - is3D = true; } else if (type == "rectangle3d") { thisOverlay = new Rectangle3DOverlay(); - thisOverlay->init(_parent); - thisOverlay->setProperties(properties); - created = true; - is3D = true; } else if (type == "line3d") { thisOverlay = new Line3DOverlay(); - thisOverlay->init(_parent); - thisOverlay->setProperties(properties); - created = true; - is3D = true; } else if (type == "localvoxels") { thisOverlay = new LocalVoxelsOverlay(); - thisOverlay->init(_parent); - thisOverlay->setProperties(properties); - created = true; - is3D = true; } else if (type == "localmodels") { thisOverlay = new LocalModelsOverlay(Application::getInstance()->getEntityClipboardRenderer()); - thisOverlay->init(_parent); - thisOverlay->setProperties(properties); - created = true; - is3D = true; } else if (type == "model") { thisOverlay = new ModelOverlay(); - thisOverlay->init(_parent); - thisOverlay->setProperties(properties); - created = true; - is3D = true; } else if (type == "billboard") { thisOverlay = new BillboardOverlay(); - thisOverlay->init(_parent); - thisOverlay->setProperties(properties); - created = true; - is3D = true; + } else { + created = false; } if (created) { - QWriteLocker lock(&_lock); - thisID = _nextOverlayID; - _nextOverlayID++; - if (is3D) { - _overlays3D[thisID] = thisOverlay; - } else { - _overlays2D[thisID] = thisOverlay; - } + thisOverlay->setProperties(properties); + thisID = addOverlay(thisOverlay); } return thisID; } +unsigned int Overlays::addOverlay(Overlay* overlay) { + overlay->init(_parent); + + QWriteLocker lock(&_lock); + unsigned int thisID = _nextOverlayID; + _nextOverlayID++; + bool is3D = typeid(*overlay) != typeid(ImageOverlay) && typeid(*overlay) != typeid(TextOverlay); + if (is3D) { + _overlays3D[thisID] = overlay; + } else { + _overlays2D[thisID] = overlay; + } + + return thisID; +} + bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) { Overlay* thisOverlay = NULL; QWriteLocker lock(&_lock); diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 6676994eed..4851b1f9dc 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -44,6 +44,9 @@ public slots: /// adds an overlay with the specific properties unsigned int addOverlay(const QString& type, const QScriptValue& properties); + /// adds an overlay that's already been created + unsigned int addOverlay(Overlay* overlay); + /// edits an overlay updating only the included properties, will return the identified OverlayID in case of /// successful edit, if the input id is for an unknown overlay this function will have no effect bool editOverlay(unsigned int id, const QScriptValue& properties); From 614f5314f20e82c1eba50735d4fbf7a345116203 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 4 Oct 2014 19:32:20 -0700 Subject: [PATCH 04/43] Add some property setters to the billboard overlay --- interface/src/ui/overlays/BillboardOverlay.cpp | 4 ++++ interface/src/ui/overlays/BillboardOverlay.h | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/interface/src/ui/overlays/BillboardOverlay.cpp b/interface/src/ui/overlays/BillboardOverlay.cpp index 4f9e7c84f6..08d2652849 100644 --- a/interface/src/ui/overlays/BillboardOverlay.cpp +++ b/interface/src/ui/overlays/BillboardOverlay.cpp @@ -150,6 +150,10 @@ void BillboardOverlay::setProperties(const QScriptValue &properties) { } } +void BillboardOverlay::setURL(const QString url) { + setBillboardURL(url); +} + void BillboardOverlay::setBillboardURL(const QUrl url) { _isLoaded = false; QNetworkReply* reply = NetworkAccessManager::getInstance().get(QNetworkRequest(url)); diff --git a/interface/src/ui/overlays/BillboardOverlay.h b/interface/src/ui/overlays/BillboardOverlay.h index a0b76869b3..85af2a3c66 100644 --- a/interface/src/ui/overlays/BillboardOverlay.h +++ b/interface/src/ui/overlays/BillboardOverlay.h @@ -24,6 +24,12 @@ public: BillboardOverlay(); virtual void render(); + + // setters + void setURL(const QString url); + void setScale(float scale) { _scale = scale; } + void setIsFacingAvatar(bool isFacingAvatar) { _isFacingAvatar = isFacingAvatar; } + virtual void setProperties(const QScriptValue& properties); void setClipFromSource(const QRect& bounds) { _fromImage = bounds; } From 817da8ca05061bd74e080154bb30327d5a35249e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 4 Oct 2014 19:33:24 -0700 Subject: [PATCH 05/43] Display a static billboard prompting user to hold still to calibrate HMD --- interface/src/devices/OculusManager.cpp | 48 ++++++++++++++++++++++--- interface/src/devices/OculusManager.h | 6 ++++ 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 59283dbc67..123b02edf2 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -58,12 +58,16 @@ int OculusManager::_activeEyeIndex = -1; float OculusManager::CALIBRATION_DELTA_MINIMUM_LENGTH = 0.02f; float OculusManager::CALIBRATION_DELTA_MINIMUM_ANGLE = 5.f * RADIANS_PER_DEGREE; float OculusManager::CALIBRATION_ZERO_MAXIMUM_LENGTH = 0.01f; -float OculusManager::CALIBRATION_ZERO_MAXIMUM_ANGLE = 0.5f * RADIANS_PER_DEGREE; +float OculusManager::CALIBRATION_ZERO_MAXIMUM_ANGLE = 2.0f * RADIANS_PER_DEGREE; quint64 OculusManager::CALIBRATION_ZERO_HOLD_TIME = 3000000; // usec +float OculusManager::CALIBRATION_MESSAGE_DISTANCE = 2.5f; OculusManager::CalibrationState OculusManager::_calibrationState; glm::vec3 OculusManager::_calibrationPosition; glm::quat OculusManager::_calibrationOrientation; quint64 OculusManager::_calibrationStartTime; +int OculusManager::_calibrationMessage = 0; +QString OculusManager::CALIBRATION_BILLBOARD_URL = "http://ctrlaltstudio.com/hifi/hold-to-calibrate.svg"; // TODO: Update with final URL +float OculusManager::CALIBRATION_BILLBOARD_SCALE = 2.f; #endif @@ -184,9 +188,20 @@ void OculusManager::disconnect() { #endif } +void OculusManager::positionCalibrationBillboard(BillboardOverlay* billboard) { + glm::quat headOrientation = Application::getInstance()->getAvatar()->getHeadOrientation(); + headOrientation.x = 0; + headOrientation.z = 0; + glm::normalize(headOrientation); + billboard->setPosition(Application::getInstance()->getAvatar()->getHeadPosition() + + headOrientation * glm::vec3(0.f, 0.f, -CALIBRATION_MESSAGE_DISTANCE)); + billboard->setRotation(headOrientation); +} + void OculusManager::calibrate(glm::vec3 position, glm::quat orientation) { #ifdef HAVE_LIBOVR static QString progressMessage; + static BillboardOverlay* billboard; switch (_calibrationState) { @@ -212,7 +227,19 @@ void OculusManager::calibrate(glm::vec3 position, glm::quat orientation) { && glm::angle(orientation * glm::inverse(_calibrationOrientation)) < CALIBRATION_ZERO_MAXIMUM_ANGLE) { _calibrationStartTime = usecTimestampNow(); _calibrationState = WAITING_FOR_ZERO_HELD; - qDebug() << "Progress box: Hold still to calibrate"; + + if (_calibrationMessage == 0) { + qDebug() << "Calibration message: Hold still to calibrate"; + + billboard = new BillboardOverlay(); + billboard->setURL(CALIBRATION_BILLBOARD_URL); + billboard->setScale(CALIBRATION_BILLBOARD_SCALE); + billboard->setIsFacingAvatar(false); + positionCalibrationBillboard(billboard); + + _calibrationMessage = Application::getInstance()->getOverlays().addOverlay(billboard); + } + progressMessage = ""; } else { _calibrationPosition = position; @@ -225,14 +252,22 @@ void OculusManager::calibrate(glm::vec3 position, glm::quat orientation) { && glm::angle(orientation * glm::inverse(_calibrationOrientation)) < CALIBRATION_ZERO_MAXIMUM_ANGLE) { if ((usecTimestampNow() - _calibrationStartTime) > CALIBRATION_ZERO_HOLD_TIME) { _calibrationState = CALIBRATED; - qDebug() << "Delete progress box"; + qDebug() << "Delete calibration message"; + Application::getInstance()->getOverlays().deleteOverlay(_calibrationMessage); + _calibrationMessage = 0; Application::getInstance()->resetSensors(); } else { - // 3...2...1... quint64 quarterSeconds = (usecTimestampNow() - _calibrationStartTime) / 250000; if (quarterSeconds + 1 > progressMessage.length()) { + // 3...2...1... if (quarterSeconds == 4 * (quarterSeconds / 4)) { - progressMessage += QString::number(CALIBRATION_ZERO_HOLD_TIME / 1000000 - quarterSeconds / 4); + quint64 wholeSeconds = CALIBRATION_ZERO_HOLD_TIME / 1000000 - quarterSeconds / 4; + + if (wholeSeconds == 2) { + positionCalibrationBillboard(billboard); + } + + progressMessage += QString::number(wholeSeconds); } else { progressMessage += "."; } @@ -258,6 +293,9 @@ void OculusManager::recalibrate() { void OculusManager::abandonCalibration() { #ifdef HAVE_LIBOVR _calibrationState = CALIBRATED; + qDebug() << "Delete calibration message"; + Application::getInstance()->getOverlays().deleteOverlay(_calibrationMessage); + _calibrationMessage = 0; #endif } diff --git a/interface/src/devices/OculusManager.h b/interface/src/devices/OculusManager.h index 15d5c73b7b..967c8b7139 100644 --- a/interface/src/devices/OculusManager.h +++ b/interface/src/devices/OculusManager.h @@ -18,6 +18,7 @@ #endif #include "renderer/ProgramObject.h" +#include "ui/overlays/BillboardOverlay.h" const float DEFAULT_OCULUS_UI_ANGULAR_SIZE = 72.0f; @@ -110,15 +111,20 @@ private: WAITING_FOR_ZERO_HELD, CALIBRATED }; + static void OculusManager::positionCalibrationBillboard(BillboardOverlay* billboard); static float CALIBRATION_DELTA_MINIMUM_LENGTH; static float CALIBRATION_DELTA_MINIMUM_ANGLE; static float CALIBRATION_ZERO_MAXIMUM_LENGTH; static float CALIBRATION_ZERO_MAXIMUM_ANGLE; static quint64 CALIBRATION_ZERO_HOLD_TIME; + static float CALIBRATION_MESSAGE_DISTANCE; static CalibrationState _calibrationState; static glm::vec3 _calibrationPosition; static glm::quat _calibrationOrientation; static quint64 _calibrationStartTime; + static int _calibrationMessage; + static QString CALIBRATION_BILLBOARD_URL; + static float CALIBRATION_BILLBOARD_SCALE; #endif From 6992b41c5c349525303703136fbba5a8f788859e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 4 Oct 2014 19:53:00 -0700 Subject: [PATCH 06/43] Fix avatar rotation erroneously initiating HMD calibration --- interface/src/devices/OculusManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 123b02edf2..cfeca9bb9a 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -456,13 +456,14 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p ovrVector3f ovrHeadPosition = ts.HeadPose.ThePose.Position; trackerPosition = glm::vec3(ovrHeadPosition.x, ovrHeadPosition.y, ovrHeadPosition.z); - trackerPosition = bodyOrientation * trackerPosition; if (_calibrationState != CALIBRATED) { ovrQuatf ovrHeadOrientation = ts.HeadPose.ThePose.Orientation; orientation = glm::quat(ovrHeadOrientation.w, ovrHeadOrientation.x, ovrHeadOrientation.y, ovrHeadOrientation.z); calibrate(trackerPosition, orientation); } + + trackerPosition = bodyOrientation * trackerPosition; #endif //Render each eye into an fbo From 32399d8620253f382e6aef88d8f94384de415014 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 4 Oct 2014 20:07:37 -0700 Subject: [PATCH 07/43] Delete calibration message if exit VR display while calibrating --- interface/src/Application.cpp | 2 ++ interface/src/devices/OculusManager.cpp | 8 +++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index da7dd5bb25..c135fd86f3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1478,6 +1478,8 @@ void Application::setEnableVRMode(bool enableVRMode) { OculusManager::connect(); } OculusManager::recalibrate(); + } else { + OculusManager::abandonCalibration(); } resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index cfeca9bb9a..6dad7006d9 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -293,9 +293,11 @@ void OculusManager::recalibrate() { void OculusManager::abandonCalibration() { #ifdef HAVE_LIBOVR _calibrationState = CALIBRATED; - qDebug() << "Delete calibration message"; - Application::getInstance()->getOverlays().deleteOverlay(_calibrationMessage); - _calibrationMessage = 0; + if (_calibrationMessage > 0) { + qDebug() << "Delete calibration message"; + Application::getInstance()->getOverlays().deleteOverlay(_calibrationMessage); + _calibrationMessage = 0; + } #endif } From ebf615fc30b9f0a01a0141d7b057f8e7618e8e90 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 6 Oct 2014 17:25:40 -0700 Subject: [PATCH 08/43] Fix header declaration --- interface/src/devices/OculusManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/devices/OculusManager.h b/interface/src/devices/OculusManager.h index 967c8b7139..e46f1673a0 100644 --- a/interface/src/devices/OculusManager.h +++ b/interface/src/devices/OculusManager.h @@ -111,7 +111,7 @@ private: WAITING_FOR_ZERO_HELD, CALIBRATED }; - static void OculusManager::positionCalibrationBillboard(BillboardOverlay* billboard); + static void positionCalibrationBillboard(BillboardOverlay* billboard); static float CALIBRATION_DELTA_MINIMUM_LENGTH; static float CALIBRATION_DELTA_MINIMUM_ANGLE; static float CALIBRATION_ZERO_MAXIMUM_LENGTH; From 05915ae134b15e0dfdd0409f4fdd73c5ad13ef10 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 8 Oct 2014 11:53:07 -0700 Subject: [PATCH 09/43] Make calibration message update its location more often --- interface/src/devices/OculusManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 6dad7006d9..8078c2666b 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -263,7 +263,7 @@ void OculusManager::calibrate(glm::vec3 position, glm::quat orientation) { if (quarterSeconds == 4 * (quarterSeconds / 4)) { quint64 wholeSeconds = CALIBRATION_ZERO_HOLD_TIME / 1000000 - quarterSeconds / 4; - if (wholeSeconds == 2) { + if (wholeSeconds == 3) { positionCalibrationBillboard(billboard); } From 7b0d00235520aa8f5a06c8cdbec4dcfb3622ac59 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 9 Oct 2014 19:51:02 -0700 Subject: [PATCH 10/43] Working on ray/voxel intersection testing. --- interface/src/MetavoxelSystem.cpp | 115 ++++++++++++++++++++++++++- interface/src/MetavoxelSystem.h | 9 ++- interface/src/ui/MetavoxelEditor.cpp | 44 ++++++++++ interface/src/ui/MetavoxelEditor.h | 28 +++++++ 4 files changed, 193 insertions(+), 3 deletions(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 10a211f61b..9732036def 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -328,6 +328,50 @@ bool MetavoxelSystem::findFirstRayHeightfieldIntersection(const glm::vec3& origi return true; } +class RayVoxelIntersectionVisitor : public RayIntersectionVisitor { +public: + + float intersectionDistance; + + RayVoxelIntersectionVisitor(const glm::vec3& origin, const glm::vec3& direction, const MetavoxelLOD& lod); + + virtual int visit(MetavoxelInfo& info, float distance); +}; + +RayVoxelIntersectionVisitor::RayVoxelIntersectionVisitor(const glm::vec3& origin, + const glm::vec3& direction, const MetavoxelLOD& lod) : + RayIntersectionVisitor(origin, direction, QVector() << + Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute(), QVector(), lod), + intersectionDistance(FLT_MAX) { +} + +int RayVoxelIntersectionVisitor::visit(MetavoxelInfo& info, float distance) { + if (!info.isLeaf) { + return _order; + } + const VoxelBuffer* buffer = static_cast( + info.inputValues.at(0).getInlineValue().data()); + if (!buffer) { + return STOP_RECURSION; + } + glm::vec3 origin = ((_origin + distance * _direction) - info.minimum) / info.size; + if (buffer->findFirstRayIntersection(origin, _direction, intersectionDistance)) { + intersectionDistance = intersectionDistance * info.size + distance; + return SHORT_CIRCUIT; + } + return STOP_RECURSION; +} + +bool MetavoxelSystem::findFirstRayVoxelIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) { + RayVoxelIntersectionVisitor visitor(origin, direction, getLOD()); + guideToAugmented(visitor); + if (visitor.intersectionDistance == FLT_MAX) { + return false; + } + distance = visitor.intersectionDistance; + return true; +} + class HeightfieldHeightVisitor : public MetavoxelVisitor { public: @@ -991,10 +1035,12 @@ void VoxelPoint::setNormal(const glm::vec3& normal) { } VoxelBuffer::VoxelBuffer(const QVector& vertices, const QVector& indices, const QVector& hermite, - const QVector& materials) : + const QHash& points, int size, const QVector& materials) : _vertices(vertices), _indices(indices), _hermite(hermite), + _points(points), + _size(size), _vertexCount(vertices.size()), _indexCount(indices.size()), _hermiteCount(hermite.size()), @@ -1002,6 +1048,68 @@ VoxelBuffer::VoxelBuffer(const QVector& vertices, const QVector _materials(materials) { } +bool VoxelBuffer::findFirstRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const { + float highest = _size - 1.0f; + glm::vec3 position = origin * highest; + glm::vec3 floors = glm::floor(position); + int max = _size - 2; + int x = qMin((int)floors.x, max), y = qMin((int)floors.y, max), z = qMin((int)floors.z, max); + float combinedDistance = 0.0f; + forever { + if (_points.contains(qRgb(x + 1, y + 1, z + 1))) { + distance = combinedDistance / highest; + return true; + } + float xDistance = FLT_MAX, yDistance = FLT_MAX, zDistance = FLT_MAX; + if (direction.x > 0.0f) { + xDistance = (x + 1.0f - position.x) / direction.x; + } else if (direction.x < 0.0f) { + xDistance = (x - position.x) / direction.x; + } + if (direction.y > 0.0f) { + yDistance = (y + 1.0f - position.y) / direction.y; + } else if (direction.y < 0.0f) { + yDistance = (y - position.y) / direction.y; + } + if (direction.z > 0.0f) { + zDistance = (z + 1.0f - position.z) / direction.z; + } else if (direction.z < 0.0f) { + zDistance = (z - position.z) / direction.z; + } + float minimumDistance = qMin(xDistance, qMin(yDistance, zDistance)); + if (minimumDistance == xDistance) { + if (direction.x > 0.0f) { + if (x++ == max) { + return false; + } + } else if (x-- == 0) { + return false; + } + } + if (minimumDistance == yDistance) { + if (direction.y > 0.0f) { + if (y++ == max) { + return false; + } + } else if (y-- == 0) { + return false; + } + } + if (minimumDistance == zDistance) { + if (direction.z > 0.0f) { + if (z++ == max) { + return false; + } + } else if (z-- == 0) { + return false; + } + } + position += direction * minimumDistance; + combinedDistance += minimumDistance; + } + return false; +} + void VoxelBuffer::render(bool cursor) { if (!_vertexBuffer.isCreated()) { _vertexBuffer.create(); @@ -1627,6 +1735,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { QVector vertices; QVector indices; QVector hermiteSegments; + QHash points; // see http://www.frankpetterson.com/publications/dualcontour/dualcontour.pdf for a description of the // dual contour algorithm for generating meshes from voxel data using Hermite-tagged edges @@ -2033,6 +2142,8 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { { (quint8)materialWeights[0], (quint8)materialWeights[1], (quint8)materialWeights[2], (quint8)materialWeights[3] } }; + points.insert(qRgb(x + 1, y + 1, z + 1), (glm::vec3(clampedX, clampedY, clampedZ) + center) / highest); + // determine whether we must "crease" by generating directional normals const float CREASE_COS_NORMAL = glm::cos(glm::radians(40.0f)); AxisIndex index(vertices.size(), vertices.size(), vertices.size()); @@ -2158,7 +2269,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { colorZ += area; } } - buffer = new VoxelBuffer(vertices, indices, hermiteSegments, + buffer = new VoxelBuffer(vertices, indices, hermiteSegments, points, size, material ? material->getMaterials() : QVector()); } BufferDataPointer pointer(buffer); diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h index 52706aab56..e256716fc0 100644 --- a/interface/src/MetavoxelSystem.h +++ b/interface/src/MetavoxelSystem.h @@ -48,6 +48,8 @@ public: bool findFirstRayHeightfieldIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance); + bool findFirstRayVoxelIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance); + Q_INVOKABLE float getHeightfieldHeight(const glm::vec3& location); Q_INVOKABLE void deleteTextures(int heightID, int colorID, int textureID); @@ -241,7 +243,10 @@ class VoxelBuffer : public BufferData { public: VoxelBuffer(const QVector& vertices, const QVector& indices, const QVector& hermite, - const QVector& materials = QVector()); + const QHash& points, int size, const QVector& materials = + QVector()); + + bool findFirstRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const; virtual void render(bool cursor = false); @@ -250,6 +255,8 @@ private: QVector _vertices; QVector _indices; QVector _hermite; + QHash _points; + int _size; int _vertexCount; int _indexCount; int _hermiteCount; diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index 45911d9626..6dfe3d77ed 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -129,6 +129,7 @@ MetavoxelEditor::MetavoxelEditor() : addTool(new EraseHeightfieldTool(this)); addTool(new VoxelMaterialBoxTool(this)); addTool(new VoxelMaterialSpannerTool(this)); + addTool(new VoxelMaterialBrushTool(this)); updateAttributes(); @@ -1525,3 +1526,46 @@ void VoxelMaterialSpannerTool::updateTexture() { void VoxelMaterialSpannerTool::textureLoaded() { _color->setColor(_texture->getAverageColor()); } + +VoxelBrushTool::VoxelBrushTool(MetavoxelEditor* editor, const QString& name) : + MetavoxelTool(editor, name, false, true) { +} + +bool VoxelBrushTool::appliesTo(const AttributePointer& attribute) const { + return attribute->inherits("VoxelColorAttribute"); +} + +void VoxelBrushTool::render() { + if (Application::getInstance()->isMouseHidden()) { + return; + } + + // find the intersection with the voxels + glm::vec3 origin = Application::getInstance()->getMouseRayOrigin(); + glm::vec3 direction = Application::getInstance()->getMouseRayDirection(); + + float distance; + if (!Application::getInstance()->getMetavoxels()->findFirstRayVoxelIntersection(origin, direction, distance)) { + return; + } + _position = origin + distance * direction; + + glColor4f(1.0f, 0.0f, 0.0f, 1.0f); + + glPushMatrix(); + glTranslatef(_position.x, _position.y, _position.z); + + Application::getInstance()->getGeometryCache()->renderSphere(0.1f, 16, 16); + + glPopMatrix(); +} + +bool VoxelBrushTool::eventFilter(QObject* watched, QEvent* event) { + return false; +} + +VoxelMaterialBrushTool::VoxelMaterialBrushTool(MetavoxelEditor* editor) : + VoxelBrushTool(editor, "Material Brush") { +} + + diff --git a/interface/src/ui/MetavoxelEditor.h b/interface/src/ui/MetavoxelEditor.h index ec92d9de28..725eac87f7 100644 --- a/interface/src/ui/MetavoxelEditor.h +++ b/interface/src/ui/MetavoxelEditor.h @@ -469,4 +469,32 @@ private: QSharedPointer _texture; }; +/// Base class for voxel brush tools. +class VoxelBrushTool : public MetavoxelTool { + Q_OBJECT + +public: + + VoxelBrushTool(MetavoxelEditor* editor, const QString& name); + + virtual bool appliesTo(const AttributePointer& attribute) const; + + virtual void render(); + + virtual bool eventFilter(QObject* watched, QEvent* event); + +protected: + + glm::vec3 _position; +}; + +/// Allows texturing parts of the voxel field. +class VoxelMaterialBrushTool : public VoxelBrushTool { + Q_OBJECT + +public: + + VoxelMaterialBrushTool(MetavoxelEditor* editor); +}; + #endif // hifi_MetavoxelEditor_h From d2c7bf4334a552319e6c0cabfc6b235c6d67c6c1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 9 Oct 2014 15:58:26 -0700 Subject: [PATCH 11/43] fix for delete of object table row --- domain-server/resources/web/js/settings.js | 27 ++++++++++++---------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/domain-server/resources/web/js/settings.js b/domain-server/resources/web/js/settings.js index 923a01a8a9..38baf223b3 100644 --- a/domain-server/resources/web/js/settings.js +++ b/domain-server/resources/web/js/settings.js @@ -474,21 +474,24 @@ function deleteTableRow(delete_glyphicon) { if (!isArray) { // this is a hash row, so we empty it but leave the hidden input blank so it is cleared when we save row.empty() - row.html(""); - } else if (table.find('.' + Settings.DATA_ROW_CLASS).length > 1) { - updateDataChangedForSiblingRows(row) - - // this isn't the last row - we can just remove it - row.remove() + row.html(""); } else { - // this is the last row, we can't remove it completely since we need to post an empty array - row.empty() + if (table.find('.' + Settings.DATA_ROW_CLASS).length) { + updateDataChangedForSiblingRows(row) - row.removeClass(Settings.DATA_ROW_CLASS).removeClass(Settings.NEW_ROW_CLASS) - row.addClass('empty-array-row') + // this isn't the last row - we can just remove it + row.remove() + } else { + // this is the last row, we can't remove it completely since we need to post an empty array + row.empty() - row.html(""); + row.removeClass(Settings.DATA_ROW_CLASS).removeClass(Settings.NEW_ROW_CLASS) + row.addClass('empty-array-row') + + row.html(""); + } } // we need to fire a change event on one of the remaining inputs so that the sidebar badge is updated From 3aca910e17a9e6694d3e4beed9bc98c3be2715f7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 10 Oct 2014 09:27:15 -0700 Subject: [PATCH 12/43] remove some extra console logs --- domain-server/resources/web/js/settings.js | 1 - 1 file changed, 1 deletion(-) diff --git a/domain-server/resources/web/js/settings.js b/domain-server/resources/web/js/settings.js index 38baf223b3..9d586c8436 100644 --- a/domain-server/resources/web/js/settings.js +++ b/domain-server/resources/web/js/settings.js @@ -152,7 +152,6 @@ $(document).ready(function(){ }) $('#settings-form').on('change', 'select', function(){ - console.log("Changed" + $(this)) $("input[name='" + $(this).attr('data-hidden-input') + "']").val($(this).val()).change() }) From db881c0dc8368ac15f428d4b5646b351c205cc56 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 10 Oct 2014 10:32:18 -0700 Subject: [PATCH 13/43] add boundBox gettable property to EntityItemProperties --- .../entities/src/EntityItemProperties.cpp | 27 +++++++++++++++++++ libraries/entities/src/EntityItemProperties.h | 1 + 2 files changed, 28 insertions(+) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 1080a866f5..2690bcd45b 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -174,6 +174,16 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons sittingPoints.setProperty("length", _sittingPoints.size()); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(sittingPoints, sittingPoints); // gettable, but not settable + AABox aaBox = getAABoxInMeters(); + QScriptValue boundingBox = engine->newObject(); + QScriptValue bottomRightNear = vec3toScriptValue(engine, aaBox.getCorner()); + QScriptValue topFarLeft = vec3toScriptValue(engine, aaBox.calcTopFarLeft()); + QScriptValue center = vec3toScriptValue(engine, aaBox.calcCenter()); + boundingBox.setProperty("brn", bottomRightNear); + boundingBox.setProperty("tfl", topFarLeft); + boundingBox.setProperty("center", center); + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(boundingBox, boundingBox); // gettable, but not settable + return properties; } @@ -643,3 +653,20 @@ AACube EntityItemProperties::getMaximumAACubeInMeters() const { return AACube(minimumCorner, diameter); } + +// The minimum bounding box for the entity. +AABox EntityItemProperties::getAABoxInMeters() const { + + // _position represents the position of the registration point. + glm::vec3 registrationRemainder = glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint; + + glm::vec3 unrotatedMinRelativeToEntity = glm::vec3(0.0f, 0.0f, 0.0f) - (_dimensions * _registrationPoint); + glm::vec3 unrotatedMaxRelativeToEntity = _dimensions * registrationRemainder; + Extents unrotatedExtentsRelativeToRegistrationPoint = { unrotatedMinRelativeToEntity, unrotatedMaxRelativeToEntity }; + Extents rotatedExtentsRelativeToRegistrationPoint = unrotatedExtentsRelativeToRegistrationPoint.getRotated(getRotation()); + + // shift the extents to be relative to the position/registration point + rotatedExtentsRelativeToRegistrationPoint.shiftBy(_position); + + return AABox(rotatedExtentsRelativeToRegistrationPoint); +} diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 3c77b63ab6..6e1594fb9b 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -101,6 +101,7 @@ public: AACube getMaximumAACubeInTreeUnits() const; AACube getMaximumAACubeInMeters() const; + AABox getAABoxInMeters() const; void debugDump() const; From ca66319aa219ab64b6fee51336ad51a15fd08148 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 10 Oct 2014 10:37:32 -0700 Subject: [PATCH 14/43] draw selection handles for bounding box correctly when rotated --- examples/libraries/entitySelectionTool.js | 144 +++++++++++----------- 1 file changed, 74 insertions(+), 70 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 0f68ef4442..b00876c969 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -454,22 +454,28 @@ SelectionDisplay = (function () { var rotateHandleOffset = 0.05; var grabberMoveUpOffset = 0.1; - var left = properties.position.x - halfDimensions.x; - var right = properties.position.x + halfDimensions.x; - var bottom = properties.position.y - halfDimensions.y; - var top = properties.position.y + halfDimensions.y; - var near = properties.position.z - halfDimensions.z; - var far = properties.position.z + halfDimensions.z; - var center = { x: properties.position.x, y: properties.position.y, z: properties.position.z }; + var top, far, left, bottom, near, right, boundsCenter, objectCenter, BLN, BRN, BLF, TLN, TRN, TLF, TRF; - var BLN = { x: left, y: bottom, z: near }; - var BRN = { x: right, y: bottom, z: near }; - var BLF = { x: left, y: bottom, z: far }; - var BRF = { x: right, y: bottom, z: far }; - var TLN = { x: left, y: top, z: near }; - var TRN = { x: right, y: top, z: near }; - var TLF = { x: left, y: top, z: far }; - var TRF = { x: right, y: top, z: far }; + objectCenter = { x: properties.position.x, y: properties.position.y, z: properties.position.z }; + + top = properties.boundingBox.tfl.y; + far = properties.boundingBox.tfl.z; + left = properties.boundingBox.tfl.x; + + bottom = properties.boundingBox.brn.y; + right = properties.boundingBox.brn.x; + near = properties.boundingBox.brn.z; + + boundsCenter = { x: properties.boundingBox.center.x, y: properties.boundingBox.center.y, z: properties.boundingBox.center.z }; + + BLN = { x: left, y: bottom, z: near }; + BRN = { x: right, y: bottom, z: near }; + BLF = { x: left, y: bottom, z: far }; + BRF = { x: right, y: bottom, z: far }; + TLN = { x: left, y: top, z: near }; + TRN = { x: right, y: top, z: near }; + TLF = { x: left, y: top, z: far }; + TRF = { x: right, y: top, z: far }; var yawCorner; var pitchCorner; @@ -488,9 +494,10 @@ SelectionDisplay = (function () { ------------------------------*/ - if (MyAvatar.position.x > center.x) { + if (MyAvatar.position.x > objectCenter.x) { // must be BRF or BRN - if (MyAvatar.position.z < center.z) { + if (MyAvatar.position.z < objectCenter.z) { + yawHandleRotation = Quat.fromVec3Degrees({ x: 270, y: 90, z: 0 }); pitchHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 90, z: 0 }); rollHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 0 }); @@ -499,21 +506,21 @@ SelectionDisplay = (function () { pitchNormal = { x: 1, y: 0, z: 0 }; rollNormal = { x: 0, y: 0, z: 1 }; - yawCorner = { x: right + rotateHandleOffset, + yawCorner = { x: left + rotateHandleOffset, y: bottom - rotateHandleOffset, z: near - rotateHandleOffset }; - pitchCorner = { x: left - rotateHandleOffset, + pitchCorner = { x: right - rotateHandleOffset, y: top + rotateHandleOffset, z: near - rotateHandleOffset}; - rollCorner = { x: right + rotateHandleOffset, + rollCorner = { x: left + rotateHandleOffset, y: top + rotateHandleOffset, z: far + rotateHandleOffset }; - yawCenter = { x: center.x, y: bottom, z: center.z }; - pitchCenter = { x: left, y: center.y, z: center.z}; - rollCenter = { x: center.x, y: center.y, z: far }; + yawCenter = { x: boundsCenter.x, y: bottom, z: boundsCenter.z }; + pitchCenter = { x: right, y: boundsCenter.y, z: boundsCenter.z}; + rollCenter = { x: boundsCenter.x, y: boundsCenter.y, z: far }; Overlays.editOverlay(pitchHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-south.png" }); @@ -521,6 +528,7 @@ SelectionDisplay = (function () { } else { + yawHandleRotation = Quat.fromVec3Degrees({ x: 270, y: 0, z: 0 }); pitchHandleRotation = Quat.fromVec3Degrees({ x: 180, y: 270, z: 0 }); rollHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 90 }); @@ -530,29 +538,31 @@ SelectionDisplay = (function () { rollNormal = { x: 0, y: 0, z: 1 }; - yawCorner = { x: right + rotateHandleOffset, + yawCorner = { x: left + rotateHandleOffset, y: bottom - rotateHandleOffset, z: far + rotateHandleOffset }; - pitchCorner = { x: left - rotateHandleOffset, + pitchCorner = { x: right - rotateHandleOffset, y: top + rotateHandleOffset, z: far + rotateHandleOffset }; - rollCorner = { x: right + rotateHandleOffset, + rollCorner = { x: left + rotateHandleOffset, y: top + rotateHandleOffset, z: near - rotateHandleOffset}; - yawCenter = { x: center.x, y: bottom, z: center.z }; - pitchCenter = { x: left, y: center.y, z: center.z }; - rollCenter = { x: center.x, y: center.y, z: near}; + yawCenter = { x: boundsCenter.x, y: bottom, z: boundsCenter.z }; + pitchCenter = { x: right, y: boundsCenter.y, z: boundsCenter.z }; + rollCenter = { x: boundsCenter.x, y: boundsCenter.y, z: near}; Overlays.editOverlay(pitchHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png" }); Overlays.editOverlay(rollHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png" }); } } else { + // must be BLF or BLN - if (MyAvatar.position.z < center.z) { + if (MyAvatar.position.z < objectCenter.z) { + yawHandleRotation = Quat.fromVec3Degrees({ x: 270, y: 180, z: 0 }); pitchHandleRotation = Quat.fromVec3Degrees({ x: 90, y: 0, z: 90 }); rollHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 180 }); @@ -561,26 +571,27 @@ SelectionDisplay = (function () { pitchNormal = { x: 1, y: 0, z: 0 }; rollNormal = { x: 0, y: 0, z: 1 }; - yawCorner = { x: left - rotateHandleOffset, + yawCorner = { x: right - rotateHandleOffset, y: bottom - rotateHandleOffset, z: near - rotateHandleOffset }; - pitchCorner = { x: right + rotateHandleOffset, + pitchCorner = { x: left + rotateHandleOffset, y: top + rotateHandleOffset, z: near - rotateHandleOffset }; - rollCorner = { x: left - rotateHandleOffset, + rollCorner = { x: right - rotateHandleOffset, y: top + rotateHandleOffset, z: far + rotateHandleOffset}; - yawCenter = { x: center.x, y: bottom, z: center.z }; - pitchCenter = { x: right, y: center.y, z: center.z }; - rollCenter = { x: center.x, y: center.y, z: far}; + yawCenter = { x: boundsCenter.x, y: bottom, z: boundsCenter.z }; + pitchCenter = { x: left, y: boundsCenter.y, z: boundsCenter.z }; + rollCenter = { x: boundsCenter.x, y: boundsCenter.y, z: far}; Overlays.editOverlay(pitchHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png" }); Overlays.editOverlay(rollHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png" }); } else { + yawHandleRotation = Quat.fromVec3Degrees({ x: 270, y: 270, z: 0 }); rollHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 180 }); pitchHandleRotation = Quat.fromVec3Degrees({ x: 180, y: 270, z: 0 }); @@ -589,21 +600,21 @@ SelectionDisplay = (function () { rollNormal = { x: 0, y: 0, z: 1 }; pitchNormal = { x: 1, y: 0, z: 0 }; - yawCorner = { x: left - rotateHandleOffset, + yawCorner = { x: right - rotateHandleOffset, y: bottom - rotateHandleOffset, z: far + rotateHandleOffset }; - rollCorner = { x: left - rotateHandleOffset, + rollCorner = { x: right - rotateHandleOffset, y: top + rotateHandleOffset, z: near - rotateHandleOffset }; - pitchCorner = { x: right + rotateHandleOffset, + pitchCorner = { x: left + rotateHandleOffset, y: top + rotateHandleOffset, z: far + rotateHandleOffset}; - yawCenter = { x: center.x, y: bottom, z: center.z }; - rollCenter = { x: center.x, y: center.y, z: near }; - pitchCenter = { x: right, y: center.y, z: center.z}; + yawCenter = { x: boundsCenter.x, y: bottom, z: boundsCenter.z }; + rollCenter = { x: boundsCenter.x, y: boundsCenter.y, z: near }; + pitchCenter = { x: left, y: boundsCenter.y, z: boundsCenter.z}; Overlays.editOverlay(pitchHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png" }); Overlays.editOverlay(rollHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png" }); @@ -611,7 +622,6 @@ SelectionDisplay = (function () { } } - var rotateHandlesVisible = true; var translateHandlesVisible = true; var stretchHandlesVisible = true; @@ -632,17 +642,11 @@ SelectionDisplay = (function () { Overlays.editOverlay(highlightBox, { visible: false }); - print("selectionBoxVisible:" + selectionBoxVisible); - Overlays.editOverlay(selectionBox, - { - visible: selectionBoxVisible, - position: center, - dimensions: properties.dimensions, - rotation: properties.rotation, - }); + Overlays.editOverlay(selectionBox, { visible: selectionBoxVisible, position: objectCenter, dimensions: properties.dimensions, + rotation: properties.rotation,}); - Overlays.editOverlay(grabberMoveUp, { visible: translateHandlesVisible, position: { x: center.x, y: top + grabberMoveUpOffset, z: center.z } }); + Overlays.editOverlay(grabberMoveUp, { visible: translateHandlesVisible, position: { x: boundsCenter.x, y: top + grabberMoveUpOffset, z: boundsCenter.z } }); Overlays.editOverlay(grabberLBN, { visible: stretchHandlesVisible, position: { x: left, y: bottom, z: near } }); Overlays.editOverlay(grabberRBN, { visible: stretchHandlesVisible, position: { x: right, y: bottom, z: near } }); @@ -654,25 +658,25 @@ SelectionDisplay = (function () { Overlays.editOverlay(grabberRTF, { visible: stretchHandlesVisible, position: { x: right, y: top, z: far } }); - Overlays.editOverlay(grabberTOP, { visible: stretchHandlesVisible, position: { x: center.x, y: top, z: center.z } }); - Overlays.editOverlay(grabberBOTTOM, { visible: stretchHandlesVisible, position: { x: center.x, y: bottom, z: center.z } }); - Overlays.editOverlay(grabberLEFT, { visible: stretchHandlesVisible, position: { x: left, y: center.y, z: center.z } }); - Overlays.editOverlay(grabberRIGHT, { visible: stretchHandlesVisible, position: { x: right, y: center.y, z: center.z } }); - Overlays.editOverlay(grabberNEAR, { visible: stretchHandlesVisible, position: { x: center.x, y: center.y, z: near } }); - Overlays.editOverlay(grabberFAR, { visible: stretchHandlesVisible, position: { x: center.x, y: center.y, z: far } }); + Overlays.editOverlay(grabberTOP, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: top, z: boundsCenter.z } }); + Overlays.editOverlay(grabberBOTTOM, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: bottom, z: boundsCenter.z } }); + Overlays.editOverlay(grabberLEFT, { visible: stretchHandlesVisible, position: { x: left, y: boundsCenter.y, z: boundsCenter.z } }); + Overlays.editOverlay(grabberRIGHT, { visible: stretchHandlesVisible, position: { x: right, y: boundsCenter.y, z: boundsCenter.z } }); + Overlays.editOverlay(grabberNEAR, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: boundsCenter.y, z: near } }); + Overlays.editOverlay(grabberFAR, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: boundsCenter.y, z: far } }); - Overlays.editOverlay(grabberEdgeTR, { visible: stretchHandlesVisible, position: { x: right, y: top, z: center.z } }); - Overlays.editOverlay(grabberEdgeTL, { visible: stretchHandlesVisible, position: { x: left, y: top, z: center.z } }); - Overlays.editOverlay(grabberEdgeTF, { visible: stretchHandlesVisible, position: { x: center.x, y: top, z: far } }); - Overlays.editOverlay(grabberEdgeTN, { visible: stretchHandlesVisible, position: { x: center.x, y: top, z: near } }); - Overlays.editOverlay(grabberEdgeBR, { visible: stretchHandlesVisible, position: { x: right, y: bottom, z: center.z } }); - Overlays.editOverlay(grabberEdgeBL, { visible: stretchHandlesVisible, position: { x: left, y: bottom, z: center.z } }); - Overlays.editOverlay(grabberEdgeBF, { visible: stretchHandlesVisible, position: { x: center.x, y: bottom, z: far } }); - Overlays.editOverlay(grabberEdgeBN, { visible: stretchHandlesVisible, position: { x: center.x, y: bottom, z: near } }); - Overlays.editOverlay(grabberEdgeNR, { visible: stretchHandlesVisible, position: { x: right, y: center.y, z: near } }); - Overlays.editOverlay(grabberEdgeNL, { visible: stretchHandlesVisible, position: { x: left, y: center.y, z: near } }); - Overlays.editOverlay(grabberEdgeFR, { visible: stretchHandlesVisible, position: { x: right, y: center.y, z: far } }); - Overlays.editOverlay(grabberEdgeFL, { visible: stretchHandlesVisible, position: { x: left, y: center.y, z: far } }); + Overlays.editOverlay(grabberEdgeTR, { visible: stretchHandlesVisible, position: { x: right, y: top, z: boundsCenter.z } }); + Overlays.editOverlay(grabberEdgeTL, { visible: stretchHandlesVisible, position: { x: left, y: top, z: boundsCenter.z } }); + Overlays.editOverlay(grabberEdgeTF, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: top, z: far } }); + Overlays.editOverlay(grabberEdgeTN, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: top, z: near } }); + Overlays.editOverlay(grabberEdgeBR, { visible: stretchHandlesVisible, position: { x: right, y: bottom, z: boundsCenter.z } }); + Overlays.editOverlay(grabberEdgeBL, { visible: stretchHandlesVisible, position: { x: left, y: bottom, z: boundsCenter.z } }); + Overlays.editOverlay(grabberEdgeBF, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: bottom, z: far } }); + Overlays.editOverlay(grabberEdgeBN, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: bottom, z: near } }); + Overlays.editOverlay(grabberEdgeNR, { visible: stretchHandlesVisible, position: { x: right, y: boundsCenter.y, z: near } }); + Overlays.editOverlay(grabberEdgeNL, { visible: stretchHandlesVisible, position: { x: left, y: boundsCenter.y, z: near } }); + Overlays.editOverlay(grabberEdgeFR, { visible: stretchHandlesVisible, position: { x: right, y: boundsCenter.y, z: far } }); + Overlays.editOverlay(grabberEdgeFL, { visible: stretchHandlesVisible, position: { x: left, y: boundsCenter.y, z: far } }); Overlays.editOverlay(baseOfEntityProjectionOverlay, From 64d9a96a2ba53c8231769917bc5459bba57d825b Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 10 Oct 2014 10:42:13 -0700 Subject: [PATCH 15/43] Update SVG file location --- interface/src/devices/OculusManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 8078c2666b..010258a56d 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -66,7 +66,7 @@ glm::vec3 OculusManager::_calibrationPosition; glm::quat OculusManager::_calibrationOrientation; quint64 OculusManager::_calibrationStartTime; int OculusManager::_calibrationMessage = 0; -QString OculusManager::CALIBRATION_BILLBOARD_URL = "http://ctrlaltstudio.com/hifi/hold-to-calibrate.svg"; // TODO: Update with final URL +QString OculusManager::CALIBRATION_BILLBOARD_URL = "http://hifi-public.s3.amazonaws.com/images/hold-to-calibrate.svg"; float OculusManager::CALIBRATION_BILLBOARD_SCALE = 2.f; #endif From aa37ba5dfdfeb0cecd17bc349dda44403f9e5c21 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 10 Oct 2014 10:57:17 -0700 Subject: [PATCH 16/43] Use const parameters --- interface/src/devices/OculusManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/devices/OculusManager.h b/interface/src/devices/OculusManager.h index e46f1673a0..dfe4a212b6 100644 --- a/interface/src/devices/OculusManager.h +++ b/interface/src/devices/OculusManager.h @@ -103,7 +103,7 @@ private: static Camera* _camera; static int _activeEyeIndex; - static void calibrate(glm::vec3 position, glm::quat orientation); + static void calibrate(const glm::vec3 position, const glm::quat orientation); enum CalibrationState { UNCALIBRATED, WAITING_FOR_DELTA, From 0a5fdee1f2d4e97c8ff5a8d730ea50c4eb49d9a5 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 10 Oct 2014 11:00:41 -0700 Subject: [PATCH 17/43] Use NULL rather than 0 for "no overlay" --- interface/src/devices/OculusManager.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 010258a56d..158ace0a37 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -65,7 +65,7 @@ OculusManager::CalibrationState OculusManager::_calibrationState; glm::vec3 OculusManager::_calibrationPosition; glm::quat OculusManager::_calibrationOrientation; quint64 OculusManager::_calibrationStartTime; -int OculusManager::_calibrationMessage = 0; +int OculusManager::_calibrationMessage = NULL; QString OculusManager::CALIBRATION_BILLBOARD_URL = "http://hifi-public.s3.amazonaws.com/images/hold-to-calibrate.svg"; float OculusManager::CALIBRATION_BILLBOARD_SCALE = 2.f; @@ -228,7 +228,7 @@ void OculusManager::calibrate(glm::vec3 position, glm::quat orientation) { _calibrationStartTime = usecTimestampNow(); _calibrationState = WAITING_FOR_ZERO_HELD; - if (_calibrationMessage == 0) { + if (!_calibrationMessage) { qDebug() << "Calibration message: Hold still to calibrate"; billboard = new BillboardOverlay(); @@ -254,7 +254,7 @@ void OculusManager::calibrate(glm::vec3 position, glm::quat orientation) { _calibrationState = CALIBRATED; qDebug() << "Delete calibration message"; Application::getInstance()->getOverlays().deleteOverlay(_calibrationMessage); - _calibrationMessage = 0; + _calibrationMessage = NULL; Application::getInstance()->resetSensors(); } else { quint64 quarterSeconds = (usecTimestampNow() - _calibrationStartTime) / 250000; @@ -293,10 +293,10 @@ void OculusManager::recalibrate() { void OculusManager::abandonCalibration() { #ifdef HAVE_LIBOVR _calibrationState = CALIBRATED; - if (_calibrationMessage > 0) { + if (_calibrationMessage) { qDebug() << "Delete calibration message"; Application::getInstance()->getOverlays().deleteOverlay(_calibrationMessage); - _calibrationMessage = 0; + _calibrationMessage = NULL; } #endif } From b0f4bc0d1ccbbb2c092dd35c721ea9740eb9f0a7 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 10 Oct 2014 11:08:15 -0700 Subject: [PATCH 18/43] Tidy up log messages --- interface/src/devices/OculusManager.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 158ace0a37..7ddd83458f 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -229,7 +229,7 @@ void OculusManager::calibrate(glm::vec3 position, glm::quat orientation) { _calibrationState = WAITING_FOR_ZERO_HELD; if (!_calibrationMessage) { - qDebug() << "Calibration message: Hold still to calibrate"; + qDebug() << "Hold still to calibrate HMD"; billboard = new BillboardOverlay(); billboard->setURL(CALIBRATION_BILLBOARD_URL); @@ -252,7 +252,7 @@ void OculusManager::calibrate(glm::vec3 position, glm::quat orientation) { && glm::angle(orientation * glm::inverse(_calibrationOrientation)) < CALIBRATION_ZERO_MAXIMUM_ANGLE) { if ((usecTimestampNow() - _calibrationStartTime) > CALIBRATION_ZERO_HOLD_TIME) { _calibrationState = CALIBRATED; - qDebug() << "Delete calibration message"; + qDebug() << "HMD calibrated"; Application::getInstance()->getOverlays().deleteOverlay(_calibrationMessage); _calibrationMessage = NULL; Application::getInstance()->resetSensors(); @@ -271,7 +271,7 @@ void OculusManager::calibrate(glm::vec3 position, glm::quat orientation) { } else { progressMessage += "."; } - qDebug() << progressMessage; + //qDebug() << progressMessage; // Progress message ready for 3D text overlays. } } } else { @@ -294,7 +294,7 @@ void OculusManager::abandonCalibration() { #ifdef HAVE_LIBOVR _calibrationState = CALIBRATED; if (_calibrationMessage) { - qDebug() << "Delete calibration message"; + qDebug() << "Abandoned HMD calibration"; Application::getInstance()->getOverlays().deleteOverlay(_calibrationMessage); _calibrationMessage = NULL; } From 357d49d442381cdbcf2280d3f0242529230c9a0a Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 10 Oct 2014 11:36:47 -0700 Subject: [PATCH 19/43] Fix building without Oculus library --- interface/src/devices/OculusManager.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 7ddd83458f..53715aabe9 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -188,6 +188,7 @@ void OculusManager::disconnect() { #endif } +#ifdef HAVE_LIBOVR void OculusManager::positionCalibrationBillboard(BillboardOverlay* billboard) { glm::quat headOrientation = Application::getInstance()->getAvatar()->getHeadOrientation(); headOrientation.x = 0; @@ -197,9 +198,10 @@ void OculusManager::positionCalibrationBillboard(BillboardOverlay* billboard) { + headOrientation * glm::vec3(0.f, 0.f, -CALIBRATION_MESSAGE_DISTANCE)); billboard->setRotation(headOrientation); } +#endif -void OculusManager::calibrate(glm::vec3 position, glm::quat orientation) { #ifdef HAVE_LIBOVR +void OculusManager::calibrate(glm::vec3 position, glm::quat orientation) { static QString progressMessage; static BillboardOverlay* billboard; @@ -281,8 +283,8 @@ void OculusManager::calibrate(glm::vec3 position, glm::quat orientation) { } break; } -#endif } +#endif void OculusManager::recalibrate() { #ifdef HAVE_LIBOVR From edf8cb671d13b510ff939d479d4a8ceb2aa8d45a Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 3 Oct 2014 09:37:56 -0700 Subject: [PATCH 20/43] Add "reset sensors" menu item corresponding to the apostrophe key --- interface/src/Menu.cpp | 14 ++++++++++---- interface/src/Menu.h | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 77009da18b..08fc5067fb 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -246,10 +246,16 @@ Menu::Menu() : #endif addActionToQMenuAndActionHash(toolsMenu, - MenuOption::Console, - Qt::CTRL | Qt::ALT | Qt::Key_J, - this, - SLOT(toggleConsole())); + MenuOption::Console, + Qt::CTRL | Qt::ALT | Qt::Key_J, + this, + SLOT(toggleConsole())); + + addActionToQMenuAndActionHash(toolsMenu, + MenuOption::ResetSensors, + Qt::Key_Apostrophe, + appInstance, + SLOT(resetSensors())); QMenu* avatarMenu = addMenu("Avatar"); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 67a4163c67..8fcce3dbf3 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -442,6 +442,7 @@ namespace MenuOption { const QString RenderLookAtVectors = "Show Look-at Vectors"; const QString RenderSkeletonCollisionShapes = "Show Skeleton Collision Shapes"; const QString ResetAvatarSize = "Reset Avatar Size"; + const QString ResetSensors = "Reset Sensors"; const QString RunningScripts = "Running Scripts"; const QString RunTimingTests = "Run Timing Tests"; const QString ScriptEditor = "Script Editor..."; From df6f4d4c95be5ab069f253cd4813baf383732e21 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 10 Oct 2014 14:17:52 -0700 Subject: [PATCH 21/43] remove cara face tracking, cleanup warnings --- interface/src/Application.cpp | 17 +- interface/src/Application.h | 4 - interface/src/devices/CaraFaceTracker.cpp | 455 ------------------ interface/src/devices/CaraFaceTracker.h | 124 ----- interface/src/devices/OculusManager.cpp | 3 + interface/src/gpu/Resource.cpp | 8 +- .../src/ui/overlays/BillboardOverlay.cpp | 11 +- 7 files changed, 14 insertions(+), 608 deletions(-) delete mode 100644 interface/src/devices/CaraFaceTracker.cpp delete mode 100644 interface/src/devices/CaraFaceTracker.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0c4cc71190..d3bed0c3ea 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1551,10 +1551,9 @@ glm::vec3 Application::getMouseVoxelWorldCoordinates(const VoxelDetail& mouseVox FaceTracker* Application::getActiveFaceTracker() { return (_dde.isActive() ? static_cast(&_dde) : - (_cara.isActive() ? static_cast(&_cara) : (_faceshift.isActive() ? static_cast(&_faceshift) : (_faceplus.isActive() ? static_cast(&_faceplus) : - (_visage.isActive() ? static_cast(&_visage) : NULL))))); + (_visage.isActive() ? static_cast(&_visage) : NULL)))); } struct SendVoxelsOperationArgs { @@ -2013,19 +2012,6 @@ void Application::updateDDE() { _dde.update(); } -void Application::updateCara() { - bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); - PerformanceWarning warn(showWarnings, "Application::updateCara()"); - - // Update Cara - _cara.update(); - - // Copy angular velocity if measured by cara, to the head - if (_cara.isActive()) { - _myAvatar->getHead()->setAngularVelocity(_cara.getHeadAngularVelocity()); - } -} - void Application::updateMyAvatarLookAtPosition() { PerformanceTimer perfTimer("lookAt"); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); @@ -2125,7 +2111,6 @@ void Application::updateMetavoxels(float deltaTime) { } void Application::cameraMenuChanged() { - float modeShiftPeriod = (_myCamera.getMode() == CAMERA_MODE_MIRROR) ? 0.0f : 1.0f; if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { if (_myCamera.getMode() != CAMERA_MODE_MIRROR) { _myCamera.setMode(CAMERA_MODE_MIRROR); diff --git a/interface/src/Application.h b/interface/src/Application.h index 7277c87b2e..ce9ed0c1a6 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -63,7 +63,6 @@ #include "devices/PrioVR.h" #include "devices/SixenseManager.h" #include "devices/Visage.h" -#include "devices/CaraFaceTracker.h" #include "devices/DdeFaceTracker.h" #include "entities/EntityTreeRenderer.h" #include "particles/ParticleTreeRenderer.h" @@ -219,7 +218,6 @@ public: Faceshift* getFaceshift() { return &_faceshift; } Visage* getVisage() { return &_visage; } DdeFaceTracker* getDDE() { return &_dde; } - CaraFaceTracker* getCara() { return &_cara; } FaceTracker* getActiveFaceTracker(); PrioVR* getPrioVR() { return &_prioVR; } BandwidthMeter* getBandwidthMeter() { return &_bandwidthMeter; } @@ -408,7 +406,6 @@ private: void updateFaceshift(); void updateVisage(); void updateDDE(); - void updateCara(); void updateMyAvatarLookAtPosition(); void updateThreads(float deltaTime); void updateMetavoxels(float deltaTime); @@ -509,7 +506,6 @@ private: Faceplus _faceplus; Faceshift _faceshift; Visage _visage; - CaraFaceTracker _cara; DdeFaceTracker _dde; PrioVR _prioVR; diff --git a/interface/src/devices/CaraFaceTracker.cpp b/interface/src/devices/CaraFaceTracker.cpp deleted file mode 100644 index bc2c4bb2d1..0000000000 --- a/interface/src/devices/CaraFaceTracker.cpp +++ /dev/null @@ -1,455 +0,0 @@ -// -// CaraFaceTracker.cpp -// interface/src/devices -// -// Created by Li Zuwei on 7/22/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "CaraFaceTracker.h" -#include - -//qt -#include -#include -#include -#include - -#define PI M_PI -#define RADTODEG(x) ( (x) * 180.0 / PI ) -#define DEGTORAD(x) ( (x) * PI / 180.0 ) - -static const QHostAddress CARA_FEATURE_POINT_SERVER_ADDR("127.0.0.1"); -static const quint16 CARA_FEATURE_POINT_SERVER_PORT = 36555; -static QString sampleJson = "[{\"id\":1, \ - \"face\":{\"x\":248,\"y\":64,\"width\":278,\"height\":341}, \ - \"pose\":{\"roll\":2.62934,\"pitch\":-12.2318,\"yaw\":0.936743}, \ - \"feature_points\":[314,194,326,187,340,187,354,189,367,193,409,190,421,187,435,184,448,183,459,188, \ - 388,207,389,223,390,240,391,257,377,266,384,267,392,268,399,266,407,264,331,209, \ - 341,204,354,204,364,209,353,214,341,214,410,208,420,201,433,200,443,205,434,211, \ - 421,211,362,294,372,290,383,287,393,289,404,286,415,289,426,291,418,300,407,306, \ - 394,308,382,307,371,302,383,295,394,295,404,294,404,295,393,297,383,296], \ - \"classifiers\":{\"emotion\":{\"smi\":-0.368829,\"sur\":-1.33334,\"neg\":0.00235828,\"att\":1},\"blink\":1}}]"; - -static const glm::vec3 DEFAULT_HEAD_ORIGIN(0.0f, 0.0f, 0.0f); -static const float TRANSLATION_SCALE = 1.0f; -static const int NUM_BLENDSHAPE_COEFF = 30; -static const int NUM_SMOOTHING_SAMPLES = 3; - -struct CaraPerson { - struct CaraPose { - float roll, pitch, yaw; - CaraPose() : - roll(0.0f), - pitch(0.0f), - yaw(0.0f) - { - } - }; - - struct CaraEmotion { - float smile, surprise, negative, attention; - CaraEmotion(): - smile(0.0f), - surprise(0.0f), - negative(0.0f), - attention(0.0f) - { - } - }; - - enum CaraBlink { - BLINK_NOT_AVAILABLE, - NO_BLINK, - BLINK - }; - - CaraPerson() : - id(-1), - blink(BLINK_NOT_AVAILABLE) - { - } - - int id; - CaraPose pose; - CaraEmotion emotion; - CaraBlink blink; - - QString toString() { - QString s = QString("id: %1, roll: %2, pitch: %3, yaw: %4, smi: %5, sur: %6, neg: %7, att: %8, blink: %9"). - arg(id). - arg(pose.roll). - arg(pose.pitch). - arg(pose.yaw). - arg(emotion.smile). - arg(emotion.surprise). - arg(emotion.negative). - arg(emotion.attention). - arg(blink); - return s; - } -}; - -class CaraPacketDecoder { -public: - static CaraPerson extractOne(const QByteArray& buffer, QJsonParseError* jsonError) { - CaraPerson person; - QJsonDocument dom = QJsonDocument::fromJson(buffer, jsonError); - - //check for errors - if(jsonError->error == QJsonParseError::NoError) { - //read the dom structure and populate the blend shapes and head poses - //qDebug() << "[Info] Cara Face Tracker Packet Parsing Successful!"; - - //begin extracting the packet - if(dom.isArray()) { - QJsonArray people = dom.array(); - //extract the first person in the array - if(people.size() > 0) { - QJsonValue val = people.at(0); - if(val.isObject()) { - QJsonObject personDOM = val.toObject(); - person.id = extractId(personDOM); - person.pose = extractPose(personDOM); - - //extract the classifier outputs - QJsonObject::const_iterator it = personDOM.constFind("classifiers"); - if(it != personDOM.constEnd()) { - QJsonObject classifierDOM = (*it).toObject(); - person.emotion = extractEmotion(classifierDOM); - person.blink = extractBlink(classifierDOM); - } - } - } - } - } - - return person; - } - -private: - static int extractId(const QJsonObject& person) { - int id = -1; - QJsonObject::const_iterator it = person.constFind("id"); - if(it != person.constEnd()) { - id = (*it).toInt(-1); - } - return id; - } - - static CaraPerson::CaraPose extractPose(const QJsonObject& person) { - CaraPerson::CaraPose pose; - QJsonObject::const_iterator it = person.constFind("pose"); - if(it != person.constEnd()) { - QJsonObject poseDOM = (*it).toObject(); - - //look for the roll, pitch, yaw; - QJsonObject::const_iterator poseIt = poseDOM.constFind("roll"); - QJsonObject::const_iterator poseEnd = poseDOM.constEnd(); - if(poseIt != poseEnd) { - pose.roll = (float)(*poseIt).toDouble(0.0); - } - poseIt = poseDOM.constFind("pitch"); - if(poseIt != poseEnd) { - pose.pitch = (float)(*poseIt).toDouble(0.0); - } - poseIt = poseDOM.constFind("yaw"); - if(poseIt != poseEnd) { - pose.yaw = (float)(*poseIt).toDouble(0.0); - } - } - return pose; - } - - static CaraPerson::CaraEmotion extractEmotion(const QJsonObject& classifiers) { - CaraPerson::CaraEmotion emotion; - QJsonObject::const_iterator it = classifiers.constFind("emotion"); - if(it != classifiers.constEnd()) { - QJsonObject emotionDOM = (*it).toObject(); - - //look for smile, surprise, negative, attention responses - QJsonObject::const_iterator emoEnd = emotionDOM.constEnd(); - QJsonObject::const_iterator emoIt = emotionDOM.constFind("smi"); - if(emoIt != emoEnd) { - emotion.smile = (float)(*emoIt).toDouble(0.0); - } - emoIt = emotionDOM.constFind("sur"); - if(emoIt != emoEnd) { - emotion.surprise = (float)(*emoIt).toDouble(0.0); - } - emoIt = emotionDOM.constFind("neg"); - if(emoIt != emoEnd) { - emotion.negative = (float)(*emoIt).toDouble(0.0); - } - emoIt = emotionDOM.constFind("att"); - if(emoIt != emoEnd) { - emotion.attention = (float)(*emoIt).toDouble(0.0); - } - } - return emotion; - } - - static CaraPerson::CaraBlink extractBlink(const QJsonObject& classifiers) { - CaraPerson::CaraBlink blink = CaraPerson::BLINK_NOT_AVAILABLE; - QJsonObject::const_iterator it = classifiers.constFind("blink"); - if(it != classifiers.constEnd()) { - int b = (*it).toInt(CaraPerson::BLINK_NOT_AVAILABLE); - switch(b) { - case CaraPerson::BLINK_NOT_AVAILABLE: - blink = CaraPerson::BLINK_NOT_AVAILABLE; - break; - case CaraPerson::NO_BLINK: - blink = CaraPerson::NO_BLINK; - break; - case CaraPerson::BLINK: - blink = CaraPerson::BLINK; - break; - default: - blink = CaraPerson::BLINK_NOT_AVAILABLE; - break; - } - } - return blink; - } -}; - -CaraFaceTracker::CaraFaceTracker() : - _lastReceiveTimestamp(0), - _pitchAverage(NUM_SMOOTHING_SAMPLES), - _yawAverage(NUM_SMOOTHING_SAMPLES), - _rollAverage(NUM_SMOOTHING_SAMPLES), - _eyeGazeLeftPitch(0.0f), - _eyeGazeLeftYaw(0.0f), - _eyeGazeRightPitch(0.0f), - _eyeGazeRightYaw(0), - _leftBlinkIndex(0), - _rightBlinkIndex(1), - _leftEyeOpenIndex(8), - _rightEyeOpenIndex(9), - _browDownLeftIndex(14), - _browDownRightIndex(15), - _browUpCenterIndex(16), - _browUpLeftIndex(17), - _browUpRightIndex(18), - _mouthSmileLeftIndex(28), - _mouthSmileRightIndex(29), - _jawOpenIndex(21) -{ - connect(&_udpSocket, SIGNAL(readyRead()), SLOT(readPendingDatagrams())); - connect(&_udpSocket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketErrorOccurred(QAbstractSocket::SocketError))); - connect(&_udpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SLOT(socketStateChanged(QAbstractSocket::SocketState))); - - bindTo(CARA_FEATURE_POINT_SERVER_PORT); - - _headTranslation = DEFAULT_HEAD_ORIGIN; - _blendshapeCoefficients.resize(NUM_BLENDSHAPE_COEFF); - _blendshapeCoefficients.fill(0.0f); - - //qDebug() << sampleJson; -} - -CaraFaceTracker::CaraFaceTracker(const QHostAddress& host, quint16 port) : - _lastReceiveTimestamp(0), - _pitchAverage(NUM_SMOOTHING_SAMPLES), - _yawAverage(NUM_SMOOTHING_SAMPLES), - _rollAverage(NUM_SMOOTHING_SAMPLES), - _eyeGazeLeftPitch(0.0f), - _eyeGazeLeftYaw(0.0f), - _eyeGazeRightPitch(0.0f), - _eyeGazeRightYaw(0.0f), - _leftBlinkIndex(0), - _rightBlinkIndex(1), - _leftEyeOpenIndex(8), - _rightEyeOpenIndex(9), - _browDownLeftIndex(14), - _browDownRightIndex(15), - _browUpCenterIndex(16), - _browUpLeftIndex(17), - _browUpRightIndex(18), - _mouthSmileLeftIndex(28), - _mouthSmileRightIndex(29), - _jawOpenIndex(21) -{ - connect(&_udpSocket, SIGNAL(readyRead()), SLOT(readPendingDatagrams())); - connect(&_udpSocket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketErrorOccurred(QAbstractSocket::SocketError))); - connect(&_udpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SIGNAL(socketStateChanged(QAbstractSocket::SocketState))); - - bindTo(host, port); - - _headTranslation = DEFAULT_HEAD_ORIGIN * TRANSLATION_SCALE; - _blendshapeCoefficients.resize(NUM_BLENDSHAPE_COEFF); //set the size of the blendshape coefficients - _blendshapeCoefficients.fill(0.0f); -} - -CaraFaceTracker::~CaraFaceTracker() { - if(_udpSocket.isOpen()) - _udpSocket.close(); -} - -void CaraFaceTracker::init() { - -} - -void CaraFaceTracker::reset() { - -} - -void CaraFaceTracker::bindTo(quint16 port) { - bindTo(QHostAddress::Any, port); -} - -void CaraFaceTracker::bindTo(const QHostAddress& host, quint16 port) { - if(_udpSocket.isOpen()) { - _udpSocket.close(); - } - _udpSocket.bind(host, port); -} - -bool CaraFaceTracker::isActive() const { - static const quint64 ACTIVE_TIMEOUT_USECS = 3000000; //3 secs - return (usecTimestampNow() - _lastReceiveTimestamp < ACTIVE_TIMEOUT_USECS); -} - -void CaraFaceTracker::update() { - // get the euler angles relative to the window - glm::vec3 eulers = glm::degrees(safeEulerAngles(_headRotation * glm::quat(glm::radians(glm::vec3( - (_eyeGazeLeftPitch + _eyeGazeRightPitch) / 2.0f, (_eyeGazeLeftYaw + _eyeGazeRightYaw) / 2.0f, 0.0f))))); - - //TODO: integrate when cara has eye gaze estimation - - _estimatedEyePitch = eulers.x; - _estimatedEyeYaw = eulers.y; -} - -//private slots and methods -void CaraFaceTracker::socketErrorOccurred(QAbstractSocket::SocketError socketError) { - qDebug() << "[Error] Cara Face Tracker Socket Error: " << _udpSocket.errorString(); -} - -void CaraFaceTracker::socketStateChanged(QAbstractSocket::SocketState socketState) { - QString state; - switch(socketState) { - case QAbstractSocket::BoundState: - state = "Bounded"; - break; - case QAbstractSocket::ClosingState: - state = "Closing"; - break; - case QAbstractSocket::ConnectedState: - state = "Connected"; - break; - case QAbstractSocket::ConnectingState: - state = "Connecting"; - break; - case QAbstractSocket::HostLookupState: - state = "Host Lookup"; - break; - case QAbstractSocket::ListeningState: - state = "Listening"; - break; - case QAbstractSocket::UnconnectedState: - state = "Unconnected"; - break; - } - qDebug() << "[Info] Cara Face Tracker Socket: " << socketState; -} - -void CaraFaceTracker::readPendingDatagrams() { - QByteArray buffer; - while (_udpSocket.hasPendingDatagrams()) { - buffer.resize(_udpSocket.pendingDatagramSize()); - _udpSocket.readDatagram(buffer.data(), buffer.size()); - decodePacket(buffer); - } -} - -void CaraFaceTracker::decodePacket(const QByteArray& buffer) { - //decode the incoming udp packet - QJsonParseError jsonError; - CaraPerson person = CaraPacketDecoder::extractOne(buffer, &jsonError); - - if(jsonError.error == QJsonParseError::NoError) { - - //do some noise filtering to the head poses - //reduce the noise first by truncating to 1 dp - person.pose.roll = glm::floor(person.pose.roll * 10) / 10; - person.pose.pitch = glm::floor(person.pose.pitch * 10) / 10; - person.pose.yaw = glm::floor(person.pose.yaw * 10) / 10; - - //qDebug() << person.toString(); - - glm::quat newRotation(glm::vec3(DEGTORAD(person.pose.pitch), DEGTORAD(person.pose.yaw), DEGTORAD(person.pose.roll))); - - // Compute angular velocity of the head - glm::quat r = newRotation * glm::inverse(_headRotation); - float theta = 2 * acos(r.w); - if (theta > EPSILON) { - float rMag = glm::length(glm::vec3(r.x, r.y, r.z)); - const float AVERAGE_CARA_FRAME_TIME = 0.04f; - const float YAW_STANDARD_DEV_DEG = 2.5f; - - _headAngularVelocity = theta / AVERAGE_CARA_FRAME_TIME * glm::vec3(r.x, r.y, r.z) / rMag; - _pitchAverage.updateAverage(person.pose.pitch); - _rollAverage.updateAverage(person.pose.roll); - - //could use the angular velocity to detemine whether to update pitch and roll to further remove the noise. - //use the angular velocity for roll and pitch, update if > THRESHOLD - //if(glm::abs(_headAngularVelocity.x) > ANGULAR_VELOCITY_MIN) { - // _pitchAverage.updateAverage(person.pose.pitch); - //} - - //if(glm::abs(_headAngularVelocity.z) > ANGULAR_VELOCITY_MIN) { - // _rollAverage.updateAverage(person.pose.roll);; - //} - - //for yaw, the jitter is great, you can't use angular velocity because it swings too much - //use the previous and current yaw, calculate the - //abs difference and move it the difference is above the standard deviation which is around 2.5 - // > the standard deviation 2.5 deg, update the yaw smoothing average - if(glm::abs(person.pose.yaw - _yawAverage.getAverage()) > YAW_STANDARD_DEV_DEG) { - //qDebug() << "Yaw Diff: " << glm::abs(person.pose.yaw - _previousYaw); - _yawAverage.updateAverage(person.pose.yaw); - } - - //set the new rotation - newRotation = glm::quat(glm::vec3(DEGTORAD(_pitchAverage.getAverage()), DEGTORAD(_yawAverage.getAverage()), DEGTORAD(-_rollAverage.getAverage()))); - } - else { - //no change in position, use previous averages - newRotation = glm::quat(glm::vec3(DEGTORAD(_pitchAverage.getAverage()), DEGTORAD(_yawAverage.getAverage()), DEGTORAD(-_rollAverage.getAverage()))); - _headAngularVelocity = glm::vec3(0,0,0); - } - - //update to new rotation angles - _headRotation = newRotation; - - //TODO: head translation, right now is 0 - - //Do Blendshapes, clip between 0.0f to 1.0f, neg should be ignored - _blendshapeCoefficients[_leftBlinkIndex] = person.blink == CaraPerson::BLINK ? 1.0f : 0.0f; - _blendshapeCoefficients[_rightBlinkIndex] = person.blink == CaraPerson::BLINK ? 1.0f : 0.0f; - - //anger and surprised are mutually exclusive so we could try use this fact to determine - //whether to down the brows or up the brows - _blendshapeCoefficients[_browDownLeftIndex] = person.emotion.negative < 0.0f ? 0.0f : person.emotion.negative; - _blendshapeCoefficients[_browDownRightIndex] = person.emotion.negative < 0.0f ? 0.0f : person.emotion.negative; - _blendshapeCoefficients[_browUpCenterIndex] = person.emotion.surprise < 0.0f ? 0.0f : person.emotion.surprise; - _blendshapeCoefficients[_browUpLeftIndex] = person.emotion.surprise < 0.0f ? 0.0f : person.emotion.surprise; - _blendshapeCoefficients[_browUpRightIndex] = person.emotion.surprise < 0.0f ? 0.0f : person.emotion.surprise; - _blendshapeCoefficients[_jawOpenIndex] = person.emotion.surprise < 0.0f ? 0.0f : person.emotion.surprise; - _blendshapeCoefficients[_mouthSmileLeftIndex] = person.emotion.smile < 0.0f ? 0.0f : person.emotion.smile; - _blendshapeCoefficients[_mouthSmileRightIndex] = person.emotion.smile < 0.0f ? 0.0f : person.emotion.smile; - } - else { - qDebug() << "[Error] Cara Face Tracker Decode Error: " << jsonError.errorString(); - } - - _lastReceiveTimestamp = usecTimestampNow(); -} - -float CaraFaceTracker::getBlendshapeCoefficient(int index) const { - return (index >= 0 && index < (int)_blendshapeCoefficients.size()) ? _blendshapeCoefficients[index] : 0.0f; -} diff --git a/interface/src/devices/CaraFaceTracker.h b/interface/src/devices/CaraFaceTracker.h deleted file mode 100644 index 0c715afda9..0000000000 --- a/interface/src/devices/CaraFaceTracker.h +++ /dev/null @@ -1,124 +0,0 @@ -// -// CaraFaceTracker.h -// interface/src/devices -// -// Created by Li Zuwei on 7/22/14. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_CaraFaceTracker_h -#define hifi_CaraFaceTracker_h - -#include - -#include -#include "FaceTracker.h" - -/*! - * \class CaraFaceTracker - * - * \brief Handles interaction with the Cara software, - * which provides head position/orientation and facial features. - * \details By default, opens a udp socket with IPV4_ANY_ADDR with port 36555. - * User needs to run the Cara Face Detection UDP Client with the destination - * host address (eg: 127.0.0.1 for localhost) and destination port 36555. -**/ - -class CaraFaceTracker : public FaceTracker { - Q_OBJECT - -public: - CaraFaceTracker(); - CaraFaceTracker(const QHostAddress& host, quint16 port); - ~CaraFaceTracker(); - - //initialization - void init(); - void reset(); - - //sockets - void bindTo(quint16 port); - void bindTo(const QHostAddress& host, quint16 port); - bool isActive() const; - - //tracking - void update(); - - //head angular velocity - const glm::vec3& getHeadAngularVelocity() const { return _headAngularVelocity; } - - //eye gaze - float getEyeGazeLeftPitch() const { return _eyeGazeLeftPitch; } - float getEyeGazeLeftYaw() const { return _eyeGazeLeftYaw; } - - float getEyeGazeRightPitch() const { return _eyeGazeRightPitch; } - float getEyeGazeRightYaw() const { return _eyeGazeRightYaw; } - - //blend shapes - float getLeftBlink() const { return getBlendshapeCoefficient(_leftBlinkIndex); } - float getRightBlink() const { return getBlendshapeCoefficient(_rightBlinkIndex); } - float getLeftEyeOpen() const { return getBlendshapeCoefficient(_leftEyeOpenIndex); } - float getRightEyeOpen() const { return getBlendshapeCoefficient(_rightEyeOpenIndex); } - - float getBrowDownLeft() const { return getBlendshapeCoefficient(_browDownLeftIndex); } - float getBrowDownRight() const { return getBlendshapeCoefficient(_browDownRightIndex); } - float getBrowUpCenter() const { return getBlendshapeCoefficient(_browUpCenterIndex); } - float getBrowUpLeft() const { return getBlendshapeCoefficient(_browUpLeftIndex); } - float getBrowUpRight() const { return getBlendshapeCoefficient(_browUpRightIndex); } - - float getMouthSize() const { return getBlendshapeCoefficient(_jawOpenIndex); } - float getMouthSmileLeft() const { return getBlendshapeCoefficient(_mouthSmileLeftIndex); } - float getMouthSmileRight() const { return getBlendshapeCoefficient(_mouthSmileRightIndex); } - -private slots: - - //sockets - void socketErrorOccurred(QAbstractSocket::SocketError socketError); - void readPendingDatagrams(); - void socketStateChanged(QAbstractSocket::SocketState socketState); - -private: - void decodePacket(const QByteArray& buffer); - float getBlendshapeCoefficient(int index) const; - - // sockets - QUdpSocket _udpSocket; - quint64 _lastReceiveTimestamp; - - //head tracking - glm::vec3 _headAngularVelocity; - - //pose average - SimpleMovingAverage _pitchAverage; - SimpleMovingAverage _yawAverage; - SimpleMovingAverage _rollAverage; - - // eye gaze degrees - float _eyeGazeLeftPitch; - float _eyeGazeLeftYaw; - float _eyeGazeRightPitch; - float _eyeGazeRightYaw; - - //blend shapes - int _leftBlinkIndex; - int _rightBlinkIndex; - int _leftEyeOpenIndex; - int _rightEyeOpenIndex; - - // Brows - int _browDownLeftIndex; - int _browDownRightIndex; - int _browUpCenterIndex; - int _browUpLeftIndex; - int _browUpRightIndex; - - int _mouthSmileLeftIndex; - int _mouthSmileRightIndex; - - int _jawOpenIndex; -}; - -#endif //endif hifi_CaraFaceTracker_h diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 1f43979c03..fcbfd32350 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -282,6 +282,9 @@ void OculusManager::calibrate(glm::vec3 position, glm::quat orientation) { _calibrationState = WAITING_FOR_ZERO; } break; + default: + break; + } } #endif diff --git a/interface/src/gpu/Resource.cpp b/interface/src/gpu/Resource.cpp index 23ea12e6e8..31f53c8201 100644 --- a/interface/src/gpu/Resource.cpp +++ b/interface/src/gpu/Resource.cpp @@ -44,16 +44,16 @@ void Resource::Sysmem::deallocateMemory(Byte* dataAllocated, Size size) { } Resource::Sysmem::Sysmem() : - _data(NULL), + _stamp(0), _size(0), - _stamp(0) + _data(NULL) { } Resource::Sysmem::Sysmem(Size size, const Byte* bytes) : - _data(NULL), + _stamp(0), _size(0), - _stamp(0) + _data(NULL) { if (size > 0) { _size = allocateMemory(&_data, size); diff --git a/interface/src/ui/overlays/BillboardOverlay.cpp b/interface/src/ui/overlays/BillboardOverlay.cpp index e00011bf6b..c52b07bcfa 100644 --- a/interface/src/ui/overlays/BillboardOverlay.cpp +++ b/interface/src/ui/overlays/BillboardOverlay.cpp @@ -15,11 +15,12 @@ #include "BillboardOverlay.h" -BillboardOverlay::BillboardOverlay() -: _fromImage(-1,-1,-1,-1), - _scale(1.0f), - _isFacingAvatar(true), - _newTextureNeeded(true) { +BillboardOverlay::BillboardOverlay() : + _newTextureNeeded(true), + _fromImage(-1,-1,-1,-1), + _scale(1.0f), + _isFacingAvatar(true) +{ _isLoaded = false; } From 1911cfd0be9313b16afa5588e8da97e90f9484a9 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 10 Oct 2014 15:11:37 -0700 Subject: [PATCH 22/43] Basic ray/voxel intersection testing up and running. --- interface/src/MetavoxelSystem.cpp | 76 +++++++++++++++++++++++-------- interface/src/MetavoxelSystem.h | 9 ++-- 2 files changed, 62 insertions(+), 23 deletions(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 9732036def..19a9a7ce89 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -354,9 +354,8 @@ int RayVoxelIntersectionVisitor::visit(MetavoxelInfo& info, float distance) { if (!buffer) { return STOP_RECURSION; } - glm::vec3 origin = ((_origin + distance * _direction) - info.minimum) / info.size; - if (buffer->findFirstRayIntersection(origin, _direction, intersectionDistance)) { - intersectionDistance = intersectionDistance * info.size + distance; + glm::vec3 entry = ((_origin + distance * _direction) - info.minimum) / info.size; + if (buffer->findFirstRayIntersection(entry, _origin, _direction, intersectionDistance)) { return SHORT_CIRCUIT; } return STOP_RECURSION; @@ -1035,11 +1034,11 @@ void VoxelPoint::setNormal(const glm::vec3& normal) { } VoxelBuffer::VoxelBuffer(const QVector& vertices, const QVector& indices, const QVector& hermite, - const QHash& points, int size, const QVector& materials) : + const QMultiHash& quadIndices, int size, const QVector& materials) : _vertices(vertices), _indices(indices), _hermite(hermite), - _points(points), + _quadIndices(quadIndices), _size(size), _vertexCount(vertices.size()), _indexCount(indices.size()), @@ -1048,17 +1047,47 @@ VoxelBuffer::VoxelBuffer(const QVector& vertices, const QVector _materials(materials) { } -bool VoxelBuffer::findFirstRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const { +static bool findRayTriangleIntersection(const glm::vec3& origin, const glm::vec3& direction, + const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, float& distance) { + glm::vec3 firstSide = v0 - v1; + glm::vec3 secondSide = v2 - v1; + glm::vec3 normal = glm::cross(secondSide, firstSide); + float dividend = glm::dot(normal, v1) - glm::dot(origin, normal); + if (dividend > 0.0f) { + return false; // origin below plane + } + float divisor = glm::dot(normal, direction); + if (divisor > -EPSILON) { + return false; + } + float t = dividend / divisor; + glm::vec3 point = origin + direction * t; + if (glm::dot(normal, glm::cross(point - v1, firstSide)) > 0.0f && + glm::dot(normal, glm::cross(secondSide, point - v1)) > 0.0f && + glm::dot(normal, glm::cross(point - v0, v2 - v0)) > 0.0f) { + distance = t; + return true; + } + return false; +} + +bool VoxelBuffer::findFirstRayIntersection(const glm::vec3& entry, const glm::vec3& origin, + const glm::vec3& direction, float& distance) const { float highest = _size - 1.0f; - glm::vec3 position = origin * highest; + glm::vec3 position = entry * highest; glm::vec3 floors = glm::floor(position); int max = _size - 2; int x = qMin((int)floors.x, max), y = qMin((int)floors.y, max), z = qMin((int)floors.z, max); - float combinedDistance = 0.0f; forever { - if (_points.contains(qRgb(x + 1, y + 1, z + 1))) { - distance = combinedDistance / highest; - return true; + for (QMultiHash::const_iterator it = _quadIndices.constFind(qRgb(x + 1, y + 1, z + 1)); + it != _quadIndices.constEnd(); it++) { + const int* indices = _indices.constData() + *it; + if (findRayTriangleIntersection(origin, direction, _vertices.at(indices[0]).vertex, + _vertices.at(indices[1]).vertex, _vertices.at(indices[2]).vertex, distance) || + findRayTriangleIntersection(origin, direction, _vertices.at(indices[0]).vertex, + _vertices.at(indices[2]).vertex, _vertices.at(indices[3]).vertex, distance)) { + return true; + } } float xDistance = FLT_MAX, yDistance = FLT_MAX, zDistance = FLT_MAX; if (direction.x > 0.0f) { @@ -1105,7 +1134,6 @@ bool VoxelBuffer::findFirstRayIntersection(const glm::vec3& origin, const glm::v } } position += direction * minimumDistance; - combinedDistance += minimumDistance; } return false; } @@ -1115,13 +1143,11 @@ void VoxelBuffer::render(bool cursor) { _vertexBuffer.create(); _vertexBuffer.bind(); _vertexBuffer.allocate(_vertices.constData(), _vertices.size() * sizeof(VoxelPoint)); - _vertices.clear(); - + _indexBuffer.create(); _indexBuffer.bind(); _indexBuffer.allocate(_indices.constData(), _indices.size() * sizeof(int)); - _indices.clear(); - + if (!_materials.isEmpty()) { _networkTextures.resize(_materials.size()); for (int i = 0; i < _materials.size(); i++) { @@ -1735,7 +1761,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { QVector vertices; QVector indices; QVector hermiteSegments; - QHash points; + QMultiHash quadIndices; // see http://www.frankpetterson.com/publications/dualcontour/dualcontour.pdf for a description of the // dual contour algorithm for generating meshes from voxel data using Hermite-tagged edges @@ -2142,8 +2168,6 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { { (quint8)materialWeights[0], (quint8)materialWeights[1], (quint8)materialWeights[2], (quint8)materialWeights[3] } }; - points.insert(qRgb(x + 1, y + 1, z + 1), (glm::vec3(clampedX, clampedY, clampedZ) + center) / highest); - // determine whether we must "crease" by generating directional normals const float CREASE_COS_NORMAL = glm::cos(glm::radians(40.0f)); AxisIndex index(vertices.size(), vertices.size(), vertices.size()); @@ -2202,6 +2226,10 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { // quads for each edge that includes a transition, using indices of previously generated vertices if (x != 0 && y != 0 && z != 0) { if (alpha0 != alpha1) { + quadIndices.insert(qRgb(x, y, z), indices.size()); + quadIndices.insert(qRgb(x, y - 1, z), indices.size()); + quadIndices.insert(qRgb(x, y - 1, z - 1), indices.size()); + quadIndices.insert(qRgb(x, y, z - 1), indices.size()); indices.append(index.x); int index1 = lastLineIndices.at(x).x; int index2 = lastPlaneIndices.at((y - 1) * expanded + x).x; @@ -2218,6 +2246,10 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { } if (alpha0 != alpha2) { + quadIndices.insert(qRgb(x, y, z), indices.size()); + quadIndices.insert(qRgb(x - 1, y, z), indices.size()); + quadIndices.insert(qRgb(x - 1, y, z - 1), indices.size()); + quadIndices.insert(qRgb(x, y, z - 1), indices.size()); indices.append(index.y); int index1 = lastIndex.y; int index2 = lastPlaneIndices.at(y * expanded + x - 1).y; @@ -2234,6 +2266,10 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { } if (alpha0 != alpha4) { + quadIndices.insert(qRgb(x, y, z), indices.size()); + quadIndices.insert(qRgb(x - 1, y, z), indices.size()); + quadIndices.insert(qRgb(x - 1, y - 1, z), indices.size()); + quadIndices.insert(qRgb(x, y - 1, z), indices.size()); indices.append(index.z); int index1 = lastIndex.z; int index2 = lastLineIndices.at(x - 1).z; @@ -2269,7 +2305,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { colorZ += area; } } - buffer = new VoxelBuffer(vertices, indices, hermiteSegments, points, size, + buffer = new VoxelBuffer(vertices, indices, hermiteSegments, quadIndices, size, material ? material->getMaterials() : QVector()); } BufferDataPointer pointer(buffer); diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h index e256716fc0..daa1bd6ca2 100644 --- a/interface/src/MetavoxelSystem.h +++ b/interface/src/MetavoxelSystem.h @@ -243,10 +243,13 @@ class VoxelBuffer : public BufferData { public: VoxelBuffer(const QVector& vertices, const QVector& indices, const QVector& hermite, - const QHash& points, int size, const QVector& materials = + const QMultiHash& quadIndices, int size, const QVector& materials = QVector()); - bool findFirstRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const; + /// Finds the first intersection between the described ray and the voxel data. + /// \param entry the entry point of the ray in relative coordinates, from (0, 0, 0) to (1, 1, 1) + bool findFirstRayIntersection(const glm::vec3& entry, const glm::vec3& origin, + const glm::vec3& direction, float& distance) const; virtual void render(bool cursor = false); @@ -255,7 +258,7 @@ private: QVector _vertices; QVector _indices; QVector _hermite; - QHash _points; + QMultiHash _quadIndices; int _size; int _vertexCount; int _indexCount; From 762cc71d31b0f8a747eea4c3557d9e8ca636d8c7 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 10 Oct 2014 17:03:10 -0700 Subject: [PATCH 23/43] Update to SDL2 --- cmake/modules/FindSDL2.cmake | 249 ++++++++++++++++++ interface/CMakeLists.txt | 2 +- interface/src/devices/Joystick.cpp | 52 ++-- interface/src/devices/Joystick.h | 34 ++- .../scripting/JoystickScriptingInterface.cpp | 130 ++++----- .../scripting/JoystickScriptingInterface.h | 83 +++++- 6 files changed, 436 insertions(+), 114 deletions(-) create mode 100644 cmake/modules/FindSDL2.cmake diff --git a/cmake/modules/FindSDL2.cmake b/cmake/modules/FindSDL2.cmake new file mode 100644 index 0000000000..f24af555a2 --- /dev/null +++ b/cmake/modules/FindSDL2.cmake @@ -0,0 +1,249 @@ +# Locate SDL2 library +# This module defines +# SDL2_LIBRARY, the name of the library to link against +# SDL2_FOUND, if false, do not try to link to SDL2 +# SDL2_INCLUDE_DIR, where to find SDL.h +# +# This module responds to the the flag: +# SDL2_BUILDING_LIBRARY +# If this is defined, then no SDL2_main will be linked in because +# only applications need main(). +# Otherwise, it is assumed you are building an application and this +# module will attempt to locate and set the the proper link flags +# as part of the returned SDL2_LIBRARY variable. +# +# Don't forget to include SDL2main.h and SDL2main.m your project for the +# OS X framework based version. (Other versions link to -lSDL2main which +# this module will try to find on your behalf.) Also for OS X, this +# module will automatically add the -framework Cocoa on your behalf. +# +# +# Additional Note: If you see an empty SDL2_LIBRARY_TEMP in your configuration +# and no SDL2_LIBRARY, it means CMake did not find your SDL2 library +# (SDL2.dll, libsdl2.so, SDL2.framework, etc). +# Set SDL2_LIBRARY_TEMP to point to your SDL2 library, and configure again. +# Similarly, if you see an empty SDL2MAIN_LIBRARY, you should set this value +# as appropriate. These values are used to generate the final SDL2_LIBRARY +# variable, but when these values are unset, SDL2_LIBRARY does not get created. +# +# +# $SDL2 is an environment variable that would +# correspond to the ./configure --prefix=$SDL2 +# used in building SDL2. +# l.e.galup 9-20-02 +# +# Modified by Eric Wing. +# Added code to assist with automated building by using environmental variables +# and providing a more controlled/consistent search behavior. +# Added new modifications to recognize OS X frameworks and +# additional Unix paths (FreeBSD, etc). +# Also corrected the header search path to follow "proper" SDL2 guidelines. +# Added a search for SDL2main which is needed by some platforms. +# Added a search for threads which is needed by some platforms. +# Added needed compile switches for MinGW. +# +# On OSX, this will prefer the Framework version (if found) over others. +# People will have to manually change the cache values of +# SDL2_LIBRARY to override this selection or set the CMake environment +# CMAKE_INCLUDE_PATH to modify the search paths. +# +# Note that the header path has changed from SDL2/SDL.h to just SDL.h +# This needed to change because "proper" SDL2 convention +# is #include "SDL.h", not . This is done for portability +# reasons because not all systems place things in SDL2/ (see FreeBSD). +# +# Ported by Johnny Patterson. This is a literal port for SDL2 of the FindSDL.cmake +# module with the minor edit of changing "SDL" to "SDL2" where necessary. This +# was not created for redistribution, and exists temporarily pending official +# SDL2 CMake modules. +# +# Note that on windows this will only search for the 32bit libraries, to search +# for 64bit change x86/i686-w64 to x64/x86_64-w64 + +#============================================================================= +# Copyright 2003-2009 Kitware, Inc. +# +# CMake - Cross Platform Makefile Generator +# Copyright 2000-2014 Kitware, Inc. +# Copyright 2000-2011 Insight Software Consortium +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the names of Kitware, Inc., the Insight Software Consortium, +# nor the names of their contributors may be used to endorse or promote +# products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +FIND_PATH(SDL2_INCLUDE_DIR SDL.h + HINTS + $ENV{SDL2} + PATH_SUFFIXES include/SDL2 include SDL2 + i686-w64-mingw32/include/SDL2 + x86_64-w64-mingw32/include/SDL2 + PATHS + ~/Library/Frameworks + /Library/Frameworks + /usr/local/include/SDL2 + /usr/include/SDL2 + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave + /opt +) + +# Lookup the 64 bit libs on x64 +IF(CMAKE_SIZEOF_VOID_P EQUAL 8) + FIND_LIBRARY(SDL2_LIBRARY_TEMP SDL2 + HINTS + $ENV{SDL2} + PATH_SUFFIXES lib64 lib + lib/x64 + x86_64-w64-mingw32/lib + PATHS + /sw + /opt/local + /opt/csw + /opt + ) +# On 32bit build find the 32bit libs +ELSE(CMAKE_SIZEOF_VOID_P EQUAL 8) + FIND_LIBRARY(SDL2_LIBRARY_TEMP SDL2 + HINTS + $ENV{SDL2} + PATH_SUFFIXES lib + lib/x86 + i686-w64-mingw32/lib + PATHS + /sw + /opt/local + /opt/csw + /opt + ) +ENDIF(CMAKE_SIZEOF_VOID_P EQUAL 8) + +IF(NOT SDL2_BUILDING_LIBRARY) + IF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework") + # Non-OS X framework versions expect you to also dynamically link to + # SDL2main. This is mainly for Windows and OS X. Other (Unix) platforms + # seem to provide SDL2main for compatibility even though they don't + # necessarily need it. + # Lookup the 64 bit libs on x64 + IF(CMAKE_SIZEOF_VOID_P EQUAL 8) + FIND_LIBRARY(SDL2MAIN_LIBRARY + NAMES SDL2main + HINTS + $ENV{SDL2} + PATH_SUFFIXES lib64 lib + lib/x64 + x86_64-w64-mingw32/lib + PATHS + /sw + /opt/local + /opt/csw + /opt + ) + # On 32bit build find the 32bit libs + ELSE(CMAKE_SIZEOF_VOID_P EQUAL 8) + FIND_LIBRARY(SDL2MAIN_LIBRARY + NAMES SDL2main + HINTS + $ENV{SDL2} + PATH_SUFFIXES lib + lib/x86 + i686-w64-mingw32/lib + PATHS + /sw + /opt/local + /opt/csw + /opt + ) + ENDIF(CMAKE_SIZEOF_VOID_P EQUAL 8) + ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework") +ENDIF(NOT SDL2_BUILDING_LIBRARY) + +# SDL2 may require threads on your system. +# The Apple build may not need an explicit flag because one of the +# frameworks may already provide it. +# But for non-OSX systems, I will use the CMake Threads package. +IF(NOT APPLE) + FIND_PACKAGE(Threads) +ENDIF(NOT APPLE) + +# MinGW needs an additional library, mwindows +# It's total link flags should look like -lmingw32 -lSDL2main -lSDL2 -lmwindows +# (Actually on second look, I think it only needs one of the m* libraries.) +IF(MINGW) + SET(MINGW32_LIBRARY mingw32 CACHE STRING "mwindows for MinGW") +ENDIF(MINGW) + +SET(SDL2_FOUND "NO") + IF(SDL2_LIBRARY_TEMP) + # For SDL2main + IF(NOT SDL2_BUILDING_LIBRARY) + IF(SDL2MAIN_LIBRARY) + SET(SDL2_LIBRARY_TEMP ${SDL2MAIN_LIBRARY} ${SDL2_LIBRARY_TEMP}) + ENDIF(SDL2MAIN_LIBRARY) + ENDIF(NOT SDL2_BUILDING_LIBRARY) + + # For OS X, SDL2 uses Cocoa as a backend so it must link to Cocoa. + # CMake doesn't display the -framework Cocoa string in the UI even + # though it actually is there if I modify a pre-used variable. + # I think it has something to do with the CACHE STRING. + # So I use a temporary variable until the end so I can set the + # "real" variable in one-shot. + IF(APPLE) + SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} "-framework Cocoa") + ENDIF(APPLE) + + # For threads, as mentioned Apple doesn't need this. + # In fact, there seems to be a problem if I used the Threads package + # and try using this line, so I'm just skipping it entirely for OS X. + IF(NOT APPLE) + SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT}) + ENDIF(NOT APPLE) + + # For MinGW library + IF(MINGW) + SET(SDL2_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2_LIBRARY_TEMP}) + ENDIF(MINGW) + + # Set the final string here so the GUI reflects the final state. + SET(SDL2_LIBRARY ${SDL2_LIBRARY_TEMP} CACHE STRING "Where the SDL2 Library can be found") + # Set the temp variable to INTERNAL so it is not seen in the CMake GUI + SET(SDL2_LIBRARY_TEMP "${SDL2_LIBRARY_TEMP}" CACHE INTERNAL "") + + SET(SDL2_FOUND "YES") +ENDIF(SDL2_LIBRARY_TEMP) + +INCLUDE(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 1202b36a9f..16ca977bae 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -2,7 +2,7 @@ set(TARGET_NAME interface) project(${TARGET_NAME}) # set a default root dir for each of our optional externals if it was not passed -set(OPTIONAL_EXTERNALS "Faceplus" "Faceshift" "LibOVR" "PrioVR" "Sixense" "Visage" "LeapMotion" "RtMidi" "Qxmpp" "SDL") +set(OPTIONAL_EXTERNALS "Faceplus" "Faceshift" "LibOVR" "PrioVR" "Sixense" "Visage" "LeapMotion" "RtMidi" "Qxmpp" "SDL2") foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) string(TOUPPER ${EXTERNAL} ${EXTERNAL}_UPPERCASE) if (NOT ${${EXTERNAL}_UPPERCASE}_ROOT_DIR) diff --git a/interface/src/devices/Joystick.cpp b/interface/src/devices/Joystick.cpp index fe67eaceaa..b63d49eea2 100644 --- a/interface/src/devices/Joystick.cpp +++ b/interface/src/devices/Joystick.cpp @@ -15,13 +15,17 @@ #include "Joystick.h" -#ifdef HAVE_SDL +const float MAX_AXIS = 32767.0f; -Joystick::Joystick(const QString& name, SDL_Joystick* sdlJoystick) : +#ifdef HAVE_SDL2 + +Joystick::Joystick(SDL_JoystickID instanceId, const QString& name, SDL_GameController* sdlGameController) : + _instanceId(instanceId), _name(name), - _axes(QVector(SDL_JoystickNumAxes(sdlJoystick))), - _buttons(QVector(SDL_JoystickNumButtons(sdlJoystick))), - _sdlJoystick(sdlJoystick) + _sdlGameController(sdlGameController), + _sdlJoystick(SDL_GameControllerGetJoystick(_sdlGameController)), + _axes(QVector(SDL_JoystickNumAxes(_sdlJoystick))), + _buttons(QVector(SDL_JoystickNumButtons(_sdlJoystick))) { } @@ -33,30 +37,24 @@ Joystick::~Joystick() { } void Joystick::closeJoystick() { -#ifdef HAVE_SDL - SDL_JoystickClose(_sdlJoystick); +#ifdef HAVE_SDL2 + SDL_GameControllerClose(_sdlGameController); #endif } -void Joystick::update() { -#ifdef HAVE_SDL - // update our current values, emit a signal when there is a change - for (int j = 0; j < getNumAxes(); j++) { - float newValue = glm::round(SDL_JoystickGetAxis(_sdlJoystick, j) + 0.5f) / std::numeric_limits::max(); - if (_axes[j] != newValue) { - float oldValue = _axes[j]; - _axes[j] = newValue; - emit axisValueChanged(j, newValue, oldValue); - } - } - for (int j = 0; j < getNumButtons(); j++) { - bool newValue = SDL_JoystickGetButton(_sdlJoystick, j); - if (_buttons[j] != newValue) { - bool oldValue = _buttons[j]; - _buttons[j] = newValue; - emit buttonStateChanged(j, newValue, oldValue); - } - } +#ifdef HAVE_SDL2 +void Joystick::handleAxisEvent(const SDL_ControllerAxisEvent& event) { + float oldValue = _axes[event.axis]; + float newValue = event.value / MAX_AXIS; + _axes[event.axis] = newValue; + emit axisValueChanged(event.axis, newValue, oldValue); +} + +void Joystick::handleButtonEvent(const SDL_ControllerButtonEvent& event) { + bool oldValue = _buttons[event.button]; + bool newValue = event.state == SDL_PRESSED; + _buttons[event.button] = newValue; + emit buttonStateChanged(event.button, newValue, oldValue); +} #endif -} \ No newline at end of file diff --git a/interface/src/devices/Joystick.h b/interface/src/devices/Joystick.h index 8343c20a04..eeeeb03759 100644 --- a/interface/src/devices/Joystick.h +++ b/interface/src/devices/Joystick.h @@ -15,7 +15,7 @@ #include #include -#ifdef HAVE_SDL +#ifdef HAVE_SDL2 #include #undef main #endif @@ -24,6 +24,10 @@ class Joystick : public QObject { Q_OBJECT Q_PROPERTY(QString name READ getName) + +#ifdef HAVE_SDL2 + Q_PROPERTY(int instanceId READ getInstanceId) +#endif Q_PROPERTY(int numAxes READ getNumAxes) Q_PROPERTY(int numButtons READ getNumButtons) @@ -31,19 +35,21 @@ public: Joystick(); ~Joystick(); -#ifdef HAVE_SDL - Joystick(const QString& name, SDL_Joystick* sdlJoystick); +#ifdef HAVE_SDL2 + Joystick(SDL_JoystickID instanceId, const QString& name, SDL_GameController* sdlGameController); #endif - void update(); - void closeJoystick(); - -#ifdef HAVE_SDL - void setSDLJoystick(SDL_Joystick* sdlJoystick) { _sdlJoystick = sdlJoystick; } + +#ifdef HAVE_SDL2 + void handleAxisEvent(const SDL_ControllerAxisEvent& event); + void handleButtonEvent(const SDL_ControllerButtonEvent& event); #endif const QString& getName() const { return _name; } +#ifdef HAVE_SDL2 + int getInstanceId() const { return _instanceId; } +#endif const QVector& getAxes() const { return _axes; } const QVector& getButtons() const { return _buttons; } @@ -55,13 +61,15 @@ signals: void axisValueChanged(int axis, float newValue, float oldValue); void buttonStateChanged(int button, float newValue, float oldValue); private: +#ifdef HAVE_SDL2 + SDL_GameController* _sdlGameController; + SDL_Joystick* _sdlJoystick; + SDL_JoystickID _instanceId; +#endif + QString _name; QVector _axes; QVector _buttons; - -#ifdef HAVE_SDL - SDL_Joystick* _sdlJoystick; -#endif }; -#endif // hifi_JoystickTracker_h \ No newline at end of file +#endif // hifi_JoystickTracker_h diff --git a/interface/src/scripting/JoystickScriptingInterface.cpp b/interface/src/scripting/JoystickScriptingInterface.cpp index 87f841c494..3f0371e1cd 100644 --- a/interface/src/scripting/JoystickScriptingInterface.cpp +++ b/interface/src/scripting/JoystickScriptingInterface.cpp @@ -10,8 +10,9 @@ // #include +#include -#ifdef HAVE_SDL +#ifdef HAVE_SDL2 #include #undef main #endif @@ -20,104 +21,103 @@ #include "JoystickScriptingInterface.h" +#ifdef HAVE_SDL2 +SDL_JoystickID getInstanceId(SDL_GameController* controller) { + SDL_Joystick* joystick = SDL_GameControllerGetJoystick(controller); + return SDL_JoystickInstanceID(joystick); +} +#endif + JoystickScriptingInterface& JoystickScriptingInterface::getInstance() { static JoystickScriptingInterface sharedInstance; return sharedInstance; } JoystickScriptingInterface::JoystickScriptingInterface() : +#ifdef HAVE_SDL2 _openJoysticks(), - _availableDeviceNames(), +#endif _isInitialized(false) { - reset(); +#ifdef HAVE_SDL2 + bool initSuccess = (SDL_Init(SDL_INIT_GAMECONTROLLER) == 0); + + if (initSuccess) { + int joystickCount = SDL_NumJoysticks(); + + for (int i = 0; i < joystickCount; i++) { + SDL_GameController* controller = SDL_GameControllerOpen(i); + SDL_JoystickID id = getInstanceId(controller); + Joystick* joystick = new Joystick(id, SDL_GameControllerName(controller), controller); + _openJoysticks[id] = joystick; + } + + _isInitialized = true; + } else { + qDebug() << "Error initializing SDL"; + } +#endif } JoystickScriptingInterface::~JoystickScriptingInterface() { +#ifdef HAVE_SDL2 qDeleteAll(_openJoysticks); -#ifdef HAVE_SDL SDL_Quit(); - _isInitialized = false; #endif } -void JoystickScriptingInterface::reset() { -#ifdef HAVE_SDL - - if (_isInitialized) { - _isInitialized = false; - - // close all the open joysticks before we quit - foreach(Joystick* openJoystick, _openJoysticks) { - openJoystick->closeJoystick(); - } - - SDL_Quit(); - } - - bool initSuccess = (SDL_Init(SDL_INIT_JOYSTICK) == 0); - - if (initSuccess) { - - int joystickCount = SDL_NumJoysticks(); - - for (int i = 0; i < joystickCount; i++) { - _availableDeviceNames << SDL_JoystickName(i); - } - - foreach(const QString& joystickName, _openJoysticks.keys()) { - _openJoysticks[joystickName]->setSDLJoystick(openSDLJoystickWithName(joystickName)); - } - - _isInitialized = true; +const QObjectList JoystickScriptingInterface::getAllJoysticks() const { + QObjectList objectList; +#ifdef HAVE_SDL2 + const QList joystickList = _openJoysticks.values(); + for (int i = 0; i < joystickList.length(); i++) { + objectList << joystickList[i]; } #endif + return objectList; } void JoystickScriptingInterface::update() { -#ifdef HAVE_SDL +#ifdef HAVE_SDL2 if (_isInitialized) { PerformanceTimer perfTimer("JoystickScriptingInterface::update"); - SDL_JoystickUpdate(); - - foreach(Joystick* joystick, _openJoysticks) { - joystick->update(); + SDL_GameControllerUpdate(); + SDL_Event event; + while (SDL_PollEvent(&event)) { + if (event.type == SDL_CONTROLLERAXISMOTION) { + Joystick* joystick = _openJoysticks[event.caxis.which]; + if (joystick) { + joystick->handleAxisEvent(event.caxis); + } + } else if (event.type == SDL_CONTROLLERBUTTONDOWN || event.type == SDL_CONTROLLERBUTTONUP) { + Joystick* joystick = _openJoysticks[event.cbutton.which]; + if (joystick) { + joystick->handleButtonEvent(event.cbutton); + } + } else if (event.type == SDL_CONTROLLERDEVICEADDED) { + SDL_GameController* controller = SDL_GameControllerOpen(event.cdevice.which); + + SDL_JoystickID id = getInstanceId(controller); + Joystick* joystick = new Joystick(id, SDL_GameControllerName(controller), controller); + _openJoysticks[id] = joystick; + emit joystickAdded(joystick); + } else if (event.type == SDL_CONTROLLERDEVICEREMOVED) { + Joystick* joystick = _openJoysticks[event.cdevice.which]; + _openJoysticks.remove(event.cdevice.which); + emit joystickRemoved(joystick); + } } } #endif } -Joystick* JoystickScriptingInterface::joystickWithName(const QString& name) { - Joystick* matchingJoystick = _openJoysticks.value(name); -#ifdef HAVE_SDL - if (!matchingJoystick) { - SDL_Joystick* openSDLJoystick = openSDLJoystickWithName(name); - - if (openSDLJoystick) { - matchingJoystick = _openJoysticks.insert(name, new Joystick(name, openSDLJoystick)).value(); - } else { - qDebug() << "No matching joystick found with name" << name << "- returning NULL pointer."; - } - } -#endif - - return matchingJoystick; -} +#ifdef HAVE_SDL2 - -#ifdef HAVE_SDL - -SDL_Joystick* JoystickScriptingInterface::openSDLJoystickWithName(const QString &name) { +SDL_Joystick* JoystickScriptingInterface::openSDLJoystickWithName(const QString& name) { // we haven't opened a joystick with this name yet - enumerate our SDL devices and see if it exists int joystickCount = SDL_NumJoysticks(); - for (int i = 0; i < joystickCount; i++) { - if (SDL_JoystickName(i) == name) { - return SDL_JoystickOpen(i); - break; - } - } return NULL; } diff --git a/interface/src/scripting/JoystickScriptingInterface.h b/interface/src/scripting/JoystickScriptingInterface.h index 02624c70d5..37546a5a85 100644 --- a/interface/src/scripting/JoystickScriptingInterface.h +++ b/interface/src/scripting/JoystickScriptingInterface.h @@ -15,34 +15,101 @@ #include #include +#ifdef HAVE_SDL2 +#include +#endif + #include "devices/Joystick.h" /// Handles joystick input through SDL. class JoystickScriptingInterface : public QObject { Q_OBJECT - Q_PROPERTY(QStringList availableJoystickNames READ getAvailableJoystickNames) +#ifdef HAVE_SDL2 + Q_PROPERTY(int AXIS_INVALID READ axisInvalid) + Q_PROPERTY(int AXIS_LEFT_X READ axisLeftX) + Q_PROPERTY(int AXIS_LEFT_Y READ axisLeftY) + Q_PROPERTY(int AXIS_RIGHT_X READ axisRightX) + Q_PROPERTY(int AXIS_RIGHT_Y READ axisRightY) + Q_PROPERTY(int AXIS_TRIGGER_LEFT READ axisTriggerLeft) + Q_PROPERTY(int AXIS_TRIGGER_RIGHT READ axisTriggerRight) + Q_PROPERTY(int AXIS_MAX READ axisMax) + + Q_PROPERTY(int BUTTON_INVALID READ buttonInvalid) + Q_PROPERTY(int BUTTON_FACE_BOTTOM READ buttonFaceBottom) + Q_PROPERTY(int BUTTON_FACE_RIGHT READ buttonFaceRight) + Q_PROPERTY(int BUTTON_FACE_LEFT READ buttonFaceLeft) + Q_PROPERTY(int BUTTON_FACE_TOP READ buttonFaceTop) + Q_PROPERTY(int BUTTON_BACK READ buttonBack) + Q_PROPERTY(int BUTTON_GUIDE READ buttonGuide) + Q_PROPERTY(int BUTTON_START READ buttonStart) + Q_PROPERTY(int BUTTON_LEFT_STICK READ buttonLeftStick) + Q_PROPERTY(int BUTTON_RIGHT_STICK READ buttonRightStick) + Q_PROPERTY(int BUTTON_LEFT_SHOULDER READ buttonLeftShoulder) + Q_PROPERTY(int BUTTON_RIGHT_SHOULDER READ buttonRightShoulder) + Q_PROPERTY(int BUTTON_DPAD_UP READ buttonDpadUp) + Q_PROPERTY(int BUTTON_DPAD_DOWN READ buttonDpadDown) + Q_PROPERTY(int BUTTON_DPAD_LEFT READ buttonDpadLeft) + Q_PROPERTY(int BUTTON_DPAD_RIGHT READ buttonDpadRight) + Q_PROPERTY(int BUTTON_MAX READ buttonMax) + + Q_PROPERTY(int BUTTON_PRESSED READ buttonPressed) + Q_PROPERTY(int BUTTON_RELEASED READ buttonRelease) +#endif + public: static JoystickScriptingInterface& getInstance(); - const QStringList& getAvailableJoystickNames() const { return _availableDeviceNames; } - void update(); public slots: - Joystick* joystickWithName(const QString& name); - void reset(); + const QObjectList getAllJoysticks() const; + +signals: + void joystickAdded(Joystick* joystick); + void joystickRemoved(Joystick* joystick); private: -#ifdef HAVE_SDL +#ifdef HAVE_SDL2 + int axisInvalid() const { return SDL_CONTROLLER_AXIS_INVALID; } + int axisLeftX() const { return SDL_CONTROLLER_AXIS_LEFTX; } + int axisLeftY() const { return SDL_CONTROLLER_AXIS_LEFTY; } + int axisRightX() const { return SDL_CONTROLLER_AXIS_RIGHTX; } + int axisRightY() const { return SDL_CONTROLLER_AXIS_RIGHTY; } + int axisTriggerLeft() const { return SDL_CONTROLLER_AXIS_TRIGGERLEFT; } + int axisTriggerRight() const { return SDL_CONTROLLER_AXIS_TRIGGERRIGHT; } + int axisMax() const { return SDL_CONTROLLER_AXIS_MAX; } + + int buttonInvalid() const { return SDL_CONTROLLER_BUTTON_INVALID; } + int buttonFaceBottom() const { return SDL_CONTROLLER_BUTTON_A; } + int buttonFaceRight() const { return SDL_CONTROLLER_BUTTON_B; } + int buttonFaceLeft() const { return SDL_CONTROLLER_BUTTON_X; } + int buttonFaceTop() const { return SDL_CONTROLLER_BUTTON_Y; } + int buttonBack() const { return SDL_CONTROLLER_BUTTON_BACK; } + int buttonGuide() const { return SDL_CONTROLLER_BUTTON_GUIDE; } + int buttonStart() const { return SDL_CONTROLLER_BUTTON_START; } + int buttonLeftStick() const { return SDL_CONTROLLER_BUTTON_LEFTSTICK; } + int buttonRightStick() const { return SDL_CONTROLLER_BUTTON_RIGHTSTICK; } + int buttonLeftShoulder() const { return SDL_CONTROLLER_BUTTON_LEFTSHOULDER; } + int buttonRightShoulder() const { return SDL_CONTROLLER_BUTTON_RIGHTSHOULDER; } + int buttonDpadUp() const { return SDL_CONTROLLER_BUTTON_DPAD_UP; } + int buttonDpadDown() const { return SDL_CONTROLLER_BUTTON_DPAD_DOWN; } + int buttonDpadLeft() const { return SDL_CONTROLLER_BUTTON_DPAD_LEFT; } + int buttonDpadRight() const { return SDL_CONTROLLER_BUTTON_DPAD_RIGHT; } + int buttonMax() const { return SDL_CONTROLLER_BUTTON_MAX; } + + int buttonPressed() const { return SDL_PRESSED; } + int buttonRelease() const { return SDL_RELEASED; } + SDL_Joystick* openSDLJoystickWithName(const QString& name); #endif JoystickScriptingInterface(); ~JoystickScriptingInterface(); - QMap _openJoysticks; - QStringList _availableDeviceNames; +#ifdef HAVE_SDL2 + QMap _openJoysticks; +#endif bool _isInitialized; }; From 1c2a971638d11fb82ab125cf900fbda5ad91db94 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 10 Oct 2014 17:03:25 -0700 Subject: [PATCH 24/43] Update gamepad.js to use new Joysticks interface --- examples/gamepad.js | 97 +++++++++++++++------------------------------ 1 file changed, 33 insertions(+), 64 deletions(-) diff --git a/examples/gamepad.js b/examples/gamepad.js index 4ec0309511..b4c2758edd 100644 --- a/examples/gamepad.js +++ b/examples/gamepad.js @@ -9,72 +9,23 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -// TODO Update to work with any controller that is plugged in. -var CONTROLLER_NAMES = [ - "Wireless 360 Controller", - "Controller (XBOX 360 For Windows)", - "Controller", // Wired 360 controller -] +var gamepads = {}; -for (var i = 0; i < CONTROLLER_NAMES.length; i++) { - gamepad = Joysticks.joystickWithName(CONTROLLER_NAMES[i]); - if (gamepad) { - print("Found controller: " + CONTROLLER_NAMES[i]); - break; - } -} +// Function -> button/axis mappings +var AXIS_STRAFE = Joysticks.AXIS_LEFT_X; +var AXIS_FORWARD = Joysticks.AXIS_LEFT_Y; +var AXIS_ROTATE = Joysticks.AXIS_RIGHT_X; -if (!gamepad) { - print("No gamepad found."); -} +var BUTTON_TURN_AROUND = Joysticks.BUTTON_RIGHT_STICK; -// Controller axis/button mappings -var GAMEPAD = { - AXES: { - LEFT_JOYSTICK_X: 0, - LEFT_JOYSTICK_Y: 1, +var BUTTON_FLY_UP = Joysticks.BUTTON_RIGHT_SHOULDER; +var BUTTON_FLY_DOWN = Joysticks.BUTTON_LEFT_SHOULDER; +var BUTTON_WARP = Joysticks.BUTTON_FACE_BOTTOM; - RIGHT_JOYSTICK_X: 2, - RIGHT_JOYSTICK_Y: 3, - - LEFT_TRIGGER: 4, - RIGHT_TRIGGER: 5, - }, - BUTTONS: { - DPAD_UP: 0, - DPAD_DOWN: 1, - DPAD_LEFT: 2, - DPAD_RIGHT: 3, - - LEFT_JOYSTICK: 6, - RIGHT_JOYSTICK: 7, - - LEFT_BUMPER: 8, - RIGHT_BUMPER: 9, - - // Face buttons, ABXY on an XBOX controller - FACE_BOTTOM: 11, - FACE_RIGHT: 12, - FACE_LEFT: 13, - FACE_TOP: 14, - } -} - -// Button/axis mappings -var AXIS_STRAFE = GAMEPAD.AXES.LEFT_JOYSTICK_X; -var AXIS_FORWARD = GAMEPAD.AXES.LEFT_JOYSTICK_Y; -var AXIS_ROTATE = GAMEPAD.AXES.RIGHT_JOYSTICK_X; - -var BUTTON_TURN_AROUND = GAMEPAD.BUTTONS.RIGHT_JOYSTICK; - -var BUTTON_FLY_UP = GAMEPAD.BUTTONS.RIGHT_BUMPER; -var BUTTON_FLY_DOWN = GAMEPAD.BUTTONS.LEFT_BUMPER -var BUTTON_WARP = GAMEPAD.BUTTONS.FACE_BOTTOM; - -var BUTTON_WARP_FORWARD = GAMEPAD.BUTTONS.DPAD_UP; -var BUTTON_WARP_BACKWARD = GAMEPAD.BUTTONS.DPAD_DOWN; -var BUTTON_WARP_LEFT = GAMEPAD.BUTTONS.DPAD_LEFT; -var BUTTON_WARP_RIGHT = GAMEPAD.BUTTONS.DPAD_RIGHT; +var BUTTON_WARP_FORWARD = Joysticks.BUTTON_DPAD_UP; +var BUTTON_WARP_BACKWARD = Joysticks.BUTTON_DPAD_DOWN; +var BUTTON_WARP_LEFT = Joysticks.BUTTON_DPAD_LEFT; +var BUTTON_WARP_RIGHT = Joysticks.BUTTON_DPAD_RIGHT; // Distance in meters to warp via BUTTON_WARP_* var WARP_DISTANCE = 1; @@ -272,9 +223,27 @@ function update(dt) { updateWarp(); } -if (gamepad) { +function addJoystick(gamepad) { gamepad.axisValueChanged.connect(reportAxisValue); gamepad.buttonStateChanged.connect(reportButtonValue); - Script.update.connect(update); + gamepads[gamepad.instanceId] = gamepad; + + print("Added gamepad: " + gamepad.name + " (" + gamepad.instanceId + ")"); } + +function removeJoystick(gamepad) { + delete gamepads[gamepad.instanceId] + + print("Removed gamepad: " + gamepad.name + " (" + gamepad.instanceId + ")"); +} + +var allJoysticks = Joysticks.getAllJoysticks(); +for (var i = 0; i < allJoysticks.length; i++) { + addJoystick(allJoysticks[i]); +} + +Joysticks.joystickAdded.connect(addJoystick); +Joysticks.joystickRemoved.connect(removeJoystick); + +Script.update.connect(update); From 82a9429414ffa223f7e5ff6a86bb007b3ce0d511 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 10 Oct 2014 17:10:27 -0700 Subject: [PATCH 25/43] add boundingBox.dimensions to entity properties --- libraries/entities/src/EntityItemProperties.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 2690bcd45b..90f56e36b9 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -179,9 +179,11 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons QScriptValue bottomRightNear = vec3toScriptValue(engine, aaBox.getCorner()); QScriptValue topFarLeft = vec3toScriptValue(engine, aaBox.calcTopFarLeft()); QScriptValue center = vec3toScriptValue(engine, aaBox.calcCenter()); + QScriptValue boundingBoxDimensions = vec3toScriptValue(engine, aaBox.getDimensions()); boundingBox.setProperty("brn", bottomRightNear); boundingBox.setProperty("tfl", topFarLeft); boundingBox.setProperty("center", center); + boundingBox.setProperty("dimensions", boundingBoxDimensions); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(boundingBox, boundingBox); // gettable, but not settable return properties; From cdafba603d21e20e1503e45fb23d87ba6f3075a8 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 10 Oct 2014 17:11:27 -0700 Subject: [PATCH 26/43] use axis aligned bounding box for highlight and selection box instead of non-axis aligned box --- examples/libraries/entitySelectionTool.js | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index b00876c969..bbcb86eb2a 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -393,14 +393,8 @@ SelectionDisplay = (function () { that.highlightSelectable = function(entityID) { var properties = Entities.getEntityProperties(entityID); - var center = { x: properties.position.x, y: properties.position.y, z: properties.position.z }; - Overlays.editOverlay(highlightBox, - { - visible: true, - position: center, - dimensions: properties.dimensions, - rotation: properties.rotation, - }); + Overlays.editOverlay(highlightBox, { visible: true, position: properties.boundingBox.center, + dimensions: properties.boundingBox.dimensions }); }; that.unhighlightSelectable = function(entityID) { @@ -642,8 +636,8 @@ SelectionDisplay = (function () { Overlays.editOverlay(highlightBox, { visible: false }); - Overlays.editOverlay(selectionBox, { visible: selectionBoxVisible, position: objectCenter, dimensions: properties.dimensions, - rotation: properties.rotation,}); + Overlays.editOverlay(selectionBox, { visible: selectionBoxVisible, position: properties.boundingBox.center, + dimensions: properties.boundingBox.dimensions }); Overlays.editOverlay(grabberMoveUp, { visible: translateHandlesVisible, position: { x: boundsCenter.x, y: top + grabberMoveUpOffset, z: boundsCenter.z } }); From 60da0f1567f1df85bae60591a03e0a53bcf3c32f Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 10 Oct 2014 17:18:52 -0700 Subject: [PATCH 27/43] Allow drawing cursor on dual contour surface, wired up material paint tool. --- .../shaders/metavoxel_voxel_cursor.frag | 32 ++++++ .../shaders/metavoxel_voxel_cursor.vert | 25 +++++ interface/src/MetavoxelSystem.cpp | 61 ++++++++-- interface/src/MetavoxelSystem.h | 6 + interface/src/ui/MetavoxelEditor.cpp | 76 +++++++++++-- interface/src/ui/MetavoxelEditor.h | 21 ++++ .../metavoxels/src/MetavoxelMessages.cpp | 105 ++++++++++++++++++ libraries/metavoxels/src/MetavoxelMessages.h | 19 ++++ 8 files changed, 326 insertions(+), 19 deletions(-) create mode 100644 interface/resources/shaders/metavoxel_voxel_cursor.frag create mode 100644 interface/resources/shaders/metavoxel_voxel_cursor.vert diff --git a/interface/resources/shaders/metavoxel_voxel_cursor.frag b/interface/resources/shaders/metavoxel_voxel_cursor.frag new file mode 100644 index 0000000000..3a803ea309 --- /dev/null +++ b/interface/resources/shaders/metavoxel_voxel_cursor.frag @@ -0,0 +1,32 @@ +#version 120 + +// +// metavoxel_voxel_base.frag +// fragment shader +// +// Created by Andrzej Kapolka on 10/10/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// the inner radius of the outline, squared +const float SQUARED_OUTLINE_INNER_RADIUS = 0.81; + +// the outer radius of the outline, squared +const float SQUARED_OUTLINE_OUTER_RADIUS = 1.0; + +// the inner radius of the inset, squared +const float SQUARED_INSET_INNER_RADIUS = 0.855625; + +// the outer radius of the inset, squared +const float SQUARED_INSET_OUTER_RADIUS = 0.950625; + +void main(void) { + // use the distance to compute the ring color, then multiply it by the varying color + float squaredDistance = dot(gl_TexCoord[0].str, gl_TexCoord[0].str); + float alpha = step(SQUARED_OUTLINE_INNER_RADIUS, squaredDistance) * step(squaredDistance, SQUARED_OUTLINE_OUTER_RADIUS); + float white = step(SQUARED_INSET_INNER_RADIUS, squaredDistance) * step(squaredDistance, SQUARED_INSET_OUTER_RADIUS); + gl_FragColor = gl_Color * vec4(white, white, white, alpha); +} diff --git a/interface/resources/shaders/metavoxel_voxel_cursor.vert b/interface/resources/shaders/metavoxel_voxel_cursor.vert new file mode 100644 index 0000000000..586eef275a --- /dev/null +++ b/interface/resources/shaders/metavoxel_voxel_cursor.vert @@ -0,0 +1,25 @@ +#version 120 + +// +// metavoxel_voxel_cursor.vert +// vertex shader +// +// Created by Andrzej Kapolka on 10/10/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +void main(void) { + // compute the view space coordinates + vec4 viewPosition = gl_ModelViewMatrix * gl_Vertex; + gl_Position = gl_ProjectionMatrix * viewPosition; + + // generate the texture coordinates from the view position + gl_TexCoord[0] = vec4(dot(viewPosition, gl_EyePlaneS[4]), dot(viewPosition, gl_EyePlaneT[4]), + dot(viewPosition, gl_EyePlaneR[4]), 1.0); + + // copy the color for interpolation + gl_FrontColor = gl_Color; +} diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 19a9a7ce89..24a1026ef4 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -454,10 +454,10 @@ float MetavoxelSystem::getHeightfieldHeight(const glm::vec3& location) { return visitor.height; } -class HeightfieldCursorRenderVisitor : public MetavoxelVisitor { +class CursorRenderVisitor : public MetavoxelVisitor { public: - HeightfieldCursorRenderVisitor(const Box& bounds); + CursorRenderVisitor(const AttributePointer& attribute, const Box& bounds); virtual int visit(MetavoxelInfo& info); @@ -466,13 +466,12 @@ private: Box _bounds; }; -HeightfieldCursorRenderVisitor::HeightfieldCursorRenderVisitor(const Box& bounds) : - MetavoxelVisitor(QVector() << - Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute()), +CursorRenderVisitor::CursorRenderVisitor(const AttributePointer& attribute, const Box& bounds) : + MetavoxelVisitor(QVector() << attribute), _bounds(bounds) { } -int HeightfieldCursorRenderVisitor::visit(MetavoxelInfo& info) { +int CursorRenderVisitor::visit(MetavoxelInfo& info) { if (!info.getBounds().intersects(_bounds)) { return STOP_RECURSION; } @@ -508,7 +507,8 @@ void MetavoxelSystem::renderHeightfieldCursor(const glm::vec3& position, float r glActiveTexture(GL_TEXTURE0); glm::vec3 extents(radius, radius, radius); - HeightfieldCursorRenderVisitor visitor(Box(position - extents, position + extents)); + CursorRenderVisitor visitor(Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), + Box(position - extents, position + extents)); guideToAugmented(visitor); DefaultMetavoxelRendererImplementation::getHeightfieldCursorProgram().release(); @@ -521,6 +521,42 @@ void MetavoxelSystem::renderHeightfieldCursor(const glm::vec3& position, float r glDepthFunc(GL_LESS); } +void MetavoxelSystem::renderVoxelCursor(const glm::vec3& position, float radius) { + glDepthFunc(GL_LEQUAL); + glEnable(GL_CULL_FACE); + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.0f, -1.0f); + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + + glEnableClientState(GL_VERTEX_ARRAY); + + DefaultMetavoxelRendererImplementation::getVoxelCursorProgram().bind(); + + glActiveTexture(GL_TEXTURE4); + float scale = 1.0f / radius; + glm::vec4 sCoefficients(scale, 0.0f, 0.0f, -scale * position.x); + glm::vec4 tCoefficients(0.0f, scale, 0.0f, -scale * position.y); + glm::vec4 rCoefficients(0.0f, 0.0f, scale, -scale * position.z); + glTexGenfv(GL_S, GL_EYE_PLANE, (const GLfloat*)&sCoefficients); + glTexGenfv(GL_T, GL_EYE_PLANE, (const GLfloat*)&tCoefficients); + glTexGenfv(GL_R, GL_EYE_PLANE, (const GLfloat*)&rCoefficients); + glActiveTexture(GL_TEXTURE0); + + glm::vec3 extents(radius, radius, radius); + CursorRenderVisitor visitor(Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute(), + Box(position - extents, position + extents)); + guideToAugmented(visitor); + + DefaultMetavoxelRendererImplementation::getVoxelCursorProgram().release(); + + glDisableClientState(GL_VERTEX_ARRAY); + + glDisable(GL_POLYGON_OFFSET_FILL); + glDisable(GL_CULL_FACE); + glDepthFunc(GL_LESS); +} + void MetavoxelSystem::deleteTextures(int heightID, int colorID, int textureID) { glDeleteTextures(1, (GLuint*)&heightID); glDeleteTextures(1, (GLuint*)&colorID); @@ -1170,7 +1206,7 @@ void VoxelBuffer::render(bool cursor) { glDrawRangeElements(GL_QUADS, 0, _vertexCount - 1, _indexCount, GL_UNSIGNED_INT, 0); - if (!_materials.isEmpty()) { + if (!(_materials.isEmpty() || cursor)) { Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false); glDepthFunc(GL_LEQUAL); @@ -1252,7 +1288,7 @@ void VoxelBuffer::render(bool cursor) { _vertexBuffer.release(); _indexBuffer.release(); - if (_hermiteCount > 0 && Menu::getInstance()->isOptionChecked(MenuOption::DisplayHermiteData)) { + if (_hermiteCount > 0 && Menu::getInstance()->isOptionChecked(MenuOption::DisplayHermiteData) && !cursor) { if (!_hermiteBuffer.isCreated()) { _hermiteBuffer.create(); _hermiteBuffer.bind(); @@ -1348,6 +1384,12 @@ void DefaultMetavoxelRendererImplementation::init() { _baseVoxelProgram.link(); loadSplatProgram("voxel", _splatVoxelProgram, _splatVoxelLocations); + + _voxelCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + + "shaders/metavoxel_voxel_cursor.vert"); + _voxelCursorProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + + "shaders/metavoxel_voxel_cursor.frag"); + _voxelCursorProgram.link(); } } @@ -2577,6 +2619,7 @@ ProgramObject DefaultMetavoxelRendererImplementation::_heightfieldCursorProgram; ProgramObject DefaultMetavoxelRendererImplementation::_baseVoxelProgram; ProgramObject DefaultMetavoxelRendererImplementation::_splatVoxelProgram; DefaultMetavoxelRendererImplementation::SplatLocations DefaultMetavoxelRendererImplementation::_splatVoxelLocations; +ProgramObject DefaultMetavoxelRendererImplementation::_voxelCursorProgram; static void enableClipPlane(GLenum plane, float x, float y, float z, float w) { GLdouble coefficients[] = { x, y, z, w }; diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h index daa1bd6ca2..f479ba5e50 100644 --- a/interface/src/MetavoxelSystem.h +++ b/interface/src/MetavoxelSystem.h @@ -46,6 +46,8 @@ public: void renderHeightfieldCursor(const glm::vec3& position, float radius); + void renderVoxelCursor(const glm::vec3& position, float radius); + bool findFirstRayHeightfieldIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance); bool findFirstRayVoxelIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance); @@ -321,6 +323,8 @@ public: static ProgramObject& getSplatVoxelProgram() { return _splatVoxelProgram; } static const SplatLocations& getSplatVoxelLocations() { return _splatVoxelLocations; } + static ProgramObject& getVoxelCursorProgram() { return _voxelCursorProgram; } + Q_INVOKABLE DefaultMetavoxelRendererImplementation(); virtual void augment(MetavoxelData& data, const MetavoxelData& previous, MetavoxelInfo& info, const MetavoxelLOD& lod); @@ -354,6 +358,8 @@ private: static ProgramObject _baseVoxelProgram; static ProgramObject _splatVoxelProgram; static SplatLocations _splatVoxelLocations; + + static ProgramObject _voxelCursorProgram; }; /// Base class for spanner renderers; provides clipping. diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index 6dfe3d77ed..ee7cf63789 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -1529,6 +1529,15 @@ void VoxelMaterialSpannerTool::textureLoaded() { VoxelBrushTool::VoxelBrushTool(MetavoxelEditor* editor, const QString& name) : MetavoxelTool(editor, name, false, true) { + + QWidget* widget = new QWidget(); + widget->setLayout(_form = new QFormLayout()); + layout()->addWidget(widget); + + _form->addRow("Radius:", _radius = new QDoubleSpinBox()); + _radius->setSingleStep(0.01); + _radius->setMaximum(FLT_MAX); + _radius->setValue(0.25); } bool VoxelBrushTool::appliesTo(const AttributePointer& attribute) const { @@ -1548,24 +1557,71 @@ void VoxelBrushTool::render() { if (!Application::getInstance()->getMetavoxels()->findFirstRayVoxelIntersection(origin, direction, distance)) { return; } - _position = origin + distance * direction; - - glColor4f(1.0f, 0.0f, 0.0f, 1.0f); - - glPushMatrix(); - glTranslatef(_position.x, _position.y, _position.z); - - Application::getInstance()->getGeometryCache()->renderSphere(0.1f, 16, 16); - - glPopMatrix(); + Application::getInstance()->getMetavoxels()->renderVoxelCursor( + _position = origin + distance * direction, _radius->value()); } bool VoxelBrushTool::eventFilter(QObject* watched, QEvent* event) { + if (event->type() == QEvent::Wheel) { + float angle = static_cast(event)->angleDelta().y(); + const float ANGLE_SCALE = 1.0f / 1000.0f; + _radius->setValue(_radius->value() * glm::pow(2.0f, angle * ANGLE_SCALE)); + return true; + + } else if (event->type() == QEvent::MouseButtonPress) { + MetavoxelEditMessage message = { createEdit(static_cast(event)->button() == Qt::RightButton) }; + Application::getInstance()->getMetavoxels()->applyEdit(message, true); + return true; + } return false; } VoxelMaterialBrushTool::VoxelMaterialBrushTool(MetavoxelEditor* editor) : VoxelBrushTool(editor, "Material Brush") { + + _form->addRow("Color:", _color = new QColorEditor(this)); + connect(_color, &QColorEditor::colorChanged, this, &VoxelMaterialBrushTool::clearTexture); + _form->addRow(_materialEditor = new SharedObjectEditor(&MaterialObject::staticMetaObject, false)); + connect(_materialEditor, &SharedObjectEditor::objectChanged, this, &VoxelMaterialBrushTool::updateTexture); } +QVariant VoxelMaterialBrushTool::createEdit(bool alternate) { + if (alternate) { + return QVariant::fromValue(PaintVoxelMaterialEdit(_position, _radius->value(), SharedObjectPointer(), QColor())); + } else { + SharedObjectPointer material = _materialEditor->getObject(); + if (static_cast(material.data())->getDiffuse().isValid()) { + _materialEditor->detachObject(); + } else { + material = SharedObjectPointer(); + } + return QVariant::fromValue(PaintVoxelMaterialEdit(_position, _radius->value(), material, _color->getColor())); + } +} +void VoxelMaterialBrushTool::clearTexture() { + _materialEditor->setObject(new MaterialObject()); +} + +void VoxelMaterialBrushTool::updateTexture() { + if (_texture) { + _texture->disconnect(this); + } + MaterialObject* material = static_cast(_materialEditor->getObject().data()); + if (!material->getDiffuse().isValid()) { + _texture.clear(); + return; + } + _texture = Application::getInstance()->getTextureCache()->getTexture(material->getDiffuse(), SPLAT_TEXTURE); + if (_texture) { + if (_texture->isLoaded()) { + textureLoaded(); + } else { + connect(_texture.data(), &Resource::loaded, this, &VoxelMaterialBrushTool::textureLoaded); + } + } +} + +void VoxelMaterialBrushTool::textureLoaded() { + _color->setColor(_texture->getAverageColor()); +} diff --git a/interface/src/ui/MetavoxelEditor.h b/interface/src/ui/MetavoxelEditor.h index 725eac87f7..debe45ea2f 100644 --- a/interface/src/ui/MetavoxelEditor.h +++ b/interface/src/ui/MetavoxelEditor.h @@ -485,6 +485,11 @@ public: protected: + virtual QVariant createEdit(bool alternate) = 0; + + QFormLayout* _form; + QDoubleSpinBox* _radius; + glm::vec3 _position; }; @@ -495,6 +500,22 @@ class VoxelMaterialBrushTool : public VoxelBrushTool { public: VoxelMaterialBrushTool(MetavoxelEditor* editor); + +protected: + + virtual QVariant createEdit(bool alternate); + +private slots: + + void clearTexture(); + void updateTexture(); + void textureLoaded(); + +private: + + QColorEditor* _color; + SharedObjectEditor* _materialEditor; + QSharedPointer _texture; }; #endif // hifi_MetavoxelEditor_h diff --git a/libraries/metavoxels/src/MetavoxelMessages.cpp b/libraries/metavoxels/src/MetavoxelMessages.cpp index 1a18079257..29fbe182d3 100644 --- a/libraries/metavoxels/src/MetavoxelMessages.cpp +++ b/libraries/metavoxels/src/MetavoxelMessages.cpp @@ -848,3 +848,108 @@ void VoxelMaterialSpannerEdit::apply(MetavoxelData& data, const WeakSharedObject VoxelMaterialSpannerEditVisitor visitor(spanner, material, averageColor); data.guide(visitor); } + +PaintVoxelMaterialEdit::PaintVoxelMaterialEdit(const glm::vec3& position, float radius, + const SharedObjectPointer& material, const QColor& averageColor) : + position(position), + radius(radius), + material(material), + averageColor(averageColor) { +} + +class PaintVoxelMaterialEditVisitor : public MetavoxelVisitor { +public: + + PaintVoxelMaterialEditVisitor(const glm::vec3& position, float radius, + const SharedObjectPointer& material, const QColor& color); + + virtual int visit(MetavoxelInfo& info); + +private: + + glm::vec3 _position; + float _radius; + SharedObjectPointer _material; + QColor _color; + Box _bounds; +}; + +PaintVoxelMaterialEditVisitor::PaintVoxelMaterialEditVisitor(const glm::vec3& position, float radius, + const SharedObjectPointer& material, const QColor& color) : + MetavoxelVisitor(QVector() << AttributeRegistry::getInstance()->getVoxelColorAttribute() << + AttributeRegistry::getInstance()->getVoxelMaterialAttribute(), QVector() << + AttributeRegistry::getInstance()->getVoxelColorAttribute() << + AttributeRegistry::getInstance()->getVoxelMaterialAttribute()), + _position(position), + _radius(radius), + _material(material), + _color(color) { + + glm::vec3 extents(_radius, _radius, _radius); + _bounds = Box(_position - extents, _position + extents); +} + +int PaintVoxelMaterialEditVisitor::visit(MetavoxelInfo& info) { + if (!info.getBounds().intersects(_bounds)) { + return STOP_RECURSION; + } + if (!info.isLeaf) { + return DEFAULT_ORDER; + } + VoxelColorDataPointer colorPointer = info.inputValues.at(0).getInlineValue(); + VoxelMaterialDataPointer materialPointer = info.inputValues.at(1).getInlineValue(); + if (!(colorPointer && materialPointer && colorPointer->getSize() == materialPointer->getSize())) { + return STOP_RECURSION; + } + QVector colorContents = colorPointer->getContents(); + QByteArray materialContents = materialPointer->getContents(); + QVector materials = materialPointer->getMaterials(); + + Box overlap = info.getBounds().getIntersection(_bounds); + int size = colorPointer->getSize(); + int area = size * size; + float scale = (size - 1.0f) / info.size; + overlap.minimum = (overlap.minimum - info.minimum) * scale; + overlap.maximum = (overlap.maximum - info.minimum) * scale; + int minX = glm::ceil(overlap.minimum.x); + int minY = glm::ceil(overlap.minimum.y); + int minZ = glm::ceil(overlap.minimum.z); + int sizeX = (int)overlap.maximum.x - minX + 1; + int sizeY = (int)overlap.maximum.y - minY + 1; + int sizeZ = (int)overlap.maximum.z - minZ + 1; + + QRgb rgb = _color.rgba(); + float step = 1.0f / scale; + glm::vec3 position(0.0f, 0.0f, info.minimum.z + minZ * step); + uchar materialIndex = getMaterialIndex(_material, materials, materialContents); + QRgb* colorData = colorContents.data(); + uchar* materialData = (uchar*)materialContents.data(); + for (int destZ = minZ * area + minY * size + minX, endZ = destZ + sizeZ * area; destZ != endZ; + destZ += area, position.z += step) { + position.y = info.minimum.y + minY * step; + for (int destY = destZ, endY = destY + sizeY * size; destY != endY; destY += size, position.y += step) { + position.x = info.minimum.x + minX * step; + for (int destX = destY, endX = destX + sizeX; destX != endX; destX++, position.x += step) { + QRgb& color = colorData[destX]; + if (qAlpha(color) != 0 && glm::distance(position, _position) <= _radius) { + color = rgb; + materialData[destX] = materialIndex; + } + } + } + } + VoxelColorDataPointer newColorPointer(new VoxelColorData(colorContents, size)); + info.outputValues[0] = AttributeValue(info.inputValues.at(0).getAttribute(), + encodeInline(newColorPointer)); + + clearUnusedMaterials(materials, materialContents); + VoxelMaterialDataPointer newMaterialPointer(new VoxelMaterialData(materialContents, size, materials)); + info.outputValues[1] = AttributeValue(_inputs.at(1), encodeInline(newMaterialPointer)); + + return STOP_RECURSION; +} + +void PaintVoxelMaterialEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const { + PaintVoxelMaterialEditVisitor visitor(position, radius, material, averageColor); + data.guide(visitor); +} diff --git a/libraries/metavoxels/src/MetavoxelMessages.h b/libraries/metavoxels/src/MetavoxelMessages.h index bf59a1e691..0ac0bf59ec 100644 --- a/libraries/metavoxels/src/MetavoxelMessages.h +++ b/libraries/metavoxels/src/MetavoxelMessages.h @@ -261,4 +261,23 @@ public: DECLARE_STREAMABLE_METATYPE(VoxelMaterialSpannerEdit) +/// An edit that sets a region of a voxel material. +class PaintVoxelMaterialEdit : public MetavoxelEdit { + STREAMABLE + +public: + + STREAM glm::vec3 position; + STREAM float radius; + STREAM SharedObjectPointer material; + STREAM QColor averageColor; + + PaintVoxelMaterialEdit(const glm::vec3& position = glm::vec3(), float radius = 0.0f, + const SharedObjectPointer& material = SharedObjectPointer(), const QColor& averageColor = QColor()); + + virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const; +}; + +DECLARE_STREAMABLE_METATYPE(PaintVoxelMaterialEdit) + #endif // hifi_MetavoxelMessages_h From 1f63656a14d843655caebd0cd65e52e1a1a96be8 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 10 Oct 2014 17:25:25 -0700 Subject: [PATCH 28/43] Comment fix. --- interface/resources/shaders/metavoxel_voxel_cursor.frag | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/shaders/metavoxel_voxel_cursor.frag b/interface/resources/shaders/metavoxel_voxel_cursor.frag index 3a803ea309..bdc6fb6d4a 100644 --- a/interface/resources/shaders/metavoxel_voxel_cursor.frag +++ b/interface/resources/shaders/metavoxel_voxel_cursor.frag @@ -1,7 +1,7 @@ #version 120 // -// metavoxel_voxel_base.frag +// metavoxel_voxel_cursor.frag // fragment shader // // Created by Andrzej Kapolka on 10/10/14. From a24b5c24a9ba8c88429c3a2e67898398c7f6e0bc Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 10 Oct 2014 17:28:09 -0700 Subject: [PATCH 29/43] Update max axis value to reflect maximum negative value --- interface/src/devices/Joystick.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/devices/Joystick.cpp b/interface/src/devices/Joystick.cpp index b63d49eea2..e110027e1a 100644 --- a/interface/src/devices/Joystick.cpp +++ b/interface/src/devices/Joystick.cpp @@ -15,7 +15,7 @@ #include "Joystick.h" -const float MAX_AXIS = 32767.0f; +const float MAX_AXIS = 32768.0f; #ifdef HAVE_SDL2 From 1d4d36444f8d0f9f7238cb3be551cae3d7e105a1 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 10 Oct 2014 17:34:16 -0700 Subject: [PATCH 30/43] Bumped the metavoxel version number. --- libraries/networking/src/PacketHeaders.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index 069b3f000d..eddd63ca7a 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -85,7 +85,7 @@ PacketVersion versionForPacketType(PacketType type) { case PacketTypeAudioStreamStats: return 1; case PacketTypeMetavoxelData: - return 5; + return 6; case PacketTypeVoxelData: return VERSION_VOXELS_HAS_FILE_BREAKS; default: From d1c6aef953aa72d400c0be49c13f143416f8f7cd Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 10 Oct 2014 17:36:21 -0700 Subject: [PATCH 31/43] Fixed my swizzle! --- interface/resources/shaders/metavoxel_voxel_cursor.frag | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/shaders/metavoxel_voxel_cursor.frag b/interface/resources/shaders/metavoxel_voxel_cursor.frag index bdc6fb6d4a..88c6df6618 100644 --- a/interface/resources/shaders/metavoxel_voxel_cursor.frag +++ b/interface/resources/shaders/metavoxel_voxel_cursor.frag @@ -25,7 +25,7 @@ const float SQUARED_INSET_OUTER_RADIUS = 0.950625; void main(void) { // use the distance to compute the ring color, then multiply it by the varying color - float squaredDistance = dot(gl_TexCoord[0].str, gl_TexCoord[0].str); + float squaredDistance = dot(gl_TexCoord[0].stp, gl_TexCoord[0].stp); float alpha = step(SQUARED_OUTLINE_INNER_RADIUS, squaredDistance) * step(squaredDistance, SQUARED_OUTLINE_OUTER_RADIUS); float white = step(SQUARED_INSET_INNER_RADIUS, squaredDistance) * step(squaredDistance, SQUARED_INSET_OUTER_RADIUS); gl_FragColor = gl_Color * vec4(white, white, white, alpha); From 42479b1ae23ed315f44ce3d28fde749dbf7e707a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 10 Oct 2014 18:03:08 -0700 Subject: [PATCH 32/43] Add joystickWithName for PrioVR --- .../scripting/JoystickScriptingInterface.cpp | 25 ++++++++++--------- .../scripting/JoystickScriptingInterface.h | 15 ++++++----- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/interface/src/scripting/JoystickScriptingInterface.cpp b/interface/src/scripting/JoystickScriptingInterface.cpp index 3f0371e1cd..ced063c8fe 100644 --- a/interface/src/scripting/JoystickScriptingInterface.cpp +++ b/interface/src/scripting/JoystickScriptingInterface.cpp @@ -78,6 +78,19 @@ const QObjectList JoystickScriptingInterface::getAllJoysticks() const { return objectList; } +Joystick* JoystickScriptingInterface::joystickWithName(const QString& name) { +#ifdef HAVE_SDL2 + QMap::iterator iter = _openJoysticks.begin(); + while (iter != _openJoysticks.end()) { + if (iter.value()->getName() == name) { + return iter.value(); + } + iter++; + } +#endif + return NULL; +} + void JoystickScriptingInterface::update() { #ifdef HAVE_SDL2 if (_isInitialized) { @@ -111,15 +124,3 @@ void JoystickScriptingInterface::update() { } #endif } - -#ifdef HAVE_SDL2 - -SDL_Joystick* JoystickScriptingInterface::openSDLJoystickWithName(const QString& name) { - // we haven't opened a joystick with this name yet - enumerate our SDL devices and see if it exists - int joystickCount = SDL_NumJoysticks(); - - - return NULL; -} - -#endif diff --git a/interface/src/scripting/JoystickScriptingInterface.h b/interface/src/scripting/JoystickScriptingInterface.h index 37546a5a85..c9a68d24b1 100644 --- a/interface/src/scripting/JoystickScriptingInterface.h +++ b/interface/src/scripting/JoystickScriptingInterface.h @@ -24,7 +24,7 @@ /// Handles joystick input through SDL. class JoystickScriptingInterface : public QObject { Q_OBJECT - + #ifdef HAVE_SDL2 Q_PROPERTY(int AXIS_INVALID READ axisInvalid) Q_PROPERTY(int AXIS_LEFT_X READ axisLeftX) @@ -59,16 +59,17 @@ class JoystickScriptingInterface : public QObject { public: static JoystickScriptingInterface& getInstance(); - + void update(); - + public slots: + Joystick* joystickWithName(const QString& name); const QObjectList getAllJoysticks() const; signals: void joystickAdded(Joystick* joystick); void joystickRemoved(Joystick* joystick); - + private: #ifdef HAVE_SDL2 int axisInvalid() const { return SDL_CONTROLLER_AXIS_INVALID; } @@ -100,13 +101,11 @@ private: int buttonPressed() const { return SDL_PRESSED; } int buttonRelease() const { return SDL_RELEASED; } - - SDL_Joystick* openSDLJoystickWithName(const QString& name); #endif - + JoystickScriptingInterface(); ~JoystickScriptingInterface(); - + #ifdef HAVE_SDL2 QMap _openJoysticks; #endif From dfff16d9e8e1c15ef59b797a4184de5a0754a68a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 10 Oct 2014 21:12:28 -0700 Subject: [PATCH 33/43] make sure to not select other entities when clicking on a grab handle of a selected entity --- examples/libraries/entitySelectionTool.js | 6 +++++- examples/newEditEntities.js | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index bbcb86eb2a..7c18b791a1 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -1749,6 +1749,7 @@ SelectionDisplay = (function () { }; that.mousePressEvent = function(event) { + var somethingClicked = false; var pickRay = Camera.computePickRay(event.x, event.y); @@ -2049,6 +2050,8 @@ SelectionDisplay = (function () { Overlays.editOverlay(yawHandle, { ignoreRayIntersection: false }); Overlays.editOverlay(pitchHandle, { ignoreRayIntersection: false }); Overlays.editOverlay(rollHandle, { ignoreRayIntersection: false }); + + return somethingClicked; }; that.mouseMoveEvent = function(event) { @@ -2150,7 +2153,8 @@ SelectionDisplay = (function () { }; - Controller.mousePressEvent.connect(that.mousePressEvent); + // NOTE: mousePressEvent from the main script should call us., so we don't + // hook the Controller.mousePressEvent.connect(that.mousePressEvent); ourselves. Controller.mouseMoveEvent.connect(that.mouseMoveEvent); Controller.mouseReleaseEvent.connect(that.mouseReleaseEvent); diff --git a/examples/newEditEntities.js b/examples/newEditEntities.js index b753537631..1fb21caacc 100644 --- a/examples/newEditEntities.js +++ b/examples/newEditEntities.js @@ -341,7 +341,7 @@ function mousePressEvent(event) { entitySelected = false; var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); - if (toolBar.mousePressEvent(event) || progressDialog.mousePressEvent(event)) { + if (toolBar.mousePressEvent(event) || progressDialog.mousePressEvent(event) || selectionDisplay.mousePressEvent(event)) { // Event handled; do nothing. return; } else { From f21ff76a38f1d15adacb3b898b2f13ad495a1b7a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 10 Oct 2014 21:23:56 -0700 Subject: [PATCH 34/43] dont allow stretching below a minimum dimension --- examples/libraries/entitySelectionTool.js | 136 ++++++++++++++++++++++ 1 file changed, 136 insertions(+) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 7c18b791a1..43c7849ab3 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -16,6 +16,8 @@ Script.include("libraries/globals.js"); SelectionDisplay = (function () { var that = {}; + var MINIMUM_DIMENSION = 0.001; + var mode = "UNKNOWN"; var overlayNames = new Array(); var lastAvatarPosition = MyAvatar.position; @@ -883,6 +885,11 @@ SelectionDisplay = (function () { // dimensions changes by: (oldNEAR - newNEAR) var changeInDimensions = { x: 0, y: 0, z: (oldNEAR - newNEAR) }; var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); + + if (newDimensions.z < MINIMUM_DIMENSION) { + newDimensions.z = MINIMUM_DIMENSION; + } + var changeInPosition = { x: 0, y: 0, z: (oldNEAR - newNEAR) * -0.5 }; var newPosition = Vec3.sum(selectedEntityPropertiesOriginalPosition, changeInPosition); var wantDebug = false; @@ -928,6 +935,11 @@ SelectionDisplay = (function () { var newFAR = oldFAR + vector.z; var changeInDimensions = { x: 0, y: 0, z: (newFAR - oldFAR) }; var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); + + if (newDimensions.z < MINIMUM_DIMENSION) { + newDimensions.z = MINIMUM_DIMENSION; + } + var changeInPosition = { x: 0, y: 0, z: (newFAR - oldFAR) * 0.5 }; var newPosition = Vec3.sum(selectedEntityPropertiesOriginalPosition, changeInPosition); var wantDebug = false; @@ -973,6 +985,11 @@ SelectionDisplay = (function () { var newTOP = oldTOP + vector.y; var changeInDimensions = { x: 0, y: (newTOP - oldTOP), z: 0 }; var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); + + if (newDimensions.y < MINIMUM_DIMENSION) { + newDimensions.y = MINIMUM_DIMENSION; + } + var changeInPosition = { x: 0, y: (newTOP - oldTOP) * 0.5, z: 0 }; var newPosition = Vec3.sum(selectedEntityPropertiesOriginalPosition, changeInPosition); var wantDebug = false; @@ -1017,6 +1034,11 @@ SelectionDisplay = (function () { var newBOTTOM = oldBOTTOM + vector.y; var changeInDimensions = { x: 0, y: (oldBOTTOM - newBOTTOM), z: 0 }; var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); + + if (newDimensions.y < MINIMUM_DIMENSION) { + newDimensions.y = MINIMUM_DIMENSION; + } + var changeInPosition = { x: 0, y: (oldBOTTOM - newBOTTOM) * -0.5, z: 0 }; var newPosition = Vec3.sum(selectedEntityPropertiesOriginalPosition, changeInPosition); var wantDebug = false; @@ -1061,6 +1083,11 @@ SelectionDisplay = (function () { var newRIGHT = oldRIGHT + vector.x; var changeInDimensions = { x: (newRIGHT - oldRIGHT), y: 0 , z: 0 }; var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); + + if (newDimensions.x < MINIMUM_DIMENSION) { + newDimensions.x = MINIMUM_DIMENSION; + } + var changeInPosition = { x: (newRIGHT - oldRIGHT) * 0.5, y: 0, z: 0 }; var newPosition = Vec3.sum(selectedEntityPropertiesOriginalPosition, changeInPosition); var wantDebug = false; @@ -1105,6 +1132,11 @@ SelectionDisplay = (function () { var newLEFT = oldLEFT + vector.x; var changeInDimensions = { x: (oldLEFT - newLEFT), y: 0, z: 0 }; var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); + + if (newDimensions.x < MINIMUM_DIMENSION) { + newDimensions.x = MINIMUM_DIMENSION; + } + var changeInPosition = { x: (oldLEFT - newLEFT) * -0.5, y: 0, z: 0 }; var newPosition = Vec3.sum(selectedEntityPropertiesOriginalPosition, changeInPosition); var wantDebug = false; @@ -1157,6 +1189,19 @@ SelectionDisplay = (function () { var changeInDimensions = { x: (newRIGHT - oldRIGHT), y: (newBOTTOM - oldBOTTOM) , z: (newNEAR - oldNEAR) }; var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); + + if (newDimensions.x < MINIMUM_DIMENSION) { + newDimensions.x = MINIMUM_DIMENSION; + } + + if (newDimensions.y < MINIMUM_DIMENSION) { + newDimensions.y = MINIMUM_DIMENSION; + } + + if (newDimensions.z < MINIMUM_DIMENSION) { + newDimensions.z = MINIMUM_DIMENSION; + } + var changeInPosition = { x: (newRIGHT - oldRIGHT) * 0.5, y: (newBOTTOM - oldBOTTOM) * -0.5, z: (newNEAR - oldNEAR) * -0.5 }; @@ -1211,6 +1256,19 @@ SelectionDisplay = (function () { var changeInDimensions = { x: (newLEFT - oldLEFT), y: (newBOTTOM - oldBOTTOM) , z: (newNEAR - oldNEAR) }; var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); + + if (newDimensions.x < MINIMUM_DIMENSION) { + newDimensions.x = MINIMUM_DIMENSION; + } + + if (newDimensions.y < MINIMUM_DIMENSION) { + newDimensions.y = MINIMUM_DIMENSION; + } + + if (newDimensions.z < MINIMUM_DIMENSION) { + newDimensions.z = MINIMUM_DIMENSION; + } + var changeInPosition = { x: (newLEFT - oldLEFT) * -0.5, y: (newBOTTOM - oldBOTTOM) * -0.5, z: (newNEAR - oldNEAR) * -0.5 }; @@ -1265,6 +1323,19 @@ SelectionDisplay = (function () { var changeInDimensions = { x: (newRIGHT - oldRIGHT), y: (newTOP - oldTOP) , z: (newNEAR - oldNEAR) }; var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); + + if (newDimensions.x < MINIMUM_DIMENSION) { + newDimensions.x = MINIMUM_DIMENSION; + } + + if (newDimensions.y < MINIMUM_DIMENSION) { + newDimensions.y = MINIMUM_DIMENSION; + } + + if (newDimensions.z < MINIMUM_DIMENSION) { + newDimensions.z = MINIMUM_DIMENSION; + } + var changeInPosition = { x: (newRIGHT - oldRIGHT) * 0.5, y: (newTOP - oldTOP) * 0.5, z: (newNEAR - oldNEAR) * -0.5 }; @@ -1319,6 +1390,19 @@ SelectionDisplay = (function () { var changeInDimensions = { x: (newLEFT - oldLEFT), y: (newTOP - oldTOP) , z: (newNEAR - oldNEAR) }; var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); + + if (newDimensions.x < MINIMUM_DIMENSION) { + newDimensions.x = MINIMUM_DIMENSION; + } + + if (newDimensions.y < MINIMUM_DIMENSION) { + newDimensions.y = MINIMUM_DIMENSION; + } + + if (newDimensions.z < MINIMUM_DIMENSION) { + newDimensions.z = MINIMUM_DIMENSION; + } + var changeInPosition = { x: (newLEFT - oldLEFT) * -0.5, y: (newTOP - oldTOP) * 0.5, z: (newNEAR - oldNEAR) * -0.5 }; @@ -1373,6 +1457,19 @@ SelectionDisplay = (function () { var changeInDimensions = { x: (newRIGHT - oldRIGHT), y: (newBOTTOM - oldBOTTOM) , z: (newFAR - oldFAR) }; var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); + + if (newDimensions.x < MINIMUM_DIMENSION) { + newDimensions.x = MINIMUM_DIMENSION; + } + + if (newDimensions.y < MINIMUM_DIMENSION) { + newDimensions.y = MINIMUM_DIMENSION; + } + + if (newDimensions.z < MINIMUM_DIMENSION) { + newDimensions.z = MINIMUM_DIMENSION; + } + var changeInPosition = { x: (newRIGHT - oldRIGHT) * 0.5, y: (newBOTTOM - oldBOTTOM) * -0.5, z: (newFAR - oldFAR) * 0.5 }; @@ -1427,6 +1524,19 @@ SelectionDisplay = (function () { var changeInDimensions = { x: (newLEFT - oldLEFT), y: (newBOTTOM - oldBOTTOM) , z: (newFAR - oldFAR) }; var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); + + if (newDimensions.x < MINIMUM_DIMENSION) { + newDimensions.x = MINIMUM_DIMENSION; + } + + if (newDimensions.y < MINIMUM_DIMENSION) { + newDimensions.y = MINIMUM_DIMENSION; + } + + if (newDimensions.z < MINIMUM_DIMENSION) { + newDimensions.z = MINIMUM_DIMENSION; + } + var changeInPosition = { x: (newLEFT - oldLEFT) * -0.5, y: (newBOTTOM - oldBOTTOM) * -0.5, z: (newFAR - oldFAR) * 0.5 }; @@ -1481,6 +1591,19 @@ SelectionDisplay = (function () { var changeInDimensions = { x: (newRIGHT - oldRIGHT), y: (newTOP - oldTOP) , z: (newFAR - oldFAR) }; var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); + + if (newDimensions.x < MINIMUM_DIMENSION) { + newDimensions.x = MINIMUM_DIMENSION; + } + + if (newDimensions.y < MINIMUM_DIMENSION) { + newDimensions.y = MINIMUM_DIMENSION; + } + + if (newDimensions.z < MINIMUM_DIMENSION) { + newDimensions.z = MINIMUM_DIMENSION; + } + var changeInPosition = { x: (newRIGHT - oldRIGHT) * 0.5, y: (newTOP - oldTOP) * 0.5, z: (newFAR - oldFAR) * 0.5 }; @@ -1535,6 +1658,19 @@ SelectionDisplay = (function () { var changeInDimensions = { x: (newLEFT - oldLEFT), y: (newTOP - oldTOP) , z: (newFAR - oldFAR) }; var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); + + if (newDimensions.x < MINIMUM_DIMENSION) { + newDimensions.x = MINIMUM_DIMENSION; + } + + if (newDimensions.y < MINIMUM_DIMENSION) { + newDimensions.y = MINIMUM_DIMENSION; + } + + if (newDimensions.z < MINIMUM_DIMENSION) { + newDimensions.z = MINIMUM_DIMENSION; + } + var changeInPosition = { x: (newLEFT - oldLEFT) * -0.5, y: (newTOP - oldTOP) * 0.5, z: (newFAR - oldFAR) * 0.5 }; From caac5881bf2544f7b2dbb7944db8a5bca7788b56 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 10 Oct 2014 21:39:05 -0700 Subject: [PATCH 35/43] correctly handle unselect and dont show highlight when other tool is active --- examples/libraries/entitySelectionTool.js | 9 ++-- examples/newEditEntities.js | 56 ++++++++++++----------- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 43c7849ab3..1e39096308 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -2254,8 +2254,9 @@ SelectionDisplay = (function () { break; default: // nothing to do by default - break; + return false; } + return true; }; that.mouseReleaseEvent = function(event) { @@ -2289,9 +2290,9 @@ SelectionDisplay = (function () { }; - // NOTE: mousePressEvent from the main script should call us., so we don't - // hook the Controller.mousePressEvent.connect(that.mousePressEvent); ourselves. - Controller.mouseMoveEvent.connect(that.mouseMoveEvent); + // NOTE: mousePressEvent and mouseMoveEvent from the main script should call us., so we don't hook these: + // Controller.mousePressEvent.connect(that.mousePressEvent); + // Controller.mouseMoveEvent.connect(that.mouseMoveEvent); Controller.mouseReleaseEvent.connect(that.mouseReleaseEvent); return that; diff --git a/examples/newEditEntities.js b/examples/newEditEntities.js index 1fb21caacc..5c50d37048 100644 --- a/examples/newEditEntities.js +++ b/examples/newEditEntities.js @@ -338,13 +338,15 @@ function rayPlaneIntersection(pickRay, point, normal) { function mousePressEvent(event) { mouseLastPosition = { x: event.x, y: event.y }; - entitySelected = false; var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); if (toolBar.mousePressEvent(event) || progressDialog.mousePressEvent(event) || selectionDisplay.mousePressEvent(event)) { // Event handled; do nothing. return; } else { + entitySelected = false; + selectionDisplay.unselectAll(); + // If we aren't active and didn't click on an overlay: quit if (!isActive) { return; @@ -440,34 +442,36 @@ function mouseMoveEvent(event) { if (!isActive) { return; } + + // allow the selectionDisplay to handle the event first, if it doesn't handle it, then do our own thing + if (selectionDisplay.mouseMoveEvent(event)) { + return; + } var pickRay = Camera.computePickRay(event.x, event.y); - if (!entitySelected) { - var entityIntersection = Entities.findRayIntersection(pickRay); - if (entityIntersection.accurate) { - if(highlightedEntityID.isKnownID && highlightedEntityID.id != entityIntersection.entityID.id) { - selectionDisplay.unhighlightSelectable(highlightedEntityID); - highlightedEntityID = { id: -1, isKnownID: false }; - } - - var halfDiagonal = Vec3.length(entityIntersection.properties.dimensions) / 2.0; - - var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), - entityIntersection.properties.position)) * 180 / 3.14; - - var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) - && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); - - if (entityIntersection.entityID.isKnownID && sizeOK) { - if (wantEntityGlow) { - Entities.editEntity(entityIntersection.entityID, { glowLevel: 0.25 }); - } - highlightedEntityID = entityIntersection.entityID; - selectionDisplay.highlightSelectable(entityIntersection.entityID); - } - + var entityIntersection = Entities.findRayIntersection(pickRay); + if (entityIntersection.accurate) { + if(highlightedEntityID.isKnownID && highlightedEntityID.id != entityIntersection.entityID.id) { + selectionDisplay.unhighlightSelectable(highlightedEntityID); + highlightedEntityID = { id: -1, isKnownID: false }; } - return; + + var halfDiagonal = Vec3.length(entityIntersection.properties.dimensions) / 2.0; + + var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), + entityIntersection.properties.position)) * 180 / 3.14; + + var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) + && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); + + if (entityIntersection.entityID.isKnownID && sizeOK) { + if (wantEntityGlow) { + Entities.editEntity(entityIntersection.entityID, { glowLevel: 0.25 }); + } + highlightedEntityID = entityIntersection.entityID; + selectionDisplay.highlightSelectable(entityIntersection.entityID); + } + } } From e6d7add5dc46edd6f1900ea43d0cd965518f67f3 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 10 Oct 2014 21:57:10 -0700 Subject: [PATCH 36/43] display tickmarks on the current rotation overlay --- examples/libraries/entitySelectionTool.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 1e39096308..8a84fa37ce 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -262,6 +262,9 @@ SelectionDisplay = (function () { visible: false, rotation: yawOverlayRotation, ignoreRayIntersection: true, // always ignore this + hasTickMarks: true, + majorTickMarksColor: { red: 0, green: 0, blue: 0 }, + minorTickMarksColor: { red: 0, green: 0, blue: 0 }, }); var yawHandle = Overlays.addOverlay("billboard", { @@ -1750,11 +1753,15 @@ SelectionDisplay = (function () { if (snapToInner) { Overlays.editOverlay(rotateOverlayOuter, { startAt: 0, endAt: 360 }); Overlays.editOverlay(rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius }); + Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius, + majorTickMarksAngle: innerSnapAngle, minorTickMarksAngle: 0, + majorTickMarksLength: -0.25, minorTickMarksLength: 0, }); } else { Overlays.editOverlay(rotateOverlayInner, { startAt: 0, endAt: 360 }); Overlays.editOverlay(rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius }); + Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius, + majorTickMarksAngle: 45.0, minorTickMarksAngle: 5, + majorTickMarksLength: 0.25, minorTickMarksLength: 0.1, }); } } From a08ddecc3a3fc1b6f3dc7f692854bfbe562dcbe7 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 10 Oct 2014 22:06:12 -0700 Subject: [PATCH 37/43] fix shifting tickmarks --- interface/src/ui/overlays/Circle3DOverlay.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp index 62ddee4cf2..d7120a5ff8 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -168,7 +168,8 @@ void Circle3DOverlay::render() { xColor color = getMajorTickMarksColor(); glColor4f(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha); - float angle = startAt; + float tickMarkAngle = getMajorTickMarksAngle(); + float angle = startAt - fmod(startAt, tickMarkAngle) + tickMarkAngle; float angleInRadians = glm::radians(angle); float tickMarkLength = getMajorTickMarksLength(); float startRadius = (tickMarkLength > 0.0f) ? innerRadius : outerRadius; @@ -183,7 +184,7 @@ void Circle3DOverlay::render() { glVertex2f(thisPointA.x, thisPointA.y); glVertex2f(thisPointB.x, thisPointB.y); - angle += getMajorTickMarksAngle(); + angle += tickMarkAngle; } } @@ -193,7 +194,8 @@ void Circle3DOverlay::render() { xColor color = getMinorTickMarksColor(); glColor4f(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha); - float angle = startAt; + float tickMarkAngle = getMinorTickMarksAngle(); + float angle = startAt - fmod(startAt, tickMarkAngle) + tickMarkAngle; float angleInRadians = glm::radians(angle); float tickMarkLength = getMinorTickMarksLength(); float startRadius = (tickMarkLength > 0.0f) ? innerRadius : outerRadius; @@ -208,7 +210,7 @@ void Circle3DOverlay::render() { glVertex2f(thisPointA.x, thisPointA.y); glVertex2f(thisPointB.x, thisPointB.y); - angle += getMinorTickMarksAngle(); + angle += tickMarkAngle; } } From 8c85c3261e3d1263b54fe2280cb7a3f56d097211 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 10 Oct 2014 22:11:27 -0700 Subject: [PATCH 38/43] draw tickmarks for current roation correctly for pitch and roll as well --- examples/libraries/entitySelectionTool.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 8a84fa37ce..1746b59f32 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -1817,11 +1817,15 @@ SelectionDisplay = (function () { if (snapToInner) { Overlays.editOverlay(rotateOverlayOuter, { startAt: 0, endAt: 360 }); Overlays.editOverlay(rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius }); + Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius, + majorTickMarksAngle: innerSnapAngle, minorTickMarksAngle: 0, + majorTickMarksLength: -0.25, minorTickMarksLength: 0, }); } else { Overlays.editOverlay(rotateOverlayInner, { startAt: 0, endAt: 360 }); Overlays.editOverlay(rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius }); + Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius, + majorTickMarksAngle: 45.0, minorTickMarksAngle: 5, + majorTickMarksLength: 0.25, minorTickMarksLength: 0.1, }); } } }; @@ -1875,11 +1879,15 @@ SelectionDisplay = (function () { if (snapToInner) { Overlays.editOverlay(rotateOverlayOuter, { startAt: 0, endAt: 360 }); Overlays.editOverlay(rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius }); + Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius, + majorTickMarksAngle: innerSnapAngle, minorTickMarksAngle: 0, + majorTickMarksLength: -0.25, minorTickMarksLength: 0, }); } else { Overlays.editOverlay(rotateOverlayInner, { startAt: 0, endAt: 360 }); Overlays.editOverlay(rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius }); + Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius, + majorTickMarksAngle: 45.0, minorTickMarksAngle: 5, + majorTickMarksLength: 0.25, minorTickMarksLength: 0.1, }); } } }; From c6bf09f509881cb988365b73048ea6acc9c94624 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 13 Oct 2014 08:35:52 -0700 Subject: [PATCH 39/43] Fix model uploading for the case that haven't uploaded model before --- examples/editModels.js | 1 - examples/newEditEntities.js | 1 - interface/src/scripting/SettingsScriptingInterface.cpp | 6 ++++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/editModels.js b/examples/editModels.js index 2741bdccdd..0a908595a3 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -1312,7 +1312,6 @@ var toolBar = (function () { if (clickedOverlay === loadFileMenuItem) { toggleNewModelButton(false); - // TODO BUG: this is bug, if the user has never uploaded a model, this will throw an JS exception file = Window.browse("Select your model file ...", Settings.getValue("LastModelUploadLocation").path(), "Model files (*.fst *.fbx)"); diff --git a/examples/newEditEntities.js b/examples/newEditEntities.js index b753537631..49dd46033b 100644 --- a/examples/newEditEntities.js +++ b/examples/newEditEntities.js @@ -238,7 +238,6 @@ var toolBar = (function () { if (clickedOverlay === loadFileMenuItem) { toggleNewModelButton(false); - // TODO BUG: this is bug, if the user has never uploaded a model, this will throw an JS exception file = Window.browse("Select your model file ...", Settings.getValue("LastModelUploadLocation").path(), "Model files (*.fst *.fbx)"); diff --git a/interface/src/scripting/SettingsScriptingInterface.cpp b/interface/src/scripting/SettingsScriptingInterface.cpp index ea9d645a94..21a5244138 100644 --- a/interface/src/scripting/SettingsScriptingInterface.cpp +++ b/interface/src/scripting/SettingsScriptingInterface.cpp @@ -22,6 +22,9 @@ QVariant SettingsScriptingInterface::getValue(const QString& setting) { QSettings* settings = Application::getInstance()->lockSettings(); QVariant value = settings->value(setting); Application::getInstance()->unlockSettings(); + if (!value.isValid()) { + value = ""; + } return value; } @@ -29,6 +32,9 @@ QVariant SettingsScriptingInterface::getValue(const QString& setting, const QVar QSettings* settings = Application::getInstance()->lockSettings(); QVariant value = settings->value(setting, defaultValue); Application::getInstance()->unlockSettings(); + if (!value.isValid()) { + value = ""; + } return value; } From 2b6cd6d29aa408d10f3e5516aedba13b49d42fc3 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 13 Oct 2014 11:33:06 -0700 Subject: [PATCH 40/43] add debugging for ryan's rotate problems --- examples/libraries/entitySelectionTool.js | 64 ++++++++++++++++++++--- examples/newEditEntities.js | 2 + 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 1746b59f32..57f8bde369 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -1706,6 +1706,13 @@ SelectionDisplay = (function () { if (!entitySelected || mode !== "ROTATE_YAW") { return; // not allowed } + + var debug = Menu.isOptionChecked("Debug Ryans Rotation Problems"); + + if (debug) { + print("rotateYaw()..."); + print(" event.x,y:" + event.x + "," + event.y); + } var pickRay = Camera.computePickRay(event.x, event.y); Overlays.editOverlay(selectionBox, { ignoreRayIntersection: true, visible: false}); @@ -1716,7 +1723,14 @@ SelectionDisplay = (function () { Overlays.editOverlay(rotateOverlayCurrent, { ignoreRayIntersection: true }); var result = Overlays.findRayIntersection(pickRay); + + if (debug) { + print(" findRayIntersection() .... result.intersects:" + result.intersects); + } + if (result.intersects) { + + var properties = Entities.getEntityProperties(currentSelection); var center = yawCenter; var zero = yawZero; @@ -1732,7 +1746,11 @@ SelectionDisplay = (function () { } // for debugging - //Overlays.editOverlay(rotateCurrentOverlay, { visible: true, start: center, end: result.intersection }); + if (debug) { + Vec3.print(" result.intersection:",result.intersection); + Overlays.editOverlay(rotateCurrentOverlay, { visible: true, start: center, end: result.intersection }); + print(" angleFromZero:" + angleFromZero); + } var yawChange = Quat.fromVec3Degrees({ x: 0, y: angleFromZero, z: 0 }); var newRotation = Quat.multiply(yawChange, originalRotation); @@ -1771,6 +1789,13 @@ SelectionDisplay = (function () { if (!entitySelected || mode !== "ROTATE_PITCH") { return; // not allowed } + var debug = Menu.isOptionChecked("Debug Ryans Rotation Problems"); + + if (debug) { + print("rotatePitch()..."); + print(" event.x,y:" + event.x + "," + event.y); + } + var pickRay = Camera.computePickRay(event.x, event.y); Overlays.editOverlay(selectionBox, { ignoreRayIntersection: true, visible: false}); Overlays.editOverlay(baseOfEntityProjectionOverlay, { ignoreRayIntersection: true, visible: false }); @@ -1779,7 +1804,11 @@ SelectionDisplay = (function () { Overlays.editOverlay(rotateOverlayOuter, { ignoreRayIntersection: true }); Overlays.editOverlay(rotateOverlayCurrent, { ignoreRayIntersection: true }); var result = Overlays.findRayIntersection(pickRay); - + + if (debug) { + print(" findRayIntersection() .... result.intersects:" + result.intersects); + } + if (result.intersects) { var properties = Entities.getEntityProperties(currentSelection); var center = pitchCenter; @@ -1796,7 +1825,11 @@ SelectionDisplay = (function () { } // for debugging - //Overlays.editOverlay(rotateCurrentOverlay, { visible: true, start: center, end: result.intersection }); + if (debug) { + Vec3.print(" result.intersection:",result.intersection); + Overlays.editOverlay(rotateCurrentOverlay, { visible: true, start: center, end: result.intersection }); + print(" angleFromZero:" + angleFromZero); + } var pitchChange = Quat.fromVec3Degrees({ x: angleFromZero, y: 0, z: 0 }); var newRotation = Quat.multiply(pitchChange, originalRotation); @@ -1834,6 +1867,13 @@ SelectionDisplay = (function () { if (!entitySelected || mode !== "ROTATE_ROLL") { return; // not allowed } + var debug = Menu.isOptionChecked("Debug Ryans Rotation Problems"); + + if (debug) { + print("rotateRoll()..."); + print(" event.x,y:" + event.x + "," + event.y); + } + var pickRay = Camera.computePickRay(event.x, event.y); Overlays.editOverlay(selectionBox, { ignoreRayIntersection: true, visible: false}); Overlays.editOverlay(baseOfEntityProjectionOverlay, { ignoreRayIntersection: true, visible: false }); @@ -1842,6 +1882,11 @@ SelectionDisplay = (function () { Overlays.editOverlay(rotateOverlayOuter, { ignoreRayIntersection: true }); Overlays.editOverlay(rotateOverlayCurrent, { ignoreRayIntersection: true }); var result = Overlays.findRayIntersection(pickRay); + + if (debug) { + print(" findRayIntersection() .... result.intersects:" + result.intersects); + } + if (result.intersects) { var properties = Entities.getEntityProperties(currentSelection); var center = rollCenter; @@ -1858,7 +1903,11 @@ SelectionDisplay = (function () { } // for debugging - //Overlays.editOverlay(rotateCurrentOverlay, { visible: true, start: center, end: result.intersection }); + if (debug) { + Vec3.print(" result.intersection:",result.intersection); + Overlays.editOverlay(rotateCurrentOverlay, { visible: true, start: center, end: result.intersection }); + print(" angleFromZero:" + angleFromZero); + } var rollChange = Quat.fromVec3Degrees({ x: 0, y: 0, z: angleFromZero }); var newRotation = Quat.multiply(rollChange, originalRotation); @@ -2124,8 +2173,11 @@ SelectionDisplay = (function () { Overlays.editOverlay(rotateOverlayCurrent, { visible: true, rotation: overlayOrientation, position: overlayCenter, startAt: 0, endAt: 0 }); // for debugging - //Overlays.editOverlay(rotateZeroOverlay, { visible: true, start: overlayCenter, end: result.intersection }); - //Overlays.editOverlay(rotateCurrentOverlay, { visible: true, start: overlayCenter, end: result.intersection }); + var debug = Menu.isOptionChecked("Debug Ryans Rotation Problems"); + if (debug) { + Overlays.editOverlay(rotateZeroOverlay, { visible: true, start: overlayCenter, end: result.intersection }); + Overlays.editOverlay(rotateCurrentOverlay, { visible: true, start: overlayCenter, end: result.intersection }); + } Overlays.editOverlay(yawHandle, { visible: false }); Overlays.editOverlay(pitchHandle, { visible: false }); diff --git a/examples/newEditEntities.js b/examples/newEditEntities.js index 5c50d37048..8657bac652 100644 --- a/examples/newEditEntities.js +++ b/examples/newEditEntities.js @@ -518,6 +518,7 @@ function setupModelMenus() { Menu.addMenuItem({ menuName: "File", menuItemName: "Models", isSeparator: true, beforeItem: "Settings" }); Menu.addMenuItem({ menuName: "File", menuItemName: "Export Models", shortcutKey: "CTRL+META+E", afterItem: "Models" }); Menu.addMenuItem({ menuName: "File", menuItemName: "Import Models", shortcutKey: "CTRL+META+I", afterItem: "Export Models" }); + Menu.addMenuItem({ menuName: "Developer", menuItemName: "Debug Ryans Rotation Problems", isCheckable: true }); } setupModelMenus(); // do this when first running our script. @@ -537,6 +538,7 @@ function cleanupModelMenus() { Menu.removeSeparator("File", "Models"); Menu.removeMenuItem("File", "Export Models"); Menu.removeMenuItem("File", "Import Models"); + Menu.removeMenuItem("Developer", "Debug Ryans Rotation Problems"); } Script.scriptEnding.connect(function() { From 45a5768750ced85ee99ced92de0697af37991374 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 13 Oct 2014 12:19:38 -0700 Subject: [PATCH 41/43] highlight grabber handles on hover --- examples/libraries/entitySelectionTool.js | 99 ++++++++++++++++++++++- 1 file changed, 98 insertions(+), 1 deletion(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 57f8bde369..503d4415de 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -60,9 +60,17 @@ SelectionDisplay = (function () { var rotateHandleColor = { red: 0, green: 0, blue: 0 }; var rotateHandleAlpha = 0.7; + var highlightedHandleColor = { red: 255, green: 0, blue: 0 }; + var highlightedHandleAlpha = 0.7; + + var previousHandle = false; + var previousHandleColor; + var previousHandleAlpha; + var grabberSizeCorner = 0.025; var grabberSizeEdge = 0.015; var grabberSizeFace = 0.025; + var grabberAlpha = 1; var grabberColorCorner = { red: 120, green: 120, blue: 120 }; var grabberColorEdge = { red: 0, green: 0, blue: 0 }; var grabberColorFace = { red: 120, green: 120, blue: 120 }; @@ -2320,7 +2328,96 @@ SelectionDisplay = (function () { that.stretchLEFT(event); break; default: - // nothing to do by default + // if not in any specific mode, then just look for handles to highlight... + var pickRay = Camera.computePickRay(event.x, event.y); + var result = Overlays.findRayIntersection(pickRay); + var pickedColor; + var pickedAlpha; + var highlightNeeded = false; + + if (result.intersects) { + switch(result.overlayID) { + case yawHandle: + case pitchHandle: + case rollHandle: + pickedColor = rotateHandleColor; + pickedAlpha = rotateHandleAlpha; + highlightNeeded = true; + break; + + case grabberMoveUp: + pickedColor = rotateHandleColor; + pickedAlpha = rotateHandleAlpha; + highlightNeeded = true; + break; + + case grabberLBN: + case grabberLBF: + case grabberRBN: + case grabberRBF: + case grabberLTN: + case grabberLTF: + case grabberRTN: + case grabberRTF: + pickedColor = grabberColorCorner; + pickedAlpha = grabberAlpha; + highlightNeeded = true; + break; + + case grabberTOP: + case grabberBOTTOM: + case grabberLEFT: + case grabberRIGHT: + case grabberNEAR: + case grabberFAR: + pickedColor = grabberColorFace; + pickedAlpha = grabberAlpha; + highlightNeeded = true; + break; + + case grabberEdgeTR: + case grabberEdgeTL: + case grabberEdgeTF: + case grabberEdgeTN: + case grabberEdgeBR: + case grabberEdgeBL: + case grabberEdgeBF: + case grabberEdgeBN: + case grabberEdgeNR: + case grabberEdgeNL: + case grabberEdgeFR: + case grabberEdgeFL: + pickedColor = grabberColorEdge; + pickedAlpha = grabberAlpha; + highlightNeeded = true; + break; + + default: + if (previousHandle) { + Overlays.editOverlay(previousHandle, { color: previousHandleColor, alpha: previousHandleAlpha }); + previousHandle = false; + } + break; + } + + if (highlightNeeded) { + if (previousHandle) { + Overlays.editOverlay(previousHandle, { color: previousHandleColor, alpha: previousHandleAlpha }); + previousHandle = false; + } + Overlays.editOverlay(result.overlayID, { color: highlightedHandleColor, alpha: highlightedHandleAlpha }); + previousHandle = result.overlayID; + previousHandleColor = pickedColor; + previousHandleAlpha = pickedAlpha; + } + + } else { + if (previousHandle) { + Overlays.editOverlay(previousHandle, { color: previousHandleColor, alpha: previousHandleAlpha }); + previousHandle = false; + } + } + return false; } return true; From bd9451d4c69d3d775ea191525b8a14e622d37258 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 13 Oct 2014 13:20:24 -0700 Subject: [PATCH 42/43] Log Oculus SDK version used in build --- interface/src/devices/OculusManager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index fcbfd32350..62894510c2 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -78,6 +78,8 @@ void OculusManager::connect() { #ifdef HAVE_LIBOVR _calibrationState = UNCALIBRATED; + qDebug() << "Oculus SDK" << OVR_VERSION_STRING; + ovr_Initialize(); _ovrHmd = ovrHmd_Create(0); From 958acfcfe0a785fb4c1e0bacd7c6597cfa979d7b Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 13 Oct 2014 13:23:31 -0700 Subject: [PATCH 43/43] Fix version logging include to include build number and write in log --- interface/src/Application.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d3bed0c3ea..777f78c2c1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -187,8 +187,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : // set the associated application properties applicationInfo.beginGroup("INFO"); - qDebug() << "[VERSION] Build sequence: " << qPrintable(applicationVersion()); - setApplicationName(applicationInfo.value("name").toString()); setApplicationVersion(BUILD_VERSION); setOrganizationName(applicationInfo.value("organizationName").toString()); @@ -207,6 +205,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : qInstallMessageHandler(messageHandler); + qDebug() << "[VERSION] Build sequence: " << qPrintable(applicationVersion()); + // call Menu getInstance static method to set up the menu _window->setMenuBar(Menu::getInstance());