From 642a1e30961e82feb54212e72bae489f6f52a737 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 11 Jul 2017 17:07:53 -0700 Subject: [PATCH 01/42] framework for LaserPointers and abstracted RayPicking on C++ side, including JS API --- interface/src/Application.cpp | 8 +++ .../src/LaserPointerScriptingInterface.cpp | 56 +++++++++++++++++++ .../src/LaserPointerScriptingInterface.h | 33 +++++++++++ .../src/controllers/LaserPointer.cpp | 35 ++++++++++++ .../src/controllers/LaserPointer.h | 34 +++++++++++ .../src/controllers/LaserPointerManager.cpp | 36 ++++++++++++ .../src/controllers/LaserPointerManager.h | 36 ++++++++++++ libraries/shared/src/JointRayPick.cpp | 26 +++++++++ libraries/shared/src/JointRayPick.h | 32 +++++++++++ libraries/shared/src/RayPick.cpp | 18 ++++++ libraries/shared/src/RayPick.h | 42 ++++++++++++++ libraries/shared/src/RayPickManager.cpp | 54 ++++++++++++++++++ libraries/shared/src/RayPickManager.h | 50 +++++++++++++++++ libraries/shared/src/StaticRayPick.cpp | 17 ++++++ libraries/shared/src/StaticRayPick.h | 28 ++++++++++ 15 files changed, 505 insertions(+) create mode 100644 interface/src/LaserPointerScriptingInterface.cpp create mode 100644 interface/src/LaserPointerScriptingInterface.h create mode 100644 libraries/controllers/src/controllers/LaserPointer.cpp create mode 100644 libraries/controllers/src/controllers/LaserPointer.h create mode 100644 libraries/controllers/src/controllers/LaserPointerManager.cpp create mode 100644 libraries/controllers/src/controllers/LaserPointerManager.h create mode 100644 libraries/shared/src/JointRayPick.cpp create mode 100644 libraries/shared/src/JointRayPick.h create mode 100644 libraries/shared/src/RayPick.cpp create mode 100644 libraries/shared/src/RayPick.h create mode 100644 libraries/shared/src/RayPickManager.cpp create mode 100644 libraries/shared/src/RayPickManager.h create mode 100644 libraries/shared/src/StaticRayPick.cpp create mode 100644 libraries/shared/src/StaticRayPick.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ddd1870723..16e322a142 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -190,6 +190,8 @@ #include #include #include +#include "LaserPointerScriptingInterface.h" +#include // On Windows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU // FIXME seems to be broken. @@ -4916,6 +4918,11 @@ void Application::update(float deltaTime) { _overlays.update(deltaTime); } + { + PROFILE_RANGE(app, "RayPick"); + RayPickManager::getInstance().update(); + } + // Update _viewFrustum with latest camera and view frustum data... // NOTE: we get this from the view frustum, to make it simpler, since the // loadViewFrumstum() method will get the correct details from the camera @@ -5761,6 +5768,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("AudioScope", DependencyManager::get().data()); scriptEngine->registerGlobalObject("AvatarBookmarks", DependencyManager::get().data()); scriptEngine->registerGlobalObject("LocationBookmarks", DependencyManager::get().data()); + scriptEngine->registerGlobalObject("LaserPointers", LaserPointerScriptingInterface::getInstance()); // Caches scriptEngine->registerGlobalObject("AnimationCache", DependencyManager::get().data()); diff --git a/interface/src/LaserPointerScriptingInterface.cpp b/interface/src/LaserPointerScriptingInterface.cpp new file mode 100644 index 0000000000..a5770a9252 --- /dev/null +++ b/interface/src/LaserPointerScriptingInterface.cpp @@ -0,0 +1,56 @@ +// +// LaserPointerScriptingInterface.cpp +// interface/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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 "LaserPointerScriptingInterface.h" + +#include +#include "Transform.h" + +LaserPointerScriptingInterface* LaserPointerScriptingInterface::getInstance() { + static LaserPointerScriptingInterface instance; + return &instance; +} + +uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& properties) { + QVariantMap propertyMap = properties.toMap(); + + if (propertyMap["joint"].isValid()) { + QString jointName = propertyMap["joint"].toString(); + + Transform offsetTransform; + if (propertyMap["offsetTransform"].isValid()) { + // TODO: + // convert transform + } + + uint16_t filter = 0; + if (propertyMap["filter"].isValid()) { + filter = propertyMap["filter"].toUInt(); + } + + float maxDistance = 0.0f; + if (propertyMap["maxDistance"].isValid()) { + maxDistance = propertyMap["maxDistance"].toFloat(); + } + + bool enabled = false; + if (propertyMap["enabled"].isValid()) { + enabled = propertyMap["enabled"].toBool(); + } + + // TODO: + // handle render state properties + + return LaserPointerManager::getInstance().createLaserPointer(jointName, offsetTransform, filter, maxDistance, enabled); + } else { + return 0; + } +} \ No newline at end of file diff --git a/interface/src/LaserPointerScriptingInterface.h b/interface/src/LaserPointerScriptingInterface.h new file mode 100644 index 0000000000..c455843d03 --- /dev/null +++ b/interface/src/LaserPointerScriptingInterface.h @@ -0,0 +1,33 @@ +// +// LaserPointerScriptingInterface.h +// interface/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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_LaserPointerScriptingInterface_h +#define hifi_LaserPointerScriptingInterface_h + +#include + +#include "controllers\LaserPointerManager.h" + +class LaserPointerScriptingInterface : public QObject { + Q_OBJECT + +public: + static LaserPointerScriptingInterface* getInstance(); + +public slots: + Q_INVOKABLE unsigned int createLaserPointer(const QVariant& properties); + Q_INVOKABLE void enableLaserPointer(unsigned int uid) { LaserPointerManager::getInstance().enableLaserPointer(uid); } + Q_INVOKABLE void disableLaserPointer(unsigned int uid) { LaserPointerManager::getInstance().disableLaserPointer(uid); } + Q_INVOKABLE void removeLaserPointer(unsigned int uid) { LaserPointerManager::getInstance().removeLaserPointer(uid); } + //Q_INVOKABLE IntersectionResults getLaserPointerCollisionResults(unsigned int uid) { LaserPointerManager::getInstance().getLaserPointerCollisionResults(uid); } + +}; + +#endif hifi_LaserPointerScriptingInterface_h \ No newline at end of file diff --git a/libraries/controllers/src/controllers/LaserPointer.cpp b/libraries/controllers/src/controllers/LaserPointer.cpp new file mode 100644 index 0000000000..4f3adce875 --- /dev/null +++ b/libraries/controllers/src/controllers/LaserPointer.cpp @@ -0,0 +1,35 @@ +// +// LaserPointer.cpp +// libraries/controllers/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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 "LaserPointer.h" + +#include "RayPickManager.h" +#include "JointRayPick.h" + +LaserPointer::LaserPointer(const QString& jointName, const Transform& offsetTransform, const uint16_t filter, const float maxDistance, const bool enabled) +{ + _rayPickUID = RayPickManager::getInstance().addRayPick(std::make_shared(jointName, offsetTransform, filter, maxDistance, enabled)); +} + +LaserPointer::~LaserPointer() { + RayPickManager::getInstance().removeRayPick(_rayPickUID); +} + +void LaserPointer::enable() { + RayPickManager::getInstance().enableRayPick(_rayPickUID); + // TODO: + // turn on rendering +} + +void LaserPointer::disable() { + RayPickManager::getInstance().disableRayPick(_rayPickUID); + // TODO: + // turn off rendering +} \ No newline at end of file diff --git a/libraries/controllers/src/controllers/LaserPointer.h b/libraries/controllers/src/controllers/LaserPointer.h new file mode 100644 index 0000000000..d09defe7b2 --- /dev/null +++ b/libraries/controllers/src/controllers/LaserPointer.h @@ -0,0 +1,34 @@ +// +// LaserPointer.h +// libraries/controllers/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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_LaserPointer_h +#define hifi_LaserPointer_h + +#include +#include "Transform.h" + +class LaserPointer { + +public: + LaserPointer(const QString& jointName, const Transform& offsetTransform, const uint16_t filter, const float maxDistance, bool enabled); + ~LaserPointer(); + + unsigned int getUID() { return _rayPickUID; } + void enable(); + void disable(); + + // void setRenderState(const QString& stateName); + // void setRenderStateProperties(const QHash& renderStateProperties); + +private: + unsigned int _rayPickUID; +}; + +#endif hifi_LaserPointer_h \ No newline at end of file diff --git a/libraries/controllers/src/controllers/LaserPointerManager.cpp b/libraries/controllers/src/controllers/LaserPointerManager.cpp new file mode 100644 index 0000000000..adea77f530 --- /dev/null +++ b/libraries/controllers/src/controllers/LaserPointerManager.cpp @@ -0,0 +1,36 @@ +// +// LaserPointerManager.cpp +// libraries/controllers/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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 "LaserPointerManager.h" +#include "LaserPointer.h" + +LaserPointerManager& LaserPointerManager::getInstance() { + static LaserPointerManager instance; + return instance; +} + +unsigned int LaserPointerManager::createLaserPointer(const QString& jointName, const Transform& offsetTransform, const uint16_t filter, const float maxDistance, bool enabled) { + std::shared_ptr laserPointer = std::make_shared(jointName, offsetTransform, filter, maxDistance, enabled); + unsigned int uid = laserPointer->getUID(); + _laserPointers[uid] = laserPointer; + return uid; +} + +void LaserPointerManager::enableLaserPointer(const unsigned int uid) { + if (_laserPointers.contains(uid)) { + _laserPointers[uid]->enable(); + } +} + +void LaserPointerManager::disableLaserPointer(const unsigned int uid) { + if (_laserPointers.contains(uid)) { + _laserPointers[uid]->disable(); + } +} \ No newline at end of file diff --git a/libraries/controllers/src/controllers/LaserPointerManager.h b/libraries/controllers/src/controllers/LaserPointerManager.h new file mode 100644 index 0000000000..28d354cf98 --- /dev/null +++ b/libraries/controllers/src/controllers/LaserPointerManager.h @@ -0,0 +1,36 @@ +// +// LaserPointerManager.h +// libraries/controllers/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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_LaserPointerManager_h +#define hifi_LaserPointerManager_h + +#include +#include +#include +#include "Transform.h" + +class LaserPointer; + +class LaserPointerManager { + +public: + static LaserPointerManager& getInstance(); + + unsigned int createLaserPointer(const QString& jointName, const Transform& offsetTransform, const uint16_t filter, const float maxDistance, bool enabled); + void removeLaserPointer(const unsigned int uid) { _laserPointers.remove(uid); } + void enableLaserPointer(const unsigned int uid); + void disableLaserPointer(const unsigned int uid); + +private: + QHash> _laserPointers; + +}; + +#endif hifi_LaserPointerManager_h \ No newline at end of file diff --git a/libraries/shared/src/JointRayPick.cpp b/libraries/shared/src/JointRayPick.cpp new file mode 100644 index 0000000000..4a645fa3fd --- /dev/null +++ b/libraries/shared/src/JointRayPick.cpp @@ -0,0 +1,26 @@ +// +// JointRayPick.cpp +// libraries/shared/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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 "JointRayPick.h" + +JointRayPick::JointRayPick(const QString& jointName, const Transform& offsetTransform, const uint16_t filter, const float maxDistance, const bool enabled) : + RayPick(filter, maxDistance, enabled), + _jointName(jointName), + _offsetTransform(offsetTransform) +{ +} + +const PickRay JointRayPick::getPickRay() { + // TODO: + // get pose for _jointName + // apply _offsetTransform + // create and return PickRay + return PickRay(); +} diff --git a/libraries/shared/src/JointRayPick.h b/libraries/shared/src/JointRayPick.h new file mode 100644 index 0000000000..cd5de79c69 --- /dev/null +++ b/libraries/shared/src/JointRayPick.h @@ -0,0 +1,32 @@ +// +// JointRayPick.h +// libraries/shared/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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_JointRayPick_h +#define hifi_JointRayPick_h + +#include "RayPick.h" + +#include +#include "Transform.h" + +class JointRayPick : public RayPick { + +public: + JointRayPick(const QString& jointName, const Transform& offsetTransform, const uint16_t filter, const float maxDistance = 0.0f, const bool enabled = false); + + const PickRay getPickRay() override; + +private: + QString _jointName; + Transform _offsetTransform; + +}; + +#endif hifi_JointRayPick_h \ No newline at end of file diff --git a/libraries/shared/src/RayPick.cpp b/libraries/shared/src/RayPick.cpp new file mode 100644 index 0000000000..674913e2e0 --- /dev/null +++ b/libraries/shared/src/RayPick.cpp @@ -0,0 +1,18 @@ +// +// RayPick.cpp +// libraries/shared/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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 "RayPick.h" + +RayPick::RayPick(const uint16_t filter, const float maxDistance, const bool enabled) : + _filter(filter), + _maxDistance(maxDistance), + _enabled(enabled) +{ +} diff --git a/libraries/shared/src/RayPick.h b/libraries/shared/src/RayPick.h new file mode 100644 index 0000000000..8a292bf5f7 --- /dev/null +++ b/libraries/shared/src/RayPick.h @@ -0,0 +1,42 @@ +// +// RayPick.h +// libraries/shared/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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_RayPick_h +#define hifi_RayPick_h + +#include +#include "RegisteredMetaTypes.h" + +class RayPick { + +public: + RayPick(const uint16_t filter, const float maxDistance, const bool enabled); + + virtual const PickRay getPickRay() = 0; + + void enable() { _enabled = true; } + void disable() { _enabled = false; } + + const uint16_t getFilter() { return _filter; } + const float getMaxDistance() { return _maxDistance; } + const bool isEnabled() { return _enabled; } + //const IntersectionResult& getLastIntersectionResult() { return _prevIntersectionResult; } + + //void setIntersectionResult(const IntersectionResult& intersectionResult) { _prevIntersectionResult = intersectionResult; } + +private: + uint16_t _filter; + float _maxDistance; + bool _enabled; + //IntersectionResult _prevIntersectionResult; // set to invalid on disable()? + +}; + +#endif hifi_RayPick_h \ No newline at end of file diff --git a/libraries/shared/src/RayPickManager.cpp b/libraries/shared/src/RayPickManager.cpp new file mode 100644 index 0000000000..5c5ebd8c10 --- /dev/null +++ b/libraries/shared/src/RayPickManager.cpp @@ -0,0 +1,54 @@ +// +// RayPickManager.cpp +// libraries/shared/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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 "RayPickManager.h" +#include "RayPick.h" + +RayPickManager& RayPickManager::getInstance() { + static RayPickManager instance; + return instance; +} + +void RayPickManager::update() { + /*** + - somehow calculate minimum number of intersection tests, update raypicks accordingly + -one option : + loop over all raypicks{ loop over all necessary intersection tests and take min distance less than rayPick->maxDistance, but keep cache of this frame's previous tests to prevent duplicate intersection tests } + ***/ +} + +unsigned int RayPickManager::addRayPick(std::shared_ptr rayPick) { + // TODO: + // use lock and defer adding to prevent issues + _rayPicks[_nextUID] = rayPick; + return _nextUID++; +} + +void RayPickManager::removeRayPick(const unsigned int uid) { + // TODO: + // use lock and defer removing to prevent issues + _rayPicks.remove(uid); +} + +void RayPickManager::enableRayPick(const unsigned int uid) { + // TODO: + // use lock and defer enabling to prevent issues + if (_rayPicks.contains(uid)) { + _rayPicks[uid]->enable(); + } +} + +void RayPickManager::disableRayPick(const unsigned int uid) { + // TODO: + // use lock and defer disabling to prevent issues + if (_rayPicks.contains(uid)) { + _rayPicks[uid]->disable(); + } +} diff --git a/libraries/shared/src/RayPickManager.h b/libraries/shared/src/RayPickManager.h new file mode 100644 index 0000000000..c296c14af7 --- /dev/null +++ b/libraries/shared/src/RayPickManager.h @@ -0,0 +1,50 @@ +// +// RayPickManager.h +// libraries/shared/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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_RayPickManager_h +#define hifi_RayPickManager_h + +#include +#include + +class RayPick; + +enum RayPickMask { + PICK_NOTHING = 0, + PICK_ENTITIES = 1, + PICK_AVATARS = 2, + PICK_OVERLAYS = 4, + PICK_HUD = 8, + + PICK_BOUNDING_BOX = 16, // if not set, picks again physics mesh (can't pick against graphics mesh, yet) + + PICK_INCLUDE_INVISIBLE = 32, // if not set, will not intersect invisible elements, otherwise, intersects both visible and invisible elements + + PICK_ALL_INTERSECTIONS = 64 // if not set, returns closest intersection, otherwise, returns list of all intersections +}; + +class RayPickManager { + +public: + static RayPickManager& getInstance(); + + void update(); + unsigned int addRayPick(std::shared_ptr rayPick); + void removeRayPick(const unsigned int uid); + void enableRayPick(const unsigned int uid); + void disableRayPick(const unsigned int uid); + +private: + QHash> _rayPicks; + unsigned int _nextUID { 1 }; // 0 is invalid + +}; + +#endif hifi_RayPickManager_h \ No newline at end of file diff --git a/libraries/shared/src/StaticRayPick.cpp b/libraries/shared/src/StaticRayPick.cpp new file mode 100644 index 0000000000..2ebe431b00 --- /dev/null +++ b/libraries/shared/src/StaticRayPick.cpp @@ -0,0 +1,17 @@ +// +// StaticRayPick.cpp +// libraries/shared/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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 "StaticRayPick.h" + +StaticRayPick::StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance, const bool enabled) : + RayPick(filter, maxDistance, enabled), + _pickRay(position, direction) +{ +} diff --git a/libraries/shared/src/StaticRayPick.h b/libraries/shared/src/StaticRayPick.h new file mode 100644 index 0000000000..6424b731c7 --- /dev/null +++ b/libraries/shared/src/StaticRayPick.h @@ -0,0 +1,28 @@ +// +// StaticRayPick.h +// libraries/shared/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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_StaticRayPick_h +#define hifi_StaticRayPick_h + +#include "RayPick.h" + +class StaticRayPick : public RayPick { + +public: + StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance = 0.0f, const bool enabled = false); + + const PickRay getPickRay() override { return _pickRay; }; + +private: + PickRay _pickRay; + +}; + +#endif hifi_StaticRayPick_h \ No newline at end of file From 15ec38b30202a7953b4374183524e2da93ae1950 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 12 Jul 2017 14:19:53 -0700 Subject: [PATCH 02/42] expose RayPickMask to JS, move everything to interface/src/raypick to prevent dependency issues, start working on RayPickManager::update (needs testing) --- interface/src/Application.cpp | 6 +- .../src/raypick}/JointRayPick.cpp | 9 +- .../src/raypick}/JointRayPick.h | 8 +- .../src/raypick}/LaserPointer.cpp | 6 +- .../src/raypick}/LaserPointer.h | 6 +- .../src/raypick}/LaserPointerManager.cpp | 6 +- .../src/raypick}/LaserPointerManager.h | 6 +- .../LaserPointerScriptingInterface.cpp | 19 ++- .../LaserPointerScriptingInterface.h | 4 +- .../src => interface/src/raypick}/RayPick.cpp | 2 +- .../src => interface/src/raypick}/RayPick.h | 2 +- interface/src/raypick/RayPickManager.cpp | 145 ++++++++++++++++++ interface/src/raypick/RayPickManager.h | 97 ++++++++++++ .../src/raypick}/StaticRayPick.cpp | 2 +- .../src/raypick}/StaticRayPick.h | 2 +- libraries/shared/src/RayPickManager.cpp | 54 ------- libraries/shared/src/RayPickManager.h | 50 ------ 17 files changed, 285 insertions(+), 139 deletions(-) rename {libraries/shared/src => interface/src/raypick}/JointRayPick.cpp (64%) rename {libraries/shared/src => interface/src/raypick}/JointRayPick.h (65%) rename {libraries/controllers/src/controllers => interface/src/raypick}/LaserPointer.cpp (72%) rename {libraries/controllers/src/controllers => interface/src/raypick}/LaserPointer.h (76%) rename {libraries/controllers/src/controllers => interface/src/raypick}/LaserPointerManager.cpp (80%) rename {libraries/controllers/src/controllers => interface/src/raypick}/LaserPointerManager.h (83%) rename interface/src/{ => raypick}/LaserPointerScriptingInterface.cpp (73%) rename interface/src/{ => raypick}/LaserPointerScriptingInterface.h (95%) rename {libraries/shared/src => interface/src/raypick}/RayPick.cpp (94%) rename {libraries/shared/src => interface/src/raypick}/RayPick.h (97%) create mode 100644 interface/src/raypick/RayPickManager.cpp create mode 100644 interface/src/raypick/RayPickManager.h rename {libraries/shared/src => interface/src/raypick}/StaticRayPick.cpp (95%) rename {libraries/shared/src => interface/src/raypick}/StaticRayPick.h (96%) delete mode 100644 libraries/shared/src/RayPickManager.cpp delete mode 100644 libraries/shared/src/RayPickManager.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 16e322a142..6fad34b6f1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -190,8 +190,8 @@ #include #include #include -#include "LaserPointerScriptingInterface.h" -#include +#include +#include // On Windows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU // FIXME seems to be broken. @@ -5821,6 +5821,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("EntityScriptServerLog", entityScriptServerLog.data()); scriptEngine->registerGlobalObject("AvatarInputs", AvatarInputs::getInstance()); + scriptEngine->registerGlobalObject("RayPick", &RayPickManager::getInstance()); + qScriptRegisterMetaType(scriptEngine, OverlayIDtoScriptValue, OverlayIDfromScriptValue); // connect this script engines printedMessage signal to the global ScriptEngines these various messages diff --git a/libraries/shared/src/JointRayPick.cpp b/interface/src/raypick/JointRayPick.cpp similarity index 64% rename from libraries/shared/src/JointRayPick.cpp rename to interface/src/raypick/JointRayPick.cpp index 4a645fa3fd..8ea48f842f 100644 --- a/libraries/shared/src/JointRayPick.cpp +++ b/interface/src/raypick/JointRayPick.cpp @@ -1,6 +1,6 @@ // // JointRayPick.cpp -// libraries/shared/src +// interface/src/raypick // // Created by Sam Gondelman 7/11/2017 // Copyright 2017 High Fidelity, Inc. @@ -10,17 +10,18 @@ // #include "JointRayPick.h" -JointRayPick::JointRayPick(const QString& jointName, const Transform& offsetTransform, const uint16_t filter, const float maxDistance, const bool enabled) : +JointRayPick::JointRayPick(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, const bool enabled) : RayPick(filter, maxDistance, enabled), _jointName(jointName), - _offsetTransform(offsetTransform) + _posOffset(posOffset), + _dirOffset(dirOffset) { } const PickRay JointRayPick::getPickRay() { // TODO: // get pose for _jointName - // apply _offsetTransform + // apply offset // create and return PickRay return PickRay(); } diff --git a/libraries/shared/src/JointRayPick.h b/interface/src/raypick/JointRayPick.h similarity index 65% rename from libraries/shared/src/JointRayPick.h rename to interface/src/raypick/JointRayPick.h index cd5de79c69..4b2f7d1071 100644 --- a/libraries/shared/src/JointRayPick.h +++ b/interface/src/raypick/JointRayPick.h @@ -1,6 +1,6 @@ // // JointRayPick.h -// libraries/shared/src +// interface/src/raypick // // Created by Sam Gondelman 7/11/2017 // Copyright 2017 High Fidelity, Inc. @@ -14,18 +14,18 @@ #include "RayPick.h" #include -#include "Transform.h" class JointRayPick : public RayPick { public: - JointRayPick(const QString& jointName, const Transform& offsetTransform, const uint16_t filter, const float maxDistance = 0.0f, const bool enabled = false); + JointRayPick(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance = 0.0f, const bool enabled = false); const PickRay getPickRay() override; private: QString _jointName; - Transform _offsetTransform; + glm::vec3 _posOffset; + glm::vec3 _dirOffset; }; diff --git a/libraries/controllers/src/controllers/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp similarity index 72% rename from libraries/controllers/src/controllers/LaserPointer.cpp rename to interface/src/raypick/LaserPointer.cpp index 4f3adce875..898df04345 100644 --- a/libraries/controllers/src/controllers/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -1,6 +1,6 @@ // // LaserPointer.cpp -// libraries/controllers/src +// interface/src/raypick // // Created by Sam Gondelman 7/11/2017 // Copyright 2017 High Fidelity, Inc. @@ -13,9 +13,9 @@ #include "RayPickManager.h" #include "JointRayPick.h" -LaserPointer::LaserPointer(const QString& jointName, const Transform& offsetTransform, const uint16_t filter, const float maxDistance, const bool enabled) +LaserPointer::LaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, const bool enabled) { - _rayPickUID = RayPickManager::getInstance().addRayPick(std::make_shared(jointName, offsetTransform, filter, maxDistance, enabled)); + _rayPickUID = RayPickManager::getInstance().addRayPick(std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled)); } LaserPointer::~LaserPointer() { diff --git a/libraries/controllers/src/controllers/LaserPointer.h b/interface/src/raypick/LaserPointer.h similarity index 76% rename from libraries/controllers/src/controllers/LaserPointer.h rename to interface/src/raypick/LaserPointer.h index d09defe7b2..93dd33f305 100644 --- a/libraries/controllers/src/controllers/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -1,6 +1,6 @@ // // LaserPointer.h -// libraries/controllers/src +// interface/src/raypick // // Created by Sam Gondelman 7/11/2017 // Copyright 2017 High Fidelity, Inc. @@ -12,12 +12,12 @@ #define hifi_LaserPointer_h #include -#include "Transform.h" +#include "glm/glm.hpp" class LaserPointer { public: - LaserPointer(const QString& jointName, const Transform& offsetTransform, const uint16_t filter, const float maxDistance, bool enabled); + LaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, bool enabled); ~LaserPointer(); unsigned int getUID() { return _rayPickUID; } diff --git a/libraries/controllers/src/controllers/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp similarity index 80% rename from libraries/controllers/src/controllers/LaserPointerManager.cpp rename to interface/src/raypick/LaserPointerManager.cpp index adea77f530..1be2087ffb 100644 --- a/libraries/controllers/src/controllers/LaserPointerManager.cpp +++ b/interface/src/raypick/LaserPointerManager.cpp @@ -1,6 +1,6 @@ // // LaserPointerManager.cpp -// libraries/controllers/src +// interface/src/raypick // // Created by Sam Gondelman 7/11/2017 // Copyright 2017 High Fidelity, Inc. @@ -16,8 +16,8 @@ LaserPointerManager& LaserPointerManager::getInstance() { return instance; } -unsigned int LaserPointerManager::createLaserPointer(const QString& jointName, const Transform& offsetTransform, const uint16_t filter, const float maxDistance, bool enabled) { - std::shared_ptr laserPointer = std::make_shared(jointName, offsetTransform, filter, maxDistance, enabled); +unsigned int LaserPointerManager::createLaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, bool enabled) { + std::shared_ptr laserPointer = std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled); unsigned int uid = laserPointer->getUID(); _laserPointers[uid] = laserPointer; return uid; diff --git a/libraries/controllers/src/controllers/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h similarity index 83% rename from libraries/controllers/src/controllers/LaserPointerManager.h rename to interface/src/raypick/LaserPointerManager.h index 28d354cf98..503db5e459 100644 --- a/libraries/controllers/src/controllers/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -1,6 +1,6 @@ // // LaserPointerManager.h -// libraries/controllers/src +// interface/src/raypick // // Created by Sam Gondelman 7/11/2017 // Copyright 2017 High Fidelity, Inc. @@ -14,7 +14,7 @@ #include #include #include -#include "Transform.h" +#include class LaserPointer; @@ -23,7 +23,7 @@ class LaserPointerManager { public: static LaserPointerManager& getInstance(); - unsigned int createLaserPointer(const QString& jointName, const Transform& offsetTransform, const uint16_t filter, const float maxDistance, bool enabled); + unsigned int createLaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, bool enabled); void removeLaserPointer(const unsigned int uid) { _laserPointers.remove(uid); } void enableLaserPointer(const unsigned int uid); void disableLaserPointer(const unsigned int uid); diff --git a/interface/src/LaserPointerScriptingInterface.cpp b/interface/src/raypick/LaserPointerScriptingInterface.cpp similarity index 73% rename from interface/src/LaserPointerScriptingInterface.cpp rename to interface/src/raypick/LaserPointerScriptingInterface.cpp index a5770a9252..f8bba2bf04 100644 --- a/interface/src/LaserPointerScriptingInterface.cpp +++ b/interface/src/raypick/LaserPointerScriptingInterface.cpp @@ -1,6 +1,6 @@ // // LaserPointerScriptingInterface.cpp -// interface/src +// interface/src/raypick // // Created by Sam Gondelman 7/11/2017 // Copyright 2017 High Fidelity, Inc. @@ -12,7 +12,8 @@ #include "LaserPointerScriptingInterface.h" #include -#include "Transform.h" +#include "RegisteredMetaTypes.h" +#include "GLMHelpers.h" LaserPointerScriptingInterface* LaserPointerScriptingInterface::getInstance() { static LaserPointerScriptingInterface instance; @@ -25,10 +26,14 @@ uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& prop if (propertyMap["joint"].isValid()) { QString jointName = propertyMap["joint"].toString(); - Transform offsetTransform; - if (propertyMap["offsetTransform"].isValid()) { - // TODO: - // convert transform + glm::vec3 posOffset = Vectors::ZERO; + if (propertyMap["posOffset"].isValid()) { + posOffset = vec3FromVariant(propertyMap["posOffset"]); + } + + glm::vec3 dirOffset = Vectors::FRONT; + if (propertyMap["dirOffset"].isValid()) { + posOffset = vec3FromVariant(propertyMap["dirOffset"]); } uint16_t filter = 0; @@ -49,7 +54,7 @@ uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& prop // TODO: // handle render state properties - return LaserPointerManager::getInstance().createLaserPointer(jointName, offsetTransform, filter, maxDistance, enabled); + return LaserPointerManager::getInstance().createLaserPointer(jointName, posOffset, dirOffset, filter, maxDistance, enabled); } else { return 0; } diff --git a/interface/src/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h similarity index 95% rename from interface/src/LaserPointerScriptingInterface.h rename to interface/src/raypick/LaserPointerScriptingInterface.h index c455843d03..428d722bbb 100644 --- a/interface/src/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -1,6 +1,6 @@ // // LaserPointerScriptingInterface.h -// interface/src +// interface/src/raypick // // Created by Sam Gondelman 7/11/2017 // Copyright 2017 High Fidelity, Inc. @@ -13,7 +13,7 @@ #include -#include "controllers\LaserPointerManager.h" +#include "LaserPointerManager.h" class LaserPointerScriptingInterface : public QObject { Q_OBJECT diff --git a/libraries/shared/src/RayPick.cpp b/interface/src/raypick/RayPick.cpp similarity index 94% rename from libraries/shared/src/RayPick.cpp rename to interface/src/raypick/RayPick.cpp index 674913e2e0..e807ef23ff 100644 --- a/libraries/shared/src/RayPick.cpp +++ b/interface/src/raypick/RayPick.cpp @@ -1,6 +1,6 @@ // // RayPick.cpp -// libraries/shared/src +// interface/src/raypick // // Created by Sam Gondelman 7/11/2017 // Copyright 2017 High Fidelity, Inc. diff --git a/libraries/shared/src/RayPick.h b/interface/src/raypick/RayPick.h similarity index 97% rename from libraries/shared/src/RayPick.h rename to interface/src/raypick/RayPick.h index 8a292bf5f7..7ad2d9f83f 100644 --- a/libraries/shared/src/RayPick.h +++ b/interface/src/raypick/RayPick.h @@ -1,6 +1,6 @@ // // RayPick.h -// libraries/shared/src +// interface/src/raypick // // Created by Sam Gondelman 7/11/2017 // Copyright 2017 High Fidelity, Inc. diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp new file mode 100644 index 0000000000..bb25c8f168 --- /dev/null +++ b/interface/src/raypick/RayPickManager.cpp @@ -0,0 +1,145 @@ +// +// RayPickManager.cpp +// interface/src/raypick +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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 "RayPickManager.h" +#include "RayPick.h" + +#include "Application.h" +#include "EntityScriptingInterface.h" +#include "ui/overlays/Overlays.h" +#include "avatar/AvatarManager.h" +#include "DependencyManager.h" + +RayPickManager& RayPickManager::getInstance() { + static RayPickManager instance; + return instance; +} + +// Returns true if this ray exists in the cache, and if it does, update res if the cached result is closer +bool RayPickManager::checkAndCompareCachedResults(std::shared_ptr rayPick, QPair& ray, QHash, QHash> cache, RayPickResult& res, unsigned int mask) { + if (cache.contains(ray) && cache[ray].contains(mask)) { + if (cache[ray][mask].getDistance() < res.getDistance() && cache[ray][mask].getDistance() < rayPick->getMaxDistance()) { + res = cache[ray][mask]; + } + return true; + } + return false; +} + +void RayPickManager::update() { + QHash, QHash> results; + for (auto &rayPick : _rayPicks) { + if (!rayPick->isEnabled() || rayPick->getFilter() == RayPickMask::PICK_NOTHING || rayPick->getMaxDistance() < 0.0f) { + continue; + } + + PickRay ray = rayPick->getPickRay(); + // TODO: + // get rid of this and make PickRay hashable + QPair rayKey = QPair(ray.origin, ray.direction); + RayPickResult res; // start with FLT_MAX distance + + if (rayPick->getFilter() & RayPickMask::PICK_ENTITIES) { + RayToEntityIntersectionResult entityRes; + if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE && rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE) { + if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_ENTITIES | RayPickMask::PICK_INCLUDE_INVISIBLE | RayPickMask::PICK_INCLUDE_NONCOLLIDABLE)) { + entityRes = DependencyManager::get()->findRayIntersection(ray, true, QScriptValue(), QScriptValue(), false, false); + } + } + else if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE) { + if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_ENTITIES | RayPickMask::PICK_INCLUDE_INVISIBLE)) { + entityRes = DependencyManager::get()->findRayIntersection(ray, true, QScriptValue(), QScriptValue(), false, true); + } + } + else if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE) { + if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_ENTITIES | RayPickMask::PICK_INCLUDE_NONCOLLIDABLE)) { + entityRes = DependencyManager::get()->findRayIntersection(ray, true, QScriptValue(), QScriptValue(), true, false); + } + } + else { + if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_ENTITIES)) { + entityRes = DependencyManager::get()->findRayIntersection(ray, true, QScriptValue(), QScriptValue(), true, true); + } + } + if (entityRes.intersects) { + res = RayPickResult(entityRes.entityID, entityRes.distance, entityRes.intersection, entityRes.surfaceNormal); + // add to cache + } + } + + if (rayPick->getFilter() & RayPickMask::PICK_OVERLAYS) { + RayToOverlayIntersectionResult overlayRes; + if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE && rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE) { + if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_OVERLAYS | RayPickMask::PICK_INCLUDE_INVISIBLE | RayPickMask::PICK_INCLUDE_NONCOLLIDABLE)) { + overlayRes = qApp->getOverlays().findRayIntersection(ray, true, QScriptValue(), QScriptValue(), false, false); + } + } + else if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE) { + if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_OVERLAYS | RayPickMask::PICK_INCLUDE_INVISIBLE)) { + overlayRes = qApp->getOverlays().findRayIntersection(ray, true, QScriptValue(), QScriptValue(), false, true); + } + } + else if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE) { + if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_OVERLAYS | RayPickMask::PICK_INCLUDE_NONCOLLIDABLE)) { + overlayRes = qApp->getOverlays().findRayIntersection(ray, true, QScriptValue(), QScriptValue(), true, false); + } + } + else { + if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_OVERLAYS)) { + overlayRes = qApp->getOverlays().findRayIntersection(ray, true, QScriptValue(), QScriptValue(), true, true); + } + } + if (overlayRes.intersects) { + res = RayPickResult(overlayRes.overlayID, overlayRes.distance, overlayRes.intersection, overlayRes.surfaceNormal); + // add to cache + } + } + + if (rayPick->getFilter() & RayPickMask::PICK_AVATARS) { + if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_AVATARS)) { + RayToAvatarIntersectionResult avatarRes = DependencyManager::get()->findRayIntersection(ray, QScriptValue(), QScriptValue()); + if (avatarRes.intersects) { + res = RayPickResult(avatarRes.avatarID, avatarRes.distance, avatarRes.intersection); + // add to cache + } + } + } + + } +} + +unsigned int RayPickManager::addRayPick(std::shared_ptr rayPick) { + // TODO: + // use lock and defer adding to prevent issues + _rayPicks[_nextUID] = rayPick; + return _nextUID++; +} + +void RayPickManager::removeRayPick(const unsigned int uid) { + // TODO: + // use lock and defer removing to prevent issues + _rayPicks.remove(uid); +} + +void RayPickManager::enableRayPick(const unsigned int uid) { + // TODO: + // use lock and defer enabling to prevent issues + if (_rayPicks.contains(uid)) { + _rayPicks[uid]->enable(); + } +} + +void RayPickManager::disableRayPick(const unsigned int uid) { + // TODO: + // use lock and defer disabling to prevent issues + if (_rayPicks.contains(uid)) { + _rayPicks[uid]->disable(); + } +} diff --git a/interface/src/raypick/RayPickManager.h b/interface/src/raypick/RayPickManager.h new file mode 100644 index 0000000000..ac700118f6 --- /dev/null +++ b/interface/src/raypick/RayPickManager.h @@ -0,0 +1,97 @@ +// +// RayPickManager.h +// interface/src/raypick +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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_RayPickManager_h +#define hifi_RayPickManager_h + +#include "RegisteredMetaTypes.h" + +#include +#include +#include + +class RayPick; + +enum RayPickMask { + PICK_NOTHING = 0, + PICK_ENTITIES = 1, + PICK_OVERLAYS = 2, + PICK_AVATARS = 4, + PICK_HUD = 8, + + PICK_BOUNDING_BOX = 16, // if not set, picks again physics mesh (can't pick against graphics mesh, yet) + + PICK_INCLUDE_INVISIBLE = 32, // if not set, will not intersect invisible elements, otherwise, intersects both visible and invisible elements + PICK_INCLUDE_NONCOLLIDABLE = 64, // if not set, will not intersect noncollidable elements, otherwise, intersects both collidable and noncollidable elements + + PICK_ALL_INTERSECTIONS = 128 // if not set, returns closest intersection, otherwise, returns list of all intersections +}; + +// TODO: +// move/improve this and register it as a meta type +class RayPickResult { + +public: + RayPickResult() {} + RayPickResult(const QUuid& objectID, const float distance, const glm::vec3& intersection, const glm::vec3& surfaceNormal = glm::vec3(NAN)) : + _objectID(objectID), _distance(distance), _intersection(intersection), _surfaceNormal(surfaceNormal) {} + + const QUuid& getUID() { return _objectID; } + const float getDistance() { return _distance; } + const glm::vec3& getIntersection() { return _intersection; } + const glm::vec3& getSurfaceNormal() { return _surfaceNormal; } + +private: + //Type type; + QUuid _objectID { 0 }; + float _distance { FLT_MAX }; + glm::vec3 _intersection { NAN }; + glm::vec3 _surfaceNormal { NAN }; +}; + +class RayPickManager : public QObject { + Q_OBJECT + Q_PROPERTY(unsigned int PICK_NOTHING READ PICK_NOTHING CONSTANT) + Q_PROPERTY(unsigned int PICK_ENTITIES READ PICK_ENTITIES CONSTANT) + Q_PROPERTY(unsigned int PICK_OVERLAYS READ PICK_OVERLAYS CONSTANT) + Q_PROPERTY(unsigned int PICK_AVATARS READ PICK_AVATARS CONSTANT) + Q_PROPERTY(unsigned int PICK_HUD READ PICK_HUD CONSTANT) + Q_PROPERTY(unsigned int PICK_BOUNDING_BOX READ PICK_BOUNDING_BOX CONSTANT) + Q_PROPERTY(unsigned int PICK_INCLUDE_INVISIBLE READ PICK_INCLUDE_INVISIBLE CONSTANT) + Q_PROPERTY(unsigned int PICK_INCLUDE_NONCOLLIDABLE READ PICK_INCLUDE_NONCOLLIDABLE CONSTANT) + Q_PROPERTY(unsigned int PICK_ALL_INTERSECTIONS READ PICK_ALL_INTERSECTIONS CONSTANT) + +public: + static RayPickManager& getInstance(); + + void update(); + bool RayPickManager::checkAndCompareCachedResults(std::shared_ptr rayPick, QPair& ray, QHash, QHash> cache, RayPickResult& res, unsigned int mask); + unsigned int addRayPick(std::shared_ptr rayPick); + void removeRayPick(const unsigned int uid); + void enableRayPick(const unsigned int uid); + void disableRayPick(const unsigned int uid); + +private: + QHash> _rayPicks; + unsigned int _nextUID { 1 }; // 0 is invalid + + const unsigned int PICK_NOTHING() { return RayPickMask::PICK_NOTHING; } + const unsigned int PICK_ENTITIES() { return RayPickMask::PICK_ENTITIES; } + const unsigned int PICK_OVERLAYS() { return RayPickMask::PICK_OVERLAYS; } + const unsigned int PICK_AVATARS() { return RayPickMask::PICK_AVATARS; } + const unsigned int PICK_HUD() { return RayPickMask::PICK_HUD; } + const unsigned int PICK_BOUNDING_BOX() { return RayPickMask::PICK_BOUNDING_BOX; } + const unsigned int PICK_INCLUDE_INVISIBLE() { return RayPickMask::PICK_INCLUDE_INVISIBLE; } + const unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return RayPickMask::PICK_INCLUDE_NONCOLLIDABLE; } + const unsigned int PICK_ALL_INTERSECTIONS() { return RayPickMask::PICK_ALL_INTERSECTIONS; } + +}; + +#endif hifi_RayPickManager_h \ No newline at end of file diff --git a/libraries/shared/src/StaticRayPick.cpp b/interface/src/raypick/StaticRayPick.cpp similarity index 95% rename from libraries/shared/src/StaticRayPick.cpp rename to interface/src/raypick/StaticRayPick.cpp index 2ebe431b00..b3bce16b58 100644 --- a/libraries/shared/src/StaticRayPick.cpp +++ b/interface/src/raypick/StaticRayPick.cpp @@ -1,6 +1,6 @@ // // StaticRayPick.cpp -// libraries/shared/src +// interface/src/raypick // // Created by Sam Gondelman 7/11/2017 // Copyright 2017 High Fidelity, Inc. diff --git a/libraries/shared/src/StaticRayPick.h b/interface/src/raypick/StaticRayPick.h similarity index 96% rename from libraries/shared/src/StaticRayPick.h rename to interface/src/raypick/StaticRayPick.h index 6424b731c7..6d3df21859 100644 --- a/libraries/shared/src/StaticRayPick.h +++ b/interface/src/raypick/StaticRayPick.h @@ -1,6 +1,6 @@ // // StaticRayPick.h -// libraries/shared/src +// interface/src/raypick // // Created by Sam Gondelman 7/11/2017 // Copyright 2017 High Fidelity, Inc. diff --git a/libraries/shared/src/RayPickManager.cpp b/libraries/shared/src/RayPickManager.cpp deleted file mode 100644 index 5c5ebd8c10..0000000000 --- a/libraries/shared/src/RayPickManager.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// -// RayPickManager.cpp -// libraries/shared/src -// -// Created by Sam Gondelman 7/11/2017 -// Copyright 2017 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 "RayPickManager.h" -#include "RayPick.h" - -RayPickManager& RayPickManager::getInstance() { - static RayPickManager instance; - return instance; -} - -void RayPickManager::update() { - /*** - - somehow calculate minimum number of intersection tests, update raypicks accordingly - -one option : - loop over all raypicks{ loop over all necessary intersection tests and take min distance less than rayPick->maxDistance, but keep cache of this frame's previous tests to prevent duplicate intersection tests } - ***/ -} - -unsigned int RayPickManager::addRayPick(std::shared_ptr rayPick) { - // TODO: - // use lock and defer adding to prevent issues - _rayPicks[_nextUID] = rayPick; - return _nextUID++; -} - -void RayPickManager::removeRayPick(const unsigned int uid) { - // TODO: - // use lock and defer removing to prevent issues - _rayPicks.remove(uid); -} - -void RayPickManager::enableRayPick(const unsigned int uid) { - // TODO: - // use lock and defer enabling to prevent issues - if (_rayPicks.contains(uid)) { - _rayPicks[uid]->enable(); - } -} - -void RayPickManager::disableRayPick(const unsigned int uid) { - // TODO: - // use lock and defer disabling to prevent issues - if (_rayPicks.contains(uid)) { - _rayPicks[uid]->disable(); - } -} diff --git a/libraries/shared/src/RayPickManager.h b/libraries/shared/src/RayPickManager.h deleted file mode 100644 index c296c14af7..0000000000 --- a/libraries/shared/src/RayPickManager.h +++ /dev/null @@ -1,50 +0,0 @@ -// -// RayPickManager.h -// libraries/shared/src -// -// Created by Sam Gondelman 7/11/2017 -// Copyright 2017 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_RayPickManager_h -#define hifi_RayPickManager_h - -#include -#include - -class RayPick; - -enum RayPickMask { - PICK_NOTHING = 0, - PICK_ENTITIES = 1, - PICK_AVATARS = 2, - PICK_OVERLAYS = 4, - PICK_HUD = 8, - - PICK_BOUNDING_BOX = 16, // if not set, picks again physics mesh (can't pick against graphics mesh, yet) - - PICK_INCLUDE_INVISIBLE = 32, // if not set, will not intersect invisible elements, otherwise, intersects both visible and invisible elements - - PICK_ALL_INTERSECTIONS = 64 // if not set, returns closest intersection, otherwise, returns list of all intersections -}; - -class RayPickManager { - -public: - static RayPickManager& getInstance(); - - void update(); - unsigned int addRayPick(std::shared_ptr rayPick); - void removeRayPick(const unsigned int uid); - void enableRayPick(const unsigned int uid); - void disableRayPick(const unsigned int uid); - -private: - QHash> _rayPicks; - unsigned int _nextUID { 1 }; // 0 is invalid - -}; - -#endif hifi_RayPickManager_h \ No newline at end of file From 3ac369d782c3936891012a142df3e8b9f1543489 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 11 Jul 2017 17:07:53 -0700 Subject: [PATCH 03/42] framework for LaserPointers and abstracted RayPicking on C++ side, including JS API --- interface/src/Application.cpp | 8 +++ .../src/LaserPointerScriptingInterface.cpp | 56 +++++++++++++++++++ .../src/LaserPointerScriptingInterface.h | 33 +++++++++++ .../src/controllers/LaserPointer.cpp | 35 ++++++++++++ .../src/controllers/LaserPointer.h | 34 +++++++++++ .../src/controllers/LaserPointerManager.cpp | 36 ++++++++++++ .../src/controllers/LaserPointerManager.h | 36 ++++++++++++ libraries/shared/src/JointRayPick.cpp | 26 +++++++++ libraries/shared/src/JointRayPick.h | 32 +++++++++++ libraries/shared/src/RayPick.cpp | 18 ++++++ libraries/shared/src/RayPick.h | 42 ++++++++++++++ libraries/shared/src/RayPickManager.cpp | 54 ++++++++++++++++++ libraries/shared/src/RayPickManager.h | 50 +++++++++++++++++ libraries/shared/src/StaticRayPick.cpp | 17 ++++++ libraries/shared/src/StaticRayPick.h | 28 ++++++++++ 15 files changed, 505 insertions(+) create mode 100644 interface/src/LaserPointerScriptingInterface.cpp create mode 100644 interface/src/LaserPointerScriptingInterface.h create mode 100644 libraries/controllers/src/controllers/LaserPointer.cpp create mode 100644 libraries/controllers/src/controllers/LaserPointer.h create mode 100644 libraries/controllers/src/controllers/LaserPointerManager.cpp create mode 100644 libraries/controllers/src/controllers/LaserPointerManager.h create mode 100644 libraries/shared/src/JointRayPick.cpp create mode 100644 libraries/shared/src/JointRayPick.h create mode 100644 libraries/shared/src/RayPick.cpp create mode 100644 libraries/shared/src/RayPick.h create mode 100644 libraries/shared/src/RayPickManager.cpp create mode 100644 libraries/shared/src/RayPickManager.h create mode 100644 libraries/shared/src/StaticRayPick.cpp create mode 100644 libraries/shared/src/StaticRayPick.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ddd1870723..16e322a142 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -190,6 +190,8 @@ #include #include #include +#include "LaserPointerScriptingInterface.h" +#include // On Windows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU // FIXME seems to be broken. @@ -4916,6 +4918,11 @@ void Application::update(float deltaTime) { _overlays.update(deltaTime); } + { + PROFILE_RANGE(app, "RayPick"); + RayPickManager::getInstance().update(); + } + // Update _viewFrustum with latest camera and view frustum data... // NOTE: we get this from the view frustum, to make it simpler, since the // loadViewFrumstum() method will get the correct details from the camera @@ -5761,6 +5768,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("AudioScope", DependencyManager::get().data()); scriptEngine->registerGlobalObject("AvatarBookmarks", DependencyManager::get().data()); scriptEngine->registerGlobalObject("LocationBookmarks", DependencyManager::get().data()); + scriptEngine->registerGlobalObject("LaserPointers", LaserPointerScriptingInterface::getInstance()); // Caches scriptEngine->registerGlobalObject("AnimationCache", DependencyManager::get().data()); diff --git a/interface/src/LaserPointerScriptingInterface.cpp b/interface/src/LaserPointerScriptingInterface.cpp new file mode 100644 index 0000000000..a5770a9252 --- /dev/null +++ b/interface/src/LaserPointerScriptingInterface.cpp @@ -0,0 +1,56 @@ +// +// LaserPointerScriptingInterface.cpp +// interface/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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 "LaserPointerScriptingInterface.h" + +#include +#include "Transform.h" + +LaserPointerScriptingInterface* LaserPointerScriptingInterface::getInstance() { + static LaserPointerScriptingInterface instance; + return &instance; +} + +uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& properties) { + QVariantMap propertyMap = properties.toMap(); + + if (propertyMap["joint"].isValid()) { + QString jointName = propertyMap["joint"].toString(); + + Transform offsetTransform; + if (propertyMap["offsetTransform"].isValid()) { + // TODO: + // convert transform + } + + uint16_t filter = 0; + if (propertyMap["filter"].isValid()) { + filter = propertyMap["filter"].toUInt(); + } + + float maxDistance = 0.0f; + if (propertyMap["maxDistance"].isValid()) { + maxDistance = propertyMap["maxDistance"].toFloat(); + } + + bool enabled = false; + if (propertyMap["enabled"].isValid()) { + enabled = propertyMap["enabled"].toBool(); + } + + // TODO: + // handle render state properties + + return LaserPointerManager::getInstance().createLaserPointer(jointName, offsetTransform, filter, maxDistance, enabled); + } else { + return 0; + } +} \ No newline at end of file diff --git a/interface/src/LaserPointerScriptingInterface.h b/interface/src/LaserPointerScriptingInterface.h new file mode 100644 index 0000000000..c455843d03 --- /dev/null +++ b/interface/src/LaserPointerScriptingInterface.h @@ -0,0 +1,33 @@ +// +// LaserPointerScriptingInterface.h +// interface/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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_LaserPointerScriptingInterface_h +#define hifi_LaserPointerScriptingInterface_h + +#include + +#include "controllers\LaserPointerManager.h" + +class LaserPointerScriptingInterface : public QObject { + Q_OBJECT + +public: + static LaserPointerScriptingInterface* getInstance(); + +public slots: + Q_INVOKABLE unsigned int createLaserPointer(const QVariant& properties); + Q_INVOKABLE void enableLaserPointer(unsigned int uid) { LaserPointerManager::getInstance().enableLaserPointer(uid); } + Q_INVOKABLE void disableLaserPointer(unsigned int uid) { LaserPointerManager::getInstance().disableLaserPointer(uid); } + Q_INVOKABLE void removeLaserPointer(unsigned int uid) { LaserPointerManager::getInstance().removeLaserPointer(uid); } + //Q_INVOKABLE IntersectionResults getLaserPointerCollisionResults(unsigned int uid) { LaserPointerManager::getInstance().getLaserPointerCollisionResults(uid); } + +}; + +#endif hifi_LaserPointerScriptingInterface_h \ No newline at end of file diff --git a/libraries/controllers/src/controllers/LaserPointer.cpp b/libraries/controllers/src/controllers/LaserPointer.cpp new file mode 100644 index 0000000000..4f3adce875 --- /dev/null +++ b/libraries/controllers/src/controllers/LaserPointer.cpp @@ -0,0 +1,35 @@ +// +// LaserPointer.cpp +// libraries/controllers/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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 "LaserPointer.h" + +#include "RayPickManager.h" +#include "JointRayPick.h" + +LaserPointer::LaserPointer(const QString& jointName, const Transform& offsetTransform, const uint16_t filter, const float maxDistance, const bool enabled) +{ + _rayPickUID = RayPickManager::getInstance().addRayPick(std::make_shared(jointName, offsetTransform, filter, maxDistance, enabled)); +} + +LaserPointer::~LaserPointer() { + RayPickManager::getInstance().removeRayPick(_rayPickUID); +} + +void LaserPointer::enable() { + RayPickManager::getInstance().enableRayPick(_rayPickUID); + // TODO: + // turn on rendering +} + +void LaserPointer::disable() { + RayPickManager::getInstance().disableRayPick(_rayPickUID); + // TODO: + // turn off rendering +} \ No newline at end of file diff --git a/libraries/controllers/src/controllers/LaserPointer.h b/libraries/controllers/src/controllers/LaserPointer.h new file mode 100644 index 0000000000..d09defe7b2 --- /dev/null +++ b/libraries/controllers/src/controllers/LaserPointer.h @@ -0,0 +1,34 @@ +// +// LaserPointer.h +// libraries/controllers/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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_LaserPointer_h +#define hifi_LaserPointer_h + +#include +#include "Transform.h" + +class LaserPointer { + +public: + LaserPointer(const QString& jointName, const Transform& offsetTransform, const uint16_t filter, const float maxDistance, bool enabled); + ~LaserPointer(); + + unsigned int getUID() { return _rayPickUID; } + void enable(); + void disable(); + + // void setRenderState(const QString& stateName); + // void setRenderStateProperties(const QHash& renderStateProperties); + +private: + unsigned int _rayPickUID; +}; + +#endif hifi_LaserPointer_h \ No newline at end of file diff --git a/libraries/controllers/src/controllers/LaserPointerManager.cpp b/libraries/controllers/src/controllers/LaserPointerManager.cpp new file mode 100644 index 0000000000..adea77f530 --- /dev/null +++ b/libraries/controllers/src/controllers/LaserPointerManager.cpp @@ -0,0 +1,36 @@ +// +// LaserPointerManager.cpp +// libraries/controllers/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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 "LaserPointerManager.h" +#include "LaserPointer.h" + +LaserPointerManager& LaserPointerManager::getInstance() { + static LaserPointerManager instance; + return instance; +} + +unsigned int LaserPointerManager::createLaserPointer(const QString& jointName, const Transform& offsetTransform, const uint16_t filter, const float maxDistance, bool enabled) { + std::shared_ptr laserPointer = std::make_shared(jointName, offsetTransform, filter, maxDistance, enabled); + unsigned int uid = laserPointer->getUID(); + _laserPointers[uid] = laserPointer; + return uid; +} + +void LaserPointerManager::enableLaserPointer(const unsigned int uid) { + if (_laserPointers.contains(uid)) { + _laserPointers[uid]->enable(); + } +} + +void LaserPointerManager::disableLaserPointer(const unsigned int uid) { + if (_laserPointers.contains(uid)) { + _laserPointers[uid]->disable(); + } +} \ No newline at end of file diff --git a/libraries/controllers/src/controllers/LaserPointerManager.h b/libraries/controllers/src/controllers/LaserPointerManager.h new file mode 100644 index 0000000000..28d354cf98 --- /dev/null +++ b/libraries/controllers/src/controllers/LaserPointerManager.h @@ -0,0 +1,36 @@ +// +// LaserPointerManager.h +// libraries/controllers/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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_LaserPointerManager_h +#define hifi_LaserPointerManager_h + +#include +#include +#include +#include "Transform.h" + +class LaserPointer; + +class LaserPointerManager { + +public: + static LaserPointerManager& getInstance(); + + unsigned int createLaserPointer(const QString& jointName, const Transform& offsetTransform, const uint16_t filter, const float maxDistance, bool enabled); + void removeLaserPointer(const unsigned int uid) { _laserPointers.remove(uid); } + void enableLaserPointer(const unsigned int uid); + void disableLaserPointer(const unsigned int uid); + +private: + QHash> _laserPointers; + +}; + +#endif hifi_LaserPointerManager_h \ No newline at end of file diff --git a/libraries/shared/src/JointRayPick.cpp b/libraries/shared/src/JointRayPick.cpp new file mode 100644 index 0000000000..4a645fa3fd --- /dev/null +++ b/libraries/shared/src/JointRayPick.cpp @@ -0,0 +1,26 @@ +// +// JointRayPick.cpp +// libraries/shared/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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 "JointRayPick.h" + +JointRayPick::JointRayPick(const QString& jointName, const Transform& offsetTransform, const uint16_t filter, const float maxDistance, const bool enabled) : + RayPick(filter, maxDistance, enabled), + _jointName(jointName), + _offsetTransform(offsetTransform) +{ +} + +const PickRay JointRayPick::getPickRay() { + // TODO: + // get pose for _jointName + // apply _offsetTransform + // create and return PickRay + return PickRay(); +} diff --git a/libraries/shared/src/JointRayPick.h b/libraries/shared/src/JointRayPick.h new file mode 100644 index 0000000000..cd5de79c69 --- /dev/null +++ b/libraries/shared/src/JointRayPick.h @@ -0,0 +1,32 @@ +// +// JointRayPick.h +// libraries/shared/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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_JointRayPick_h +#define hifi_JointRayPick_h + +#include "RayPick.h" + +#include +#include "Transform.h" + +class JointRayPick : public RayPick { + +public: + JointRayPick(const QString& jointName, const Transform& offsetTransform, const uint16_t filter, const float maxDistance = 0.0f, const bool enabled = false); + + const PickRay getPickRay() override; + +private: + QString _jointName; + Transform _offsetTransform; + +}; + +#endif hifi_JointRayPick_h \ No newline at end of file diff --git a/libraries/shared/src/RayPick.cpp b/libraries/shared/src/RayPick.cpp new file mode 100644 index 0000000000..674913e2e0 --- /dev/null +++ b/libraries/shared/src/RayPick.cpp @@ -0,0 +1,18 @@ +// +// RayPick.cpp +// libraries/shared/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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 "RayPick.h" + +RayPick::RayPick(const uint16_t filter, const float maxDistance, const bool enabled) : + _filter(filter), + _maxDistance(maxDistance), + _enabled(enabled) +{ +} diff --git a/libraries/shared/src/RayPick.h b/libraries/shared/src/RayPick.h new file mode 100644 index 0000000000..8a292bf5f7 --- /dev/null +++ b/libraries/shared/src/RayPick.h @@ -0,0 +1,42 @@ +// +// RayPick.h +// libraries/shared/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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_RayPick_h +#define hifi_RayPick_h + +#include +#include "RegisteredMetaTypes.h" + +class RayPick { + +public: + RayPick(const uint16_t filter, const float maxDistance, const bool enabled); + + virtual const PickRay getPickRay() = 0; + + void enable() { _enabled = true; } + void disable() { _enabled = false; } + + const uint16_t getFilter() { return _filter; } + const float getMaxDistance() { return _maxDistance; } + const bool isEnabled() { return _enabled; } + //const IntersectionResult& getLastIntersectionResult() { return _prevIntersectionResult; } + + //void setIntersectionResult(const IntersectionResult& intersectionResult) { _prevIntersectionResult = intersectionResult; } + +private: + uint16_t _filter; + float _maxDistance; + bool _enabled; + //IntersectionResult _prevIntersectionResult; // set to invalid on disable()? + +}; + +#endif hifi_RayPick_h \ No newline at end of file diff --git a/libraries/shared/src/RayPickManager.cpp b/libraries/shared/src/RayPickManager.cpp new file mode 100644 index 0000000000..5c5ebd8c10 --- /dev/null +++ b/libraries/shared/src/RayPickManager.cpp @@ -0,0 +1,54 @@ +// +// RayPickManager.cpp +// libraries/shared/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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 "RayPickManager.h" +#include "RayPick.h" + +RayPickManager& RayPickManager::getInstance() { + static RayPickManager instance; + return instance; +} + +void RayPickManager::update() { + /*** + - somehow calculate minimum number of intersection tests, update raypicks accordingly + -one option : + loop over all raypicks{ loop over all necessary intersection tests and take min distance less than rayPick->maxDistance, but keep cache of this frame's previous tests to prevent duplicate intersection tests } + ***/ +} + +unsigned int RayPickManager::addRayPick(std::shared_ptr rayPick) { + // TODO: + // use lock and defer adding to prevent issues + _rayPicks[_nextUID] = rayPick; + return _nextUID++; +} + +void RayPickManager::removeRayPick(const unsigned int uid) { + // TODO: + // use lock and defer removing to prevent issues + _rayPicks.remove(uid); +} + +void RayPickManager::enableRayPick(const unsigned int uid) { + // TODO: + // use lock and defer enabling to prevent issues + if (_rayPicks.contains(uid)) { + _rayPicks[uid]->enable(); + } +} + +void RayPickManager::disableRayPick(const unsigned int uid) { + // TODO: + // use lock and defer disabling to prevent issues + if (_rayPicks.contains(uid)) { + _rayPicks[uid]->disable(); + } +} diff --git a/libraries/shared/src/RayPickManager.h b/libraries/shared/src/RayPickManager.h new file mode 100644 index 0000000000..c296c14af7 --- /dev/null +++ b/libraries/shared/src/RayPickManager.h @@ -0,0 +1,50 @@ +// +// RayPickManager.h +// libraries/shared/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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_RayPickManager_h +#define hifi_RayPickManager_h + +#include +#include + +class RayPick; + +enum RayPickMask { + PICK_NOTHING = 0, + PICK_ENTITIES = 1, + PICK_AVATARS = 2, + PICK_OVERLAYS = 4, + PICK_HUD = 8, + + PICK_BOUNDING_BOX = 16, // if not set, picks again physics mesh (can't pick against graphics mesh, yet) + + PICK_INCLUDE_INVISIBLE = 32, // if not set, will not intersect invisible elements, otherwise, intersects both visible and invisible elements + + PICK_ALL_INTERSECTIONS = 64 // if not set, returns closest intersection, otherwise, returns list of all intersections +}; + +class RayPickManager { + +public: + static RayPickManager& getInstance(); + + void update(); + unsigned int addRayPick(std::shared_ptr rayPick); + void removeRayPick(const unsigned int uid); + void enableRayPick(const unsigned int uid); + void disableRayPick(const unsigned int uid); + +private: + QHash> _rayPicks; + unsigned int _nextUID { 1 }; // 0 is invalid + +}; + +#endif hifi_RayPickManager_h \ No newline at end of file diff --git a/libraries/shared/src/StaticRayPick.cpp b/libraries/shared/src/StaticRayPick.cpp new file mode 100644 index 0000000000..2ebe431b00 --- /dev/null +++ b/libraries/shared/src/StaticRayPick.cpp @@ -0,0 +1,17 @@ +// +// StaticRayPick.cpp +// libraries/shared/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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 "StaticRayPick.h" + +StaticRayPick::StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance, const bool enabled) : + RayPick(filter, maxDistance, enabled), + _pickRay(position, direction) +{ +} diff --git a/libraries/shared/src/StaticRayPick.h b/libraries/shared/src/StaticRayPick.h new file mode 100644 index 0000000000..6424b731c7 --- /dev/null +++ b/libraries/shared/src/StaticRayPick.h @@ -0,0 +1,28 @@ +// +// StaticRayPick.h +// libraries/shared/src +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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_StaticRayPick_h +#define hifi_StaticRayPick_h + +#include "RayPick.h" + +class StaticRayPick : public RayPick { + +public: + StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance = 0.0f, const bool enabled = false); + + const PickRay getPickRay() override { return _pickRay; }; + +private: + PickRay _pickRay; + +}; + +#endif hifi_StaticRayPick_h \ No newline at end of file From ea65a04f28c7eebd34624cfcd64c7eff478119b1 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 12 Jul 2017 14:19:53 -0700 Subject: [PATCH 04/42] expose RayPickMask to JS, move everything to interface/src/raypick to prevent dependency issues, start working on RayPickManager::update (needs testing) --- interface/src/Application.cpp | 6 +- .../src/raypick}/JointRayPick.cpp | 9 +- .../src/raypick}/JointRayPick.h | 8 +- .../src/raypick}/LaserPointer.cpp | 6 +- .../src/raypick}/LaserPointer.h | 6 +- .../src/raypick}/LaserPointerManager.cpp | 6 +- .../src/raypick}/LaserPointerManager.h | 6 +- .../LaserPointerScriptingInterface.cpp | 19 ++- .../LaserPointerScriptingInterface.h | 4 +- .../src => interface/src/raypick}/RayPick.cpp | 2 +- .../src => interface/src/raypick}/RayPick.h | 2 +- interface/src/raypick/RayPickManager.cpp | 145 ++++++++++++++++++ interface/src/raypick/RayPickManager.h | 97 ++++++++++++ .../src/raypick}/StaticRayPick.cpp | 2 +- .../src/raypick}/StaticRayPick.h | 2 +- libraries/shared/src/RayPickManager.cpp | 54 ------- libraries/shared/src/RayPickManager.h | 50 ------ 17 files changed, 285 insertions(+), 139 deletions(-) rename {libraries/shared/src => interface/src/raypick}/JointRayPick.cpp (64%) rename {libraries/shared/src => interface/src/raypick}/JointRayPick.h (65%) rename {libraries/controllers/src/controllers => interface/src/raypick}/LaserPointer.cpp (72%) rename {libraries/controllers/src/controllers => interface/src/raypick}/LaserPointer.h (76%) rename {libraries/controllers/src/controllers => interface/src/raypick}/LaserPointerManager.cpp (80%) rename {libraries/controllers/src/controllers => interface/src/raypick}/LaserPointerManager.h (83%) rename interface/src/{ => raypick}/LaserPointerScriptingInterface.cpp (73%) rename interface/src/{ => raypick}/LaserPointerScriptingInterface.h (95%) rename {libraries/shared/src => interface/src/raypick}/RayPick.cpp (94%) rename {libraries/shared/src => interface/src/raypick}/RayPick.h (97%) create mode 100644 interface/src/raypick/RayPickManager.cpp create mode 100644 interface/src/raypick/RayPickManager.h rename {libraries/shared/src => interface/src/raypick}/StaticRayPick.cpp (95%) rename {libraries/shared/src => interface/src/raypick}/StaticRayPick.h (96%) delete mode 100644 libraries/shared/src/RayPickManager.cpp delete mode 100644 libraries/shared/src/RayPickManager.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 16e322a142..6fad34b6f1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -190,8 +190,8 @@ #include #include #include -#include "LaserPointerScriptingInterface.h" -#include +#include +#include // On Windows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU // FIXME seems to be broken. @@ -5821,6 +5821,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("EntityScriptServerLog", entityScriptServerLog.data()); scriptEngine->registerGlobalObject("AvatarInputs", AvatarInputs::getInstance()); + scriptEngine->registerGlobalObject("RayPick", &RayPickManager::getInstance()); + qScriptRegisterMetaType(scriptEngine, OverlayIDtoScriptValue, OverlayIDfromScriptValue); // connect this script engines printedMessage signal to the global ScriptEngines these various messages diff --git a/libraries/shared/src/JointRayPick.cpp b/interface/src/raypick/JointRayPick.cpp similarity index 64% rename from libraries/shared/src/JointRayPick.cpp rename to interface/src/raypick/JointRayPick.cpp index 4a645fa3fd..8ea48f842f 100644 --- a/libraries/shared/src/JointRayPick.cpp +++ b/interface/src/raypick/JointRayPick.cpp @@ -1,6 +1,6 @@ // // JointRayPick.cpp -// libraries/shared/src +// interface/src/raypick // // Created by Sam Gondelman 7/11/2017 // Copyright 2017 High Fidelity, Inc. @@ -10,17 +10,18 @@ // #include "JointRayPick.h" -JointRayPick::JointRayPick(const QString& jointName, const Transform& offsetTransform, const uint16_t filter, const float maxDistance, const bool enabled) : +JointRayPick::JointRayPick(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, const bool enabled) : RayPick(filter, maxDistance, enabled), _jointName(jointName), - _offsetTransform(offsetTransform) + _posOffset(posOffset), + _dirOffset(dirOffset) { } const PickRay JointRayPick::getPickRay() { // TODO: // get pose for _jointName - // apply _offsetTransform + // apply offset // create and return PickRay return PickRay(); } diff --git a/libraries/shared/src/JointRayPick.h b/interface/src/raypick/JointRayPick.h similarity index 65% rename from libraries/shared/src/JointRayPick.h rename to interface/src/raypick/JointRayPick.h index cd5de79c69..4b2f7d1071 100644 --- a/libraries/shared/src/JointRayPick.h +++ b/interface/src/raypick/JointRayPick.h @@ -1,6 +1,6 @@ // // JointRayPick.h -// libraries/shared/src +// interface/src/raypick // // Created by Sam Gondelman 7/11/2017 // Copyright 2017 High Fidelity, Inc. @@ -14,18 +14,18 @@ #include "RayPick.h" #include -#include "Transform.h" class JointRayPick : public RayPick { public: - JointRayPick(const QString& jointName, const Transform& offsetTransform, const uint16_t filter, const float maxDistance = 0.0f, const bool enabled = false); + JointRayPick(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance = 0.0f, const bool enabled = false); const PickRay getPickRay() override; private: QString _jointName; - Transform _offsetTransform; + glm::vec3 _posOffset; + glm::vec3 _dirOffset; }; diff --git a/libraries/controllers/src/controllers/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp similarity index 72% rename from libraries/controllers/src/controllers/LaserPointer.cpp rename to interface/src/raypick/LaserPointer.cpp index 4f3adce875..898df04345 100644 --- a/libraries/controllers/src/controllers/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -1,6 +1,6 @@ // // LaserPointer.cpp -// libraries/controllers/src +// interface/src/raypick // // Created by Sam Gondelman 7/11/2017 // Copyright 2017 High Fidelity, Inc. @@ -13,9 +13,9 @@ #include "RayPickManager.h" #include "JointRayPick.h" -LaserPointer::LaserPointer(const QString& jointName, const Transform& offsetTransform, const uint16_t filter, const float maxDistance, const bool enabled) +LaserPointer::LaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, const bool enabled) { - _rayPickUID = RayPickManager::getInstance().addRayPick(std::make_shared(jointName, offsetTransform, filter, maxDistance, enabled)); + _rayPickUID = RayPickManager::getInstance().addRayPick(std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled)); } LaserPointer::~LaserPointer() { diff --git a/libraries/controllers/src/controllers/LaserPointer.h b/interface/src/raypick/LaserPointer.h similarity index 76% rename from libraries/controllers/src/controllers/LaserPointer.h rename to interface/src/raypick/LaserPointer.h index d09defe7b2..93dd33f305 100644 --- a/libraries/controllers/src/controllers/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -1,6 +1,6 @@ // // LaserPointer.h -// libraries/controllers/src +// interface/src/raypick // // Created by Sam Gondelman 7/11/2017 // Copyright 2017 High Fidelity, Inc. @@ -12,12 +12,12 @@ #define hifi_LaserPointer_h #include -#include "Transform.h" +#include "glm/glm.hpp" class LaserPointer { public: - LaserPointer(const QString& jointName, const Transform& offsetTransform, const uint16_t filter, const float maxDistance, bool enabled); + LaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, bool enabled); ~LaserPointer(); unsigned int getUID() { return _rayPickUID; } diff --git a/libraries/controllers/src/controllers/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp similarity index 80% rename from libraries/controllers/src/controllers/LaserPointerManager.cpp rename to interface/src/raypick/LaserPointerManager.cpp index adea77f530..1be2087ffb 100644 --- a/libraries/controllers/src/controllers/LaserPointerManager.cpp +++ b/interface/src/raypick/LaserPointerManager.cpp @@ -1,6 +1,6 @@ // // LaserPointerManager.cpp -// libraries/controllers/src +// interface/src/raypick // // Created by Sam Gondelman 7/11/2017 // Copyright 2017 High Fidelity, Inc. @@ -16,8 +16,8 @@ LaserPointerManager& LaserPointerManager::getInstance() { return instance; } -unsigned int LaserPointerManager::createLaserPointer(const QString& jointName, const Transform& offsetTransform, const uint16_t filter, const float maxDistance, bool enabled) { - std::shared_ptr laserPointer = std::make_shared(jointName, offsetTransform, filter, maxDistance, enabled); +unsigned int LaserPointerManager::createLaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, bool enabled) { + std::shared_ptr laserPointer = std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled); unsigned int uid = laserPointer->getUID(); _laserPointers[uid] = laserPointer; return uid; diff --git a/libraries/controllers/src/controllers/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h similarity index 83% rename from libraries/controllers/src/controllers/LaserPointerManager.h rename to interface/src/raypick/LaserPointerManager.h index 28d354cf98..503db5e459 100644 --- a/libraries/controllers/src/controllers/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -1,6 +1,6 @@ // // LaserPointerManager.h -// libraries/controllers/src +// interface/src/raypick // // Created by Sam Gondelman 7/11/2017 // Copyright 2017 High Fidelity, Inc. @@ -14,7 +14,7 @@ #include #include #include -#include "Transform.h" +#include class LaserPointer; @@ -23,7 +23,7 @@ class LaserPointerManager { public: static LaserPointerManager& getInstance(); - unsigned int createLaserPointer(const QString& jointName, const Transform& offsetTransform, const uint16_t filter, const float maxDistance, bool enabled); + unsigned int createLaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, bool enabled); void removeLaserPointer(const unsigned int uid) { _laserPointers.remove(uid); } void enableLaserPointer(const unsigned int uid); void disableLaserPointer(const unsigned int uid); diff --git a/interface/src/LaserPointerScriptingInterface.cpp b/interface/src/raypick/LaserPointerScriptingInterface.cpp similarity index 73% rename from interface/src/LaserPointerScriptingInterface.cpp rename to interface/src/raypick/LaserPointerScriptingInterface.cpp index a5770a9252..f8bba2bf04 100644 --- a/interface/src/LaserPointerScriptingInterface.cpp +++ b/interface/src/raypick/LaserPointerScriptingInterface.cpp @@ -1,6 +1,6 @@ // // LaserPointerScriptingInterface.cpp -// interface/src +// interface/src/raypick // // Created by Sam Gondelman 7/11/2017 // Copyright 2017 High Fidelity, Inc. @@ -12,7 +12,8 @@ #include "LaserPointerScriptingInterface.h" #include -#include "Transform.h" +#include "RegisteredMetaTypes.h" +#include "GLMHelpers.h" LaserPointerScriptingInterface* LaserPointerScriptingInterface::getInstance() { static LaserPointerScriptingInterface instance; @@ -25,10 +26,14 @@ uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& prop if (propertyMap["joint"].isValid()) { QString jointName = propertyMap["joint"].toString(); - Transform offsetTransform; - if (propertyMap["offsetTransform"].isValid()) { - // TODO: - // convert transform + glm::vec3 posOffset = Vectors::ZERO; + if (propertyMap["posOffset"].isValid()) { + posOffset = vec3FromVariant(propertyMap["posOffset"]); + } + + glm::vec3 dirOffset = Vectors::FRONT; + if (propertyMap["dirOffset"].isValid()) { + posOffset = vec3FromVariant(propertyMap["dirOffset"]); } uint16_t filter = 0; @@ -49,7 +54,7 @@ uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& prop // TODO: // handle render state properties - return LaserPointerManager::getInstance().createLaserPointer(jointName, offsetTransform, filter, maxDistance, enabled); + return LaserPointerManager::getInstance().createLaserPointer(jointName, posOffset, dirOffset, filter, maxDistance, enabled); } else { return 0; } diff --git a/interface/src/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h similarity index 95% rename from interface/src/LaserPointerScriptingInterface.h rename to interface/src/raypick/LaserPointerScriptingInterface.h index c455843d03..428d722bbb 100644 --- a/interface/src/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -1,6 +1,6 @@ // // LaserPointerScriptingInterface.h -// interface/src +// interface/src/raypick // // Created by Sam Gondelman 7/11/2017 // Copyright 2017 High Fidelity, Inc. @@ -13,7 +13,7 @@ #include -#include "controllers\LaserPointerManager.h" +#include "LaserPointerManager.h" class LaserPointerScriptingInterface : public QObject { Q_OBJECT diff --git a/libraries/shared/src/RayPick.cpp b/interface/src/raypick/RayPick.cpp similarity index 94% rename from libraries/shared/src/RayPick.cpp rename to interface/src/raypick/RayPick.cpp index 674913e2e0..e807ef23ff 100644 --- a/libraries/shared/src/RayPick.cpp +++ b/interface/src/raypick/RayPick.cpp @@ -1,6 +1,6 @@ // // RayPick.cpp -// libraries/shared/src +// interface/src/raypick // // Created by Sam Gondelman 7/11/2017 // Copyright 2017 High Fidelity, Inc. diff --git a/libraries/shared/src/RayPick.h b/interface/src/raypick/RayPick.h similarity index 97% rename from libraries/shared/src/RayPick.h rename to interface/src/raypick/RayPick.h index 8a292bf5f7..7ad2d9f83f 100644 --- a/libraries/shared/src/RayPick.h +++ b/interface/src/raypick/RayPick.h @@ -1,6 +1,6 @@ // // RayPick.h -// libraries/shared/src +// interface/src/raypick // // Created by Sam Gondelman 7/11/2017 // Copyright 2017 High Fidelity, Inc. diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp new file mode 100644 index 0000000000..bb25c8f168 --- /dev/null +++ b/interface/src/raypick/RayPickManager.cpp @@ -0,0 +1,145 @@ +// +// RayPickManager.cpp +// interface/src/raypick +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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 "RayPickManager.h" +#include "RayPick.h" + +#include "Application.h" +#include "EntityScriptingInterface.h" +#include "ui/overlays/Overlays.h" +#include "avatar/AvatarManager.h" +#include "DependencyManager.h" + +RayPickManager& RayPickManager::getInstance() { + static RayPickManager instance; + return instance; +} + +// Returns true if this ray exists in the cache, and if it does, update res if the cached result is closer +bool RayPickManager::checkAndCompareCachedResults(std::shared_ptr rayPick, QPair& ray, QHash, QHash> cache, RayPickResult& res, unsigned int mask) { + if (cache.contains(ray) && cache[ray].contains(mask)) { + if (cache[ray][mask].getDistance() < res.getDistance() && cache[ray][mask].getDistance() < rayPick->getMaxDistance()) { + res = cache[ray][mask]; + } + return true; + } + return false; +} + +void RayPickManager::update() { + QHash, QHash> results; + for (auto &rayPick : _rayPicks) { + if (!rayPick->isEnabled() || rayPick->getFilter() == RayPickMask::PICK_NOTHING || rayPick->getMaxDistance() < 0.0f) { + continue; + } + + PickRay ray = rayPick->getPickRay(); + // TODO: + // get rid of this and make PickRay hashable + QPair rayKey = QPair(ray.origin, ray.direction); + RayPickResult res; // start with FLT_MAX distance + + if (rayPick->getFilter() & RayPickMask::PICK_ENTITIES) { + RayToEntityIntersectionResult entityRes; + if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE && rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE) { + if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_ENTITIES | RayPickMask::PICK_INCLUDE_INVISIBLE | RayPickMask::PICK_INCLUDE_NONCOLLIDABLE)) { + entityRes = DependencyManager::get()->findRayIntersection(ray, true, QScriptValue(), QScriptValue(), false, false); + } + } + else if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE) { + if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_ENTITIES | RayPickMask::PICK_INCLUDE_INVISIBLE)) { + entityRes = DependencyManager::get()->findRayIntersection(ray, true, QScriptValue(), QScriptValue(), false, true); + } + } + else if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE) { + if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_ENTITIES | RayPickMask::PICK_INCLUDE_NONCOLLIDABLE)) { + entityRes = DependencyManager::get()->findRayIntersection(ray, true, QScriptValue(), QScriptValue(), true, false); + } + } + else { + if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_ENTITIES)) { + entityRes = DependencyManager::get()->findRayIntersection(ray, true, QScriptValue(), QScriptValue(), true, true); + } + } + if (entityRes.intersects) { + res = RayPickResult(entityRes.entityID, entityRes.distance, entityRes.intersection, entityRes.surfaceNormal); + // add to cache + } + } + + if (rayPick->getFilter() & RayPickMask::PICK_OVERLAYS) { + RayToOverlayIntersectionResult overlayRes; + if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE && rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE) { + if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_OVERLAYS | RayPickMask::PICK_INCLUDE_INVISIBLE | RayPickMask::PICK_INCLUDE_NONCOLLIDABLE)) { + overlayRes = qApp->getOverlays().findRayIntersection(ray, true, QScriptValue(), QScriptValue(), false, false); + } + } + else if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE) { + if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_OVERLAYS | RayPickMask::PICK_INCLUDE_INVISIBLE)) { + overlayRes = qApp->getOverlays().findRayIntersection(ray, true, QScriptValue(), QScriptValue(), false, true); + } + } + else if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE) { + if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_OVERLAYS | RayPickMask::PICK_INCLUDE_NONCOLLIDABLE)) { + overlayRes = qApp->getOverlays().findRayIntersection(ray, true, QScriptValue(), QScriptValue(), true, false); + } + } + else { + if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_OVERLAYS)) { + overlayRes = qApp->getOverlays().findRayIntersection(ray, true, QScriptValue(), QScriptValue(), true, true); + } + } + if (overlayRes.intersects) { + res = RayPickResult(overlayRes.overlayID, overlayRes.distance, overlayRes.intersection, overlayRes.surfaceNormal); + // add to cache + } + } + + if (rayPick->getFilter() & RayPickMask::PICK_AVATARS) { + if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_AVATARS)) { + RayToAvatarIntersectionResult avatarRes = DependencyManager::get()->findRayIntersection(ray, QScriptValue(), QScriptValue()); + if (avatarRes.intersects) { + res = RayPickResult(avatarRes.avatarID, avatarRes.distance, avatarRes.intersection); + // add to cache + } + } + } + + } +} + +unsigned int RayPickManager::addRayPick(std::shared_ptr rayPick) { + // TODO: + // use lock and defer adding to prevent issues + _rayPicks[_nextUID] = rayPick; + return _nextUID++; +} + +void RayPickManager::removeRayPick(const unsigned int uid) { + // TODO: + // use lock and defer removing to prevent issues + _rayPicks.remove(uid); +} + +void RayPickManager::enableRayPick(const unsigned int uid) { + // TODO: + // use lock and defer enabling to prevent issues + if (_rayPicks.contains(uid)) { + _rayPicks[uid]->enable(); + } +} + +void RayPickManager::disableRayPick(const unsigned int uid) { + // TODO: + // use lock and defer disabling to prevent issues + if (_rayPicks.contains(uid)) { + _rayPicks[uid]->disable(); + } +} diff --git a/interface/src/raypick/RayPickManager.h b/interface/src/raypick/RayPickManager.h new file mode 100644 index 0000000000..ac700118f6 --- /dev/null +++ b/interface/src/raypick/RayPickManager.h @@ -0,0 +1,97 @@ +// +// RayPickManager.h +// interface/src/raypick +// +// Created by Sam Gondelman 7/11/2017 +// Copyright 2017 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_RayPickManager_h +#define hifi_RayPickManager_h + +#include "RegisteredMetaTypes.h" + +#include +#include +#include + +class RayPick; + +enum RayPickMask { + PICK_NOTHING = 0, + PICK_ENTITIES = 1, + PICK_OVERLAYS = 2, + PICK_AVATARS = 4, + PICK_HUD = 8, + + PICK_BOUNDING_BOX = 16, // if not set, picks again physics mesh (can't pick against graphics mesh, yet) + + PICK_INCLUDE_INVISIBLE = 32, // if not set, will not intersect invisible elements, otherwise, intersects both visible and invisible elements + PICK_INCLUDE_NONCOLLIDABLE = 64, // if not set, will not intersect noncollidable elements, otherwise, intersects both collidable and noncollidable elements + + PICK_ALL_INTERSECTIONS = 128 // if not set, returns closest intersection, otherwise, returns list of all intersections +}; + +// TODO: +// move/improve this and register it as a meta type +class RayPickResult { + +public: + RayPickResult() {} + RayPickResult(const QUuid& objectID, const float distance, const glm::vec3& intersection, const glm::vec3& surfaceNormal = glm::vec3(NAN)) : + _objectID(objectID), _distance(distance), _intersection(intersection), _surfaceNormal(surfaceNormal) {} + + const QUuid& getUID() { return _objectID; } + const float getDistance() { return _distance; } + const glm::vec3& getIntersection() { return _intersection; } + const glm::vec3& getSurfaceNormal() { return _surfaceNormal; } + +private: + //Type type; + QUuid _objectID { 0 }; + float _distance { FLT_MAX }; + glm::vec3 _intersection { NAN }; + glm::vec3 _surfaceNormal { NAN }; +}; + +class RayPickManager : public QObject { + Q_OBJECT + Q_PROPERTY(unsigned int PICK_NOTHING READ PICK_NOTHING CONSTANT) + Q_PROPERTY(unsigned int PICK_ENTITIES READ PICK_ENTITIES CONSTANT) + Q_PROPERTY(unsigned int PICK_OVERLAYS READ PICK_OVERLAYS CONSTANT) + Q_PROPERTY(unsigned int PICK_AVATARS READ PICK_AVATARS CONSTANT) + Q_PROPERTY(unsigned int PICK_HUD READ PICK_HUD CONSTANT) + Q_PROPERTY(unsigned int PICK_BOUNDING_BOX READ PICK_BOUNDING_BOX CONSTANT) + Q_PROPERTY(unsigned int PICK_INCLUDE_INVISIBLE READ PICK_INCLUDE_INVISIBLE CONSTANT) + Q_PROPERTY(unsigned int PICK_INCLUDE_NONCOLLIDABLE READ PICK_INCLUDE_NONCOLLIDABLE CONSTANT) + Q_PROPERTY(unsigned int PICK_ALL_INTERSECTIONS READ PICK_ALL_INTERSECTIONS CONSTANT) + +public: + static RayPickManager& getInstance(); + + void update(); + bool RayPickManager::checkAndCompareCachedResults(std::shared_ptr rayPick, QPair& ray, QHash, QHash> cache, RayPickResult& res, unsigned int mask); + unsigned int addRayPick(std::shared_ptr rayPick); + void removeRayPick(const unsigned int uid); + void enableRayPick(const unsigned int uid); + void disableRayPick(const unsigned int uid); + +private: + QHash> _rayPicks; + unsigned int _nextUID { 1 }; // 0 is invalid + + const unsigned int PICK_NOTHING() { return RayPickMask::PICK_NOTHING; } + const unsigned int PICK_ENTITIES() { return RayPickMask::PICK_ENTITIES; } + const unsigned int PICK_OVERLAYS() { return RayPickMask::PICK_OVERLAYS; } + const unsigned int PICK_AVATARS() { return RayPickMask::PICK_AVATARS; } + const unsigned int PICK_HUD() { return RayPickMask::PICK_HUD; } + const unsigned int PICK_BOUNDING_BOX() { return RayPickMask::PICK_BOUNDING_BOX; } + const unsigned int PICK_INCLUDE_INVISIBLE() { return RayPickMask::PICK_INCLUDE_INVISIBLE; } + const unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return RayPickMask::PICK_INCLUDE_NONCOLLIDABLE; } + const unsigned int PICK_ALL_INTERSECTIONS() { return RayPickMask::PICK_ALL_INTERSECTIONS; } + +}; + +#endif hifi_RayPickManager_h \ No newline at end of file diff --git a/libraries/shared/src/StaticRayPick.cpp b/interface/src/raypick/StaticRayPick.cpp similarity index 95% rename from libraries/shared/src/StaticRayPick.cpp rename to interface/src/raypick/StaticRayPick.cpp index 2ebe431b00..b3bce16b58 100644 --- a/libraries/shared/src/StaticRayPick.cpp +++ b/interface/src/raypick/StaticRayPick.cpp @@ -1,6 +1,6 @@ // // StaticRayPick.cpp -// libraries/shared/src +// interface/src/raypick // // Created by Sam Gondelman 7/11/2017 // Copyright 2017 High Fidelity, Inc. diff --git a/libraries/shared/src/StaticRayPick.h b/interface/src/raypick/StaticRayPick.h similarity index 96% rename from libraries/shared/src/StaticRayPick.h rename to interface/src/raypick/StaticRayPick.h index 6424b731c7..6d3df21859 100644 --- a/libraries/shared/src/StaticRayPick.h +++ b/interface/src/raypick/StaticRayPick.h @@ -1,6 +1,6 @@ // // StaticRayPick.h -// libraries/shared/src +// interface/src/raypick // // Created by Sam Gondelman 7/11/2017 // Copyright 2017 High Fidelity, Inc. diff --git a/libraries/shared/src/RayPickManager.cpp b/libraries/shared/src/RayPickManager.cpp deleted file mode 100644 index 5c5ebd8c10..0000000000 --- a/libraries/shared/src/RayPickManager.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// -// RayPickManager.cpp -// libraries/shared/src -// -// Created by Sam Gondelman 7/11/2017 -// Copyright 2017 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 "RayPickManager.h" -#include "RayPick.h" - -RayPickManager& RayPickManager::getInstance() { - static RayPickManager instance; - return instance; -} - -void RayPickManager::update() { - /*** - - somehow calculate minimum number of intersection tests, update raypicks accordingly - -one option : - loop over all raypicks{ loop over all necessary intersection tests and take min distance less than rayPick->maxDistance, but keep cache of this frame's previous tests to prevent duplicate intersection tests } - ***/ -} - -unsigned int RayPickManager::addRayPick(std::shared_ptr rayPick) { - // TODO: - // use lock and defer adding to prevent issues - _rayPicks[_nextUID] = rayPick; - return _nextUID++; -} - -void RayPickManager::removeRayPick(const unsigned int uid) { - // TODO: - // use lock and defer removing to prevent issues - _rayPicks.remove(uid); -} - -void RayPickManager::enableRayPick(const unsigned int uid) { - // TODO: - // use lock and defer enabling to prevent issues - if (_rayPicks.contains(uid)) { - _rayPicks[uid]->enable(); - } -} - -void RayPickManager::disableRayPick(const unsigned int uid) { - // TODO: - // use lock and defer disabling to prevent issues - if (_rayPicks.contains(uid)) { - _rayPicks[uid]->disable(); - } -} diff --git a/libraries/shared/src/RayPickManager.h b/libraries/shared/src/RayPickManager.h deleted file mode 100644 index c296c14af7..0000000000 --- a/libraries/shared/src/RayPickManager.h +++ /dev/null @@ -1,50 +0,0 @@ -// -// RayPickManager.h -// libraries/shared/src -// -// Created by Sam Gondelman 7/11/2017 -// Copyright 2017 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_RayPickManager_h -#define hifi_RayPickManager_h - -#include -#include - -class RayPick; - -enum RayPickMask { - PICK_NOTHING = 0, - PICK_ENTITIES = 1, - PICK_AVATARS = 2, - PICK_OVERLAYS = 4, - PICK_HUD = 8, - - PICK_BOUNDING_BOX = 16, // if not set, picks again physics mesh (can't pick against graphics mesh, yet) - - PICK_INCLUDE_INVISIBLE = 32, // if not set, will not intersect invisible elements, otherwise, intersects both visible and invisible elements - - PICK_ALL_INTERSECTIONS = 64 // if not set, returns closest intersection, otherwise, returns list of all intersections -}; - -class RayPickManager { - -public: - static RayPickManager& getInstance(); - - void update(); - unsigned int addRayPick(std::shared_ptr rayPick); - void removeRayPick(const unsigned int uid); - void enableRayPick(const unsigned int uid); - void disableRayPick(const unsigned int uid); - -private: - QHash> _rayPicks; - unsigned int _nextUID { 1 }; // 0 is invalid - -}; - -#endif hifi_RayPickManager_h \ No newline at end of file From 916a99c670f7f13666ce1d145b99f8b7acef5168 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 12 Jul 2017 17:12:25 -0700 Subject: [PATCH 05/42] added JS/C++ RayPickResult, working on RayPickManager::update --- interface/src/raypick/LaserPointer.cpp | 4 + interface/src/raypick/LaserPointer.h | 4 + interface/src/raypick/LaserPointerManager.cpp | 10 +- interface/src/raypick/LaserPointerManager.h | 2 + .../raypick/LaserPointerScriptingInterface.h | 3 +- interface/src/raypick/RayPick.h | 6 +- interface/src/raypick/RayPickManager.cpp | 113 ++++++++++++------ interface/src/raypick/RayPickManager.h | 28 +---- libraries/shared/src/RegisteredMetaTypes.cpp | 18 +++ libraries/shared/src/RegisteredMetaTypes.h | 15 +++ 10 files changed, 137 insertions(+), 66 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 898df04345..b190539607 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -32,4 +32,8 @@ void LaserPointer::disable() { RayPickManager::getInstance().disableRayPick(_rayPickUID); // TODO: // turn off rendering +} + +const RayPickResult& LaserPointer::getPrevRayPickResult() { + return RayPickManager::getInstance().getPrevRayPickResult(_rayPickUID); } \ No newline at end of file diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index 93dd33f305..a65c6a9748 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -14,6 +14,8 @@ #include #include "glm/glm.hpp" +class RayPickResult; + class LaserPointer { public: @@ -27,6 +29,8 @@ public: // void setRenderState(const QString& stateName); // void setRenderStateProperties(const QHash& renderStateProperties); + const RayPickResult& getPrevRayPickResult(); + private: unsigned int _rayPickUID; }; diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp index 1be2087ffb..2e7b084d73 100644 --- a/interface/src/raypick/LaserPointerManager.cpp +++ b/interface/src/raypick/LaserPointerManager.cpp @@ -10,6 +10,7 @@ // #include "LaserPointerManager.h" #include "LaserPointer.h" +#include "RayPick.h" LaserPointerManager& LaserPointerManager::getInstance() { static LaserPointerManager instance; @@ -33,4 +34,11 @@ void LaserPointerManager::disableLaserPointer(const unsigned int uid) { if (_laserPointers.contains(uid)) { _laserPointers[uid]->disable(); } -} \ No newline at end of file +} + +const RayPickResult& LaserPointerManager::getPrevRayPickResult(const unsigned int uid) { + if (_laserPointers.contains(uid)) { + return _laserPointers[uid]->getPrevRayPickResult(); + } + return RayPickResult(); +} diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h index 503db5e459..f8b3ae1a26 100644 --- a/interface/src/raypick/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -17,6 +17,7 @@ #include class LaserPointer; +class RayPickResult; class LaserPointerManager { @@ -27,6 +28,7 @@ public: void removeLaserPointer(const unsigned int uid) { _laserPointers.remove(uid); } void enableLaserPointer(const unsigned int uid); void disableLaserPointer(const unsigned int uid); + const RayPickResult& getPrevRayPickResult(const unsigned int uid); private: QHash> _laserPointers; diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h index 428d722bbb..8d6758119a 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -14,6 +14,7 @@ #include #include "LaserPointerManager.h" +#include "RegisteredMetaTypes.h" class LaserPointerScriptingInterface : public QObject { Q_OBJECT @@ -26,7 +27,7 @@ public slots: Q_INVOKABLE void enableLaserPointer(unsigned int uid) { LaserPointerManager::getInstance().enableLaserPointer(uid); } Q_INVOKABLE void disableLaserPointer(unsigned int uid) { LaserPointerManager::getInstance().disableLaserPointer(uid); } Q_INVOKABLE void removeLaserPointer(unsigned int uid) { LaserPointerManager::getInstance().removeLaserPointer(uid); } - //Q_INVOKABLE IntersectionResults getLaserPointerCollisionResults(unsigned int uid) { LaserPointerManager::getInstance().getLaserPointerCollisionResults(uid); } + Q_INVOKABLE RayPickResult getPrevRayPickResult(unsigned int uid) { return LaserPointerManager::getInstance().getPrevRayPickResult(uid); } }; diff --git a/interface/src/raypick/RayPick.h b/interface/src/raypick/RayPick.h index 7ad2d9f83f..512512dc2f 100644 --- a/interface/src/raypick/RayPick.h +++ b/interface/src/raypick/RayPick.h @@ -27,15 +27,15 @@ public: const uint16_t getFilter() { return _filter; } const float getMaxDistance() { return _maxDistance; } const bool isEnabled() { return _enabled; } - //const IntersectionResult& getLastIntersectionResult() { return _prevIntersectionResult; } + const RayPickResult& getPrevRayPickResult() { return _prevResult; } - //void setIntersectionResult(const IntersectionResult& intersectionResult) { _prevIntersectionResult = intersectionResult; } + void setRayPickResult(const RayPickResult& rayPickResult) { _prevResult = rayPickResult; } private: uint16_t _filter; float _maxDistance; bool _enabled; - //IntersectionResult _prevIntersectionResult; // set to invalid on disable()? + RayPickResult _prevResult; }; diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp index bb25c8f168..5a242c4f3b 100644 --- a/interface/src/raypick/RayPickManager.cpp +++ b/interface/src/raypick/RayPickManager.cpp @@ -9,12 +9,14 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "RayPickManager.h" + #include "RayPick.h" #include "Application.h" #include "EntityScriptingInterface.h" #include "ui/overlays/Overlays.h" #include "avatar/AvatarManager.h" +#include "scripting/HMDScriptingInterface.h" #include "DependencyManager.h" RayPickManager& RayPickManager::getInstance() { @@ -23,9 +25,9 @@ RayPickManager& RayPickManager::getInstance() { } // Returns true if this ray exists in the cache, and if it does, update res if the cached result is closer -bool RayPickManager::checkAndCompareCachedResults(std::shared_ptr rayPick, QPair& ray, QHash, QHash> cache, RayPickResult& res, unsigned int mask) { +bool RayPickManager::checkAndCompareCachedResults(QPair& ray, QHash, QHash>& cache, RayPickResult& res, unsigned int mask) { if (cache.contains(ray) && cache[ray].contains(mask)) { - if (cache[ray][mask].getDistance() < res.getDistance() && cache[ray][mask].getDistance() < rayPick->getMaxDistance()) { + if (cache[ray][mask].distance < res.distance) { res = cache[ray][mask]; } return true; @@ -33,6 +35,18 @@ bool RayPickManager::checkAndCompareCachedResults(std::shared_ptr rayPi return false; } +void RayPickManager::cacheResult(const bool intersects, const RayPickResult& resTemp, unsigned int mask, RayPickResult& res, + QPair& ray, QHash, QHash>& cache) { + if (intersects) { + cache[ray][mask] = resTemp; + if (resTemp.distance < res.distance) { + res = resTemp; + } + } else { + cache[ray][mask] = RayPickResult(); + } +} + void RayPickManager::update() { QHash, QHash> results; for (auto &rayPick : _rayPicks) { @@ -44,74 +58,92 @@ void RayPickManager::update() { // TODO: // get rid of this and make PickRay hashable QPair rayKey = QPair(ray.origin, ray.direction); - RayPickResult res; // start with FLT_MAX distance + RayPickResult res; if (rayPick->getFilter() & RayPickMask::PICK_ENTITIES) { RayToEntityIntersectionResult entityRes; + bool fromCache = true; if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE && rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE) { - if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_ENTITIES | RayPickMask::PICK_INCLUDE_INVISIBLE | RayPickMask::PICK_INCLUDE_NONCOLLIDABLE)) { + if (!checkAndCompareCachedResults(rayKey, results, res, RayPickMask::PICK_ENTITIES | RayPickMask::PICK_INCLUDE_INVISIBLE | RayPickMask::PICK_INCLUDE_NONCOLLIDABLE)) { entityRes = DependencyManager::get()->findRayIntersection(ray, true, QScriptValue(), QScriptValue(), false, false); + fromCache = false; } - } - else if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE) { - if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_ENTITIES | RayPickMask::PICK_INCLUDE_INVISIBLE)) { + } else if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE) { + if (!checkAndCompareCachedResults(rayKey, results, res, RayPickMask::PICK_ENTITIES | RayPickMask::PICK_INCLUDE_INVISIBLE)) { entityRes = DependencyManager::get()->findRayIntersection(ray, true, QScriptValue(), QScriptValue(), false, true); + fromCache = false; } - } - else if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE) { - if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_ENTITIES | RayPickMask::PICK_INCLUDE_NONCOLLIDABLE)) { + } else if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE) { + if (!checkAndCompareCachedResults(rayKey, results, res, RayPickMask::PICK_ENTITIES | RayPickMask::PICK_INCLUDE_NONCOLLIDABLE)) { entityRes = DependencyManager::get()->findRayIntersection(ray, true, QScriptValue(), QScriptValue(), true, false); + fromCache = false; } - } - else { - if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_ENTITIES)) { + } else { + if (!checkAndCompareCachedResults(rayKey, results, res, RayPickMask::PICK_ENTITIES)) { entityRes = DependencyManager::get()->findRayIntersection(ray, true, QScriptValue(), QScriptValue(), true, true); + fromCache = false; } } - if (entityRes.intersects) { - res = RayPickResult(entityRes.entityID, entityRes.distance, entityRes.intersection, entityRes.surfaceNormal); - // add to cache + + if (!fromCache) { + unsigned int mask = (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE) | (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE); + cacheResult(entityRes.intersects, RayPickResult(entityRes.entityID, entityRes.distance, entityRes.intersection, entityRes.surfaceNormal), + RayPickMask::PICK_ENTITIES | mask, res, rayKey, results); } } if (rayPick->getFilter() & RayPickMask::PICK_OVERLAYS) { RayToOverlayIntersectionResult overlayRes; + bool fromCache = true; if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE && rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE) { - if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_OVERLAYS | RayPickMask::PICK_INCLUDE_INVISIBLE | RayPickMask::PICK_INCLUDE_NONCOLLIDABLE)) { + if (!checkAndCompareCachedResults(rayKey, results, res, RayPickMask::PICK_OVERLAYS | RayPickMask::PICK_INCLUDE_INVISIBLE | RayPickMask::PICK_INCLUDE_NONCOLLIDABLE)) { overlayRes = qApp->getOverlays().findRayIntersection(ray, true, QScriptValue(), QScriptValue(), false, false); + fromCache = false; } - } - else if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE) { - if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_OVERLAYS | RayPickMask::PICK_INCLUDE_INVISIBLE)) { + } else if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE) { + if (!checkAndCompareCachedResults(rayKey, results, res, RayPickMask::PICK_OVERLAYS | RayPickMask::PICK_INCLUDE_INVISIBLE)) { overlayRes = qApp->getOverlays().findRayIntersection(ray, true, QScriptValue(), QScriptValue(), false, true); + fromCache = false; } - } - else if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE) { - if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_OVERLAYS | RayPickMask::PICK_INCLUDE_NONCOLLIDABLE)) { + } else if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE) { + if (!checkAndCompareCachedResults(rayKey, results, res, RayPickMask::PICK_OVERLAYS | RayPickMask::PICK_INCLUDE_NONCOLLIDABLE)) { overlayRes = qApp->getOverlays().findRayIntersection(ray, true, QScriptValue(), QScriptValue(), true, false); + fromCache = false; } - } - else { - if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_OVERLAYS)) { + } else { + if (!checkAndCompareCachedResults(rayKey, results, res, RayPickMask::PICK_OVERLAYS)) { overlayRes = qApp->getOverlays().findRayIntersection(ray, true, QScriptValue(), QScriptValue(), true, true); + fromCache = false; } } - if (overlayRes.intersects) { - res = RayPickResult(overlayRes.overlayID, overlayRes.distance, overlayRes.intersection, overlayRes.surfaceNormal); - // add to cache + + if (!fromCache) { + unsigned int mask = (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE) | (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE); + cacheResult(overlayRes.intersects, RayPickResult(overlayRes.overlayID, overlayRes.distance, overlayRes.intersection, overlayRes.surfaceNormal), + RayPickMask::PICK_OVERLAYS | mask, res, rayKey, results); } } if (rayPick->getFilter() & RayPickMask::PICK_AVATARS) { - if (!checkAndCompareCachedResults(rayPick, rayKey, results, res, RayPickMask::PICK_AVATARS)) { + if (!checkAndCompareCachedResults(rayKey, results, res, RayPickMask::PICK_AVATARS)) { RayToAvatarIntersectionResult avatarRes = DependencyManager::get()->findRayIntersection(ray, QScriptValue(), QScriptValue()); - if (avatarRes.intersects) { - res = RayPickResult(avatarRes.avatarID, avatarRes.distance, avatarRes.intersection); - // add to cache - } + cacheResult(avatarRes.intersects, RayPickResult(avatarRes.avatarID, avatarRes.distance, avatarRes.intersection), RayPickMask::PICK_AVATARS, res, rayKey, results); } } + // Can't intersect with HUD in desktop mode + if (rayPick->getFilter() & RayPickMask::PICK_HUD && DependencyManager::get()->isHMDMode()) { + if (!checkAndCompareCachedResults(rayKey, results, res, RayPickMask::PICK_HUD)) { + glm::vec3 hudRes = DependencyManager::get()->calculateRayUICollisionPoint(ray.origin, ray.direction); + cacheResult(true, RayPickResult(0, glm::distance(ray.origin, hudRes), hudRes), RayPickMask::PICK_HUD, res, rayKey, results); + } + } + + if (res.distance < rayPick->getMaxDistance()) { + rayPick->setRayPickResult(res); + } else { + rayPick->setRayPickResult(RayPickResult()); + } } } @@ -129,17 +161,22 @@ void RayPickManager::removeRayPick(const unsigned int uid) { } void RayPickManager::enableRayPick(const unsigned int uid) { - // TODO: - // use lock and defer enabling to prevent issues if (_rayPicks.contains(uid)) { _rayPicks[uid]->enable(); } } void RayPickManager::disableRayPick(const unsigned int uid) { - // TODO: - // use lock and defer disabling to prevent issues if (_rayPicks.contains(uid)) { _rayPicks[uid]->disable(); } } + +const RayPickResult& RayPickManager::getPrevRayPickResult(const unsigned int uid) { + // TODO: + // does this need to lock the individual ray? what happens with concurrent set/get? + if (_rayPicks.contains(uid)) { + return _rayPicks[uid]->getPrevRayPickResult(); + } + return RayPickResult(); +} diff --git a/interface/src/raypick/RayPickManager.h b/interface/src/raypick/RayPickManager.h index ac700118f6..8a98677776 100644 --- a/interface/src/raypick/RayPickManager.h +++ b/interface/src/raypick/RayPickManager.h @@ -18,6 +18,7 @@ #include class RayPick; +class RayPickResult; enum RayPickMask { PICK_NOTHING = 0, @@ -34,28 +35,6 @@ enum RayPickMask { PICK_ALL_INTERSECTIONS = 128 // if not set, returns closest intersection, otherwise, returns list of all intersections }; -// TODO: -// move/improve this and register it as a meta type -class RayPickResult { - -public: - RayPickResult() {} - RayPickResult(const QUuid& objectID, const float distance, const glm::vec3& intersection, const glm::vec3& surfaceNormal = glm::vec3(NAN)) : - _objectID(objectID), _distance(distance), _intersection(intersection), _surfaceNormal(surfaceNormal) {} - - const QUuid& getUID() { return _objectID; } - const float getDistance() { return _distance; } - const glm::vec3& getIntersection() { return _intersection; } - const glm::vec3& getSurfaceNormal() { return _surfaceNormal; } - -private: - //Type type; - QUuid _objectID { 0 }; - float _distance { FLT_MAX }; - glm::vec3 _intersection { NAN }; - glm::vec3 _surfaceNormal { NAN }; -}; - class RayPickManager : public QObject { Q_OBJECT Q_PROPERTY(unsigned int PICK_NOTHING READ PICK_NOTHING CONSTANT) @@ -72,11 +51,14 @@ public: static RayPickManager& getInstance(); void update(); - bool RayPickManager::checkAndCompareCachedResults(std::shared_ptr rayPick, QPair& ray, QHash, QHash> cache, RayPickResult& res, unsigned int mask); + bool checkAndCompareCachedResults(QPair& ray, QHash, QHash>& cache, RayPickResult& res, unsigned int mask); + void cacheResult(const bool intersects, const RayPickResult& resTemp, unsigned int mask, RayPickResult& res, + QPair& ray, QHash, QHash>& cache); unsigned int addRayPick(std::shared_ptr rayPick); void removeRayPick(const unsigned int uid); void enableRayPick(const unsigned int uid); void disableRayPick(const unsigned int uid); + const RayPickResult& getPrevRayPickResult(const unsigned int uid); private: QHash> _rayPicks; diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index b30637c83f..1565777666 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -34,6 +34,7 @@ int vec2MetaTypeId = qRegisterMetaType(); int quatMetaTypeId = qRegisterMetaType(); int xColorMetaTypeId = qRegisterMetaType(); int pickRayMetaTypeId = qRegisterMetaType(); +int rayPickResultMetaTypeId = qRegisterMetaType(); int collisionMetaTypeId = qRegisterMetaType(); int qMapURLStringMetaTypeId = qRegisterMetaType>(); int socketErrorMetaTypeId = qRegisterMetaType(); @@ -56,6 +57,7 @@ void registerMetaTypes(QScriptEngine* engine) { qScriptRegisterMetaType(engine, qColorToScriptValue, qColorFromScriptValue); qScriptRegisterMetaType(engine, qURLToScriptValue, qURLFromScriptValue); qScriptRegisterMetaType(engine, pickRayToScriptValue, pickRayFromScriptValue); + qScriptRegisterMetaType(engine, rayPickResultToScriptValue, rayPickResultFromScriptValue); qScriptRegisterMetaType(engine, collisionToScriptValue, collisionFromScriptValue); qScriptRegisterMetaType(engine, quuidToScriptValue, quuidFromScriptValue); qScriptRegisterMetaType(engine, qSizeFToScriptValue, qSizeFFromScriptValue); @@ -751,6 +753,22 @@ void pickRayFromScriptValue(const QScriptValue& object, PickRay& pickRay) { } } +QScriptValue rayPickResultToScriptValue(QScriptEngine* engine, const RayPickResult& rayPickResult) { + QScriptValue obj = engine->newObject(); + QScriptValue objectID = quuidToScriptValue(engine, rayPickResult.objectID); + obj.setProperty("objectID", objectID); + obj.setProperty("distance", rayPickResult.distance); + QScriptValue intersection = vec3toScriptValue(engine, rayPickResult.intersection); + obj.setProperty("intersection", intersection); + QScriptValue surfaceNormal = vec3toScriptValue(engine, rayPickResult.surfaceNormal); + obj.setProperty("surfaceNormal", surfaceNormal); + return obj; +} + +void rayPickResultFromScriptValue(const QScriptValue& object, RayPickResult& rayPickResult) { + // TODO: cannot currently accept RayPickResults from JS +} + QScriptValue collisionToScriptValue(QScriptEngine* engine, const Collision& collision) { QScriptValue obj = engine->newObject(); obj.setProperty("type", collision.type); diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 123c769a96..7d9ba941a9 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -136,6 +136,21 @@ Q_DECLARE_METATYPE(PickRay) QScriptValue pickRayToScriptValue(QScriptEngine* engine, const PickRay& pickRay); void pickRayFromScriptValue(const QScriptValue& object, PickRay& pickRay); +class RayPickResult { +public: + RayPickResult() {} + RayPickResult(const QUuid& objectID, const float distance, const glm::vec3& intersection, const glm::vec3& surfaceNormal = glm::vec3(NAN)) : + objectID(objectID), distance(distance), intersection(intersection), surfaceNormal(surfaceNormal) {} + //Type type; + QUuid objectID { 0 }; + float distance { FLT_MAX }; + glm::vec3 intersection { NAN }; + glm::vec3 surfaceNormal { NAN }; +}; +Q_DECLARE_METATYPE(RayPickResult) +QScriptValue rayPickResultToScriptValue(QScriptEngine* engine, const RayPickResult& rayPickResult); +void rayPickResultFromScriptValue(const QScriptValue& object, RayPickResult& rayPickResult); + enum ContactEventType { CONTACT_EVENT_TYPE_START, CONTACT_EVENT_TYPE_CONTINUE, From 783750a0bcd32330ab0c79698d4760957f9fc6cb Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 13 Jul 2017 14:47:24 -0700 Subject: [PATCH 06/42] update jointraypicks from joints, dirOffset needs work --- interface/src/raypick/JointRayPick.cpp | 29 +++++++++++++++---- interface/src/raypick/JointRayPick.h | 2 +- .../LaserPointerScriptingInterface.cpp | 3 +- interface/src/raypick/RayPick.h | 4 +-- interface/src/raypick/RayPickManager.cpp | 10 +++++-- interface/src/raypick/StaticRayPick.cpp | 5 ++++ interface/src/raypick/StaticRayPick.h | 2 +- 7 files changed, 43 insertions(+), 12 deletions(-) diff --git a/interface/src/raypick/JointRayPick.cpp b/interface/src/raypick/JointRayPick.cpp index 8ea48f842f..9309f0d826 100644 --- a/interface/src/raypick/JointRayPick.cpp +++ b/interface/src/raypick/JointRayPick.cpp @@ -10,6 +10,9 @@ // #include "JointRayPick.h" +#include "DependencyManager.h" +#include "avatar/AvatarManager.h" + JointRayPick::JointRayPick(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, const bool enabled) : RayPick(filter, maxDistance, enabled), _jointName(jointName), @@ -18,10 +21,26 @@ JointRayPick::JointRayPick(const QString& jointName, const glm::vec3& posOffset, { } -const PickRay JointRayPick::getPickRay() { - // TODO: - // get pose for _jointName - // apply offset - // create and return PickRay +const PickRay JointRayPick::getPickRay(bool& valid) { + auto myAvatar = DependencyManager::get()->getMyAvatar(); + int jointIndex = myAvatar->getJointIndex(_jointName); + if (jointIndex != -1) { + glm::vec3 jointPos = myAvatar->getAbsoluteJointTranslationInObjectFrame(jointIndex); + glm::quat jointRot = myAvatar->getAbsoluteJointRotationInObjectFrame(jointIndex); + glm::vec3 avatarPos = myAvatar->getPosition(); + glm::quat avatarRot = myAvatar->getOrientation(); + + glm::vec3 pos = avatarPos + (avatarRot * jointPos); + glm::quat rot = avatarRot * jointRot; + + // Apply offset + pos = pos + (rot * _posOffset); + glm::vec3 dir = rot * glm::normalize(_dirOffset); + + valid = true; + return PickRay(pos, dir); + } + + valid = false; return PickRay(); } diff --git a/interface/src/raypick/JointRayPick.h b/interface/src/raypick/JointRayPick.h index 4b2f7d1071..54d393ab46 100644 --- a/interface/src/raypick/JointRayPick.h +++ b/interface/src/raypick/JointRayPick.h @@ -20,7 +20,7 @@ class JointRayPick : public RayPick { public: JointRayPick(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance = 0.0f, const bool enabled = false); - const PickRay getPickRay() override; + const PickRay getPickRay(bool& valid) override; private: QString _jointName; diff --git a/interface/src/raypick/LaserPointerScriptingInterface.cpp b/interface/src/raypick/LaserPointerScriptingInterface.cpp index f8bba2bf04..ef87b1780c 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.cpp +++ b/interface/src/raypick/LaserPointerScriptingInterface.cpp @@ -26,12 +26,13 @@ uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& prop if (propertyMap["joint"].isValid()) { QString jointName = propertyMap["joint"].toString(); + // x = upward, y = forward, z = lateral glm::vec3 posOffset = Vectors::ZERO; if (propertyMap["posOffset"].isValid()) { posOffset = vec3FromVariant(propertyMap["posOffset"]); } - glm::vec3 dirOffset = Vectors::FRONT; + glm::vec3 dirOffset = Vectors::UP; if (propertyMap["dirOffset"].isValid()) { posOffset = vec3FromVariant(propertyMap["dirOffset"]); } diff --git a/interface/src/raypick/RayPick.h b/interface/src/raypick/RayPick.h index 512512dc2f..855cd53ba8 100644 --- a/interface/src/raypick/RayPick.h +++ b/interface/src/raypick/RayPick.h @@ -17,9 +17,9 @@ class RayPick { public: - RayPick(const uint16_t filter, const float maxDistance, const bool enabled); + RayPick(const uint16_t filter, const float maxDistance, const bool enabled); - virtual const PickRay getPickRay() = 0; + virtual const PickRay getPickRay(bool& valid) = 0; void enable() { _enabled = true; } void disable() { _enabled = false; } diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp index 5a242c4f3b..d56d9cb501 100644 --- a/interface/src/raypick/RayPickManager.cpp +++ b/interface/src/raypick/RayPickManager.cpp @@ -54,7 +54,13 @@ void RayPickManager::update() { continue; } - PickRay ray = rayPick->getPickRay(); + bool valid; + PickRay ray = rayPick->getPickRay(valid); + + if (!valid) { + continue; + } + // TODO: // get rid of this and make PickRay hashable QPair rayKey = QPair(ray.origin, ray.direction); @@ -139,7 +145,7 @@ void RayPickManager::update() { } } - if (res.distance < rayPick->getMaxDistance()) { + if (rayPick->getMaxDistance() == 0.0f || (rayPick->getMaxDistance() > 0.0f && res.distance < rayPick->getMaxDistance())) { rayPick->setRayPickResult(res); } else { rayPick->setRayPickResult(RayPickResult()); diff --git a/interface/src/raypick/StaticRayPick.cpp b/interface/src/raypick/StaticRayPick.cpp index b3bce16b58..9edd992a17 100644 --- a/interface/src/raypick/StaticRayPick.cpp +++ b/interface/src/raypick/StaticRayPick.cpp @@ -15,3 +15,8 @@ StaticRayPick::StaticRayPick(const glm::vec3& position, const glm::vec3& directi _pickRay(position, direction) { } + +const PickRay StaticRayPick::getPickRay(bool& valid) { + valid = true; + return _pickRay; +} \ No newline at end of file diff --git a/interface/src/raypick/StaticRayPick.h b/interface/src/raypick/StaticRayPick.h index 6d3df21859..f4f2b769e3 100644 --- a/interface/src/raypick/StaticRayPick.h +++ b/interface/src/raypick/StaticRayPick.h @@ -18,7 +18,7 @@ class StaticRayPick : public RayPick { public: StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance = 0.0f, const bool enabled = false); - const PickRay getPickRay() override { return _pickRay; }; + const PickRay getPickRay(bool& valid) override; private: PickRay _pickRay; From 3a35cd128fd0bb36621fb2d541f4300443611929 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 13 Jul 2017 16:09:21 -0700 Subject: [PATCH 07/42] fix dirOffset, expose intersection type to JS --- .../src/raypick/LaserPointerScriptingInterface.cpp | 2 +- interface/src/raypick/RayPickManager.cpp | 8 ++++---- interface/src/raypick/RayPickManager.h | 10 ++++++++++ libraries/shared/src/RegisteredMetaTypes.cpp | 1 + libraries/shared/src/RegisteredMetaTypes.h | 14 +++++++++++--- 5 files changed, 27 insertions(+), 8 deletions(-) diff --git a/interface/src/raypick/LaserPointerScriptingInterface.cpp b/interface/src/raypick/LaserPointerScriptingInterface.cpp index ef87b1780c..68f8423d73 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.cpp +++ b/interface/src/raypick/LaserPointerScriptingInterface.cpp @@ -34,7 +34,7 @@ uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& prop glm::vec3 dirOffset = Vectors::UP; if (propertyMap["dirOffset"].isValid()) { - posOffset = vec3FromVariant(propertyMap["dirOffset"]); + dirOffset = vec3FromVariant(propertyMap["dirOffset"]); } uint16_t filter = 0; diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp index d56d9cb501..c84fbfdd20 100644 --- a/interface/src/raypick/RayPickManager.cpp +++ b/interface/src/raypick/RayPickManager.cpp @@ -93,7 +93,7 @@ void RayPickManager::update() { if (!fromCache) { unsigned int mask = (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE) | (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE); - cacheResult(entityRes.intersects, RayPickResult(entityRes.entityID, entityRes.distance, entityRes.intersection, entityRes.surfaceNormal), + cacheResult(entityRes.intersects, RayPickResult(IntersectionType::ENTITY, entityRes.entityID, entityRes.distance, entityRes.intersection, entityRes.surfaceNormal), RayPickMask::PICK_ENTITIES | mask, res, rayKey, results); } } @@ -125,7 +125,7 @@ void RayPickManager::update() { if (!fromCache) { unsigned int mask = (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE) | (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE); - cacheResult(overlayRes.intersects, RayPickResult(overlayRes.overlayID, overlayRes.distance, overlayRes.intersection, overlayRes.surfaceNormal), + cacheResult(overlayRes.intersects, RayPickResult(IntersectionType::OVERLAY, overlayRes.overlayID, overlayRes.distance, overlayRes.intersection, overlayRes.surfaceNormal), RayPickMask::PICK_OVERLAYS | mask, res, rayKey, results); } } @@ -133,7 +133,7 @@ void RayPickManager::update() { if (rayPick->getFilter() & RayPickMask::PICK_AVATARS) { if (!checkAndCompareCachedResults(rayKey, results, res, RayPickMask::PICK_AVATARS)) { RayToAvatarIntersectionResult avatarRes = DependencyManager::get()->findRayIntersection(ray, QScriptValue(), QScriptValue()); - cacheResult(avatarRes.intersects, RayPickResult(avatarRes.avatarID, avatarRes.distance, avatarRes.intersection), RayPickMask::PICK_AVATARS, res, rayKey, results); + cacheResult(avatarRes.intersects, RayPickResult(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection), RayPickMask::PICK_AVATARS, res, rayKey, results); } } @@ -141,7 +141,7 @@ void RayPickManager::update() { if (rayPick->getFilter() & RayPickMask::PICK_HUD && DependencyManager::get()->isHMDMode()) { if (!checkAndCompareCachedResults(rayKey, results, res, RayPickMask::PICK_HUD)) { glm::vec3 hudRes = DependencyManager::get()->calculateRayUICollisionPoint(ray.origin, ray.direction); - cacheResult(true, RayPickResult(0, glm::distance(ray.origin, hudRes), hudRes), RayPickMask::PICK_HUD, res, rayKey, results); + cacheResult(true, RayPickResult(IntersectionType::HUD, 0, glm::distance(ray.origin, hudRes), hudRes), RayPickMask::PICK_HUD, res, rayKey, results); } } diff --git a/interface/src/raypick/RayPickManager.h b/interface/src/raypick/RayPickManager.h index 8a98677776..6dc98415e7 100644 --- a/interface/src/raypick/RayPickManager.h +++ b/interface/src/raypick/RayPickManager.h @@ -46,6 +46,11 @@ class RayPickManager : public QObject { Q_PROPERTY(unsigned int PICK_INCLUDE_INVISIBLE READ PICK_INCLUDE_INVISIBLE CONSTANT) Q_PROPERTY(unsigned int PICK_INCLUDE_NONCOLLIDABLE READ PICK_INCLUDE_NONCOLLIDABLE CONSTANT) Q_PROPERTY(unsigned int PICK_ALL_INTERSECTIONS READ PICK_ALL_INTERSECTIONS CONSTANT) + Q_PROPERTY(unsigned int INTERSECTED_NONE READ INTERSECTED_NONE CONSTANT) + Q_PROPERTY(unsigned int INTERSECTED_ENTITY READ INTERSECTED_ENTITY CONSTANT) + Q_PROPERTY(unsigned int INTERSECTED_OVERLAY READ INTERSECTED_OVERLAY CONSTANT) + Q_PROPERTY(unsigned int INTERSECTED_AVATAR READ INTERSECTED_AVATAR CONSTANT) + Q_PROPERTY(unsigned int INTERSECTED_HUD READ INTERSECTED_HUD CONSTANT) public: static RayPickManager& getInstance(); @@ -73,6 +78,11 @@ private: const unsigned int PICK_INCLUDE_INVISIBLE() { return RayPickMask::PICK_INCLUDE_INVISIBLE; } const unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return RayPickMask::PICK_INCLUDE_NONCOLLIDABLE; } const unsigned int PICK_ALL_INTERSECTIONS() { return RayPickMask::PICK_ALL_INTERSECTIONS; } + const unsigned int INTERSECTED_NONE() { return IntersectionType::NONE; } + const unsigned int INTERSECTED_ENTITY() { return IntersectionType::ENTITY; } + const unsigned int INTERSECTED_OVERLAY() { return IntersectionType::OVERLAY; } + const unsigned int INTERSECTED_AVATAR() { return IntersectionType::AVATAR; } + const unsigned int INTERSECTED_HUD() { return IntersectionType::HUD; } }; diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index 1565777666..78b54d26f1 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -755,6 +755,7 @@ void pickRayFromScriptValue(const QScriptValue& object, PickRay& pickRay) { QScriptValue rayPickResultToScriptValue(QScriptEngine* engine, const RayPickResult& rayPickResult) { QScriptValue obj = engine->newObject(); + obj.setProperty("type", rayPickResult.type); QScriptValue objectID = quuidToScriptValue(engine, rayPickResult.objectID); obj.setProperty("objectID", objectID); obj.setProperty("distance", rayPickResult.distance); diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 7d9ba941a9..f4fc9109ac 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -136,12 +136,20 @@ Q_DECLARE_METATYPE(PickRay) QScriptValue pickRayToScriptValue(QScriptEngine* engine, const PickRay& pickRay); void pickRayFromScriptValue(const QScriptValue& object, PickRay& pickRay); +enum IntersectionType { + NONE, + ENTITY, + OVERLAY, + AVATAR, + HUD +}; + class RayPickResult { public: RayPickResult() {} - RayPickResult(const QUuid& objectID, const float distance, const glm::vec3& intersection, const glm::vec3& surfaceNormal = glm::vec3(NAN)) : - objectID(objectID), distance(distance), intersection(intersection), surfaceNormal(surfaceNormal) {} - //Type type; + RayPickResult(const IntersectionType type, const QUuid& objectID, const float distance, const glm::vec3& intersection, const glm::vec3& surfaceNormal = glm::vec3(NAN)) : + type(type), objectID(objectID), distance(distance), intersection(intersection), surfaceNormal(surfaceNormal) {} + IntersectionType type { NONE }; QUuid objectID { 0 }; float distance { FLT_MAX }; glm::vec3 intersection { NAN }; From 3c719b26b151afc46deb44edde49cdb68fe7d821 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 13 Jul 2017 17:43:44 -0700 Subject: [PATCH 08/42] working on renderstates --- interface/src/raypick/LaserPointer.cpp | 27 +++++++++--- interface/src/raypick/LaserPointer.h | 30 +++++++++++-- interface/src/raypick/LaserPointerManager.cpp | 5 ++- interface/src/raypick/LaserPointerManager.h | 6 ++- .../LaserPointerScriptingInterface.cpp | 44 +++++++++++++++++-- interface/src/raypick/RayPickManager.cpp | 2 +- 6 files changed, 97 insertions(+), 17 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index b190539607..028b266009 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -13,7 +13,12 @@ #include "RayPickManager.h" #include "JointRayPick.h" -LaserPointer::LaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, const bool enabled) +#include "Application.h" + +LaserPointer::LaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, + const QHash& renderStates, const bool enabled) : + _renderingEnabled(enabled), + _renderStates(renderStates) { _rayPickUID = RayPickManager::getInstance().addRayPick(std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled)); } @@ -24,16 +29,26 @@ LaserPointer::~LaserPointer() { void LaserPointer::enable() { RayPickManager::getInstance().enableRayPick(_rayPickUID); - // TODO: - // turn on rendering + _renderingEnabled = true; } void LaserPointer::disable() { RayPickManager::getInstance().disableRayPick(_rayPickUID); - // TODO: - // turn off rendering + _renderingEnabled = false; } const RayPickResult& LaserPointer::getPrevRayPickResult() { return RayPickManager::getInstance().getPrevRayPickResult(_rayPickUID); -} \ No newline at end of file +} + +void LaserPointer::render(RenderArgs* args) { + if (_renderingEnabled && !_currentRenderState.isEmpty() && _renderStates.contains(_currentRenderState)) { + _renderStates[_currentRenderState].render(args); + } +} + +void RenderState::render(RenderArgs * args) { + if (!_startID.isNull()) qApp->getOverlays().getOverlay(_startID)->render(args); + if (!_pathID.isNull()) qApp->getOverlays().getOverlay(_pathID)->render(args); + if (!_endID.isNull()) qApp->getOverlays().getOverlay(_endID)->render(args); +} diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index a65c6a9748..f970668bf1 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -13,25 +13,49 @@ #include #include "glm/glm.hpp" +#include +#include "ui/overlays/Overlay.h" class RayPickResult; +class RenderState { + +public: + RenderState() {} + RenderState(const OverlayID& startID, const OverlayID& pathID, const OverlayID& endID) : + _startID(startID), _pathID(pathID), _endID(endID) {} + + void render(RenderArgs* args); + +private: + OverlayID _startID; + OverlayID _pathID; + OverlayID _endID; +}; + + class LaserPointer { public: - LaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, bool enabled); + LaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, + const QHash& renderStates, const bool enabled); ~LaserPointer(); unsigned int getUID() { return _rayPickUID; } void enable(); void disable(); - // void setRenderState(const QString& stateName); - // void setRenderStateProperties(const QHash& renderStateProperties); + void setRenderState(const QString& state) { _currentRenderState = state; } const RayPickResult& getPrevRayPickResult(); + void render(RenderArgs* args); + const render::ShapeKey getShapeKey() { return render::ShapeKey::Builder::ownPipeline(); } + private: + bool _renderingEnabled; + QString _currentRenderState { "" }; + QHash _renderStates; unsigned int _rayPickUID; }; diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp index 2e7b084d73..86affdb3b4 100644 --- a/interface/src/raypick/LaserPointerManager.cpp +++ b/interface/src/raypick/LaserPointerManager.cpp @@ -17,8 +17,9 @@ LaserPointerManager& LaserPointerManager::getInstance() { return instance; } -unsigned int LaserPointerManager::createLaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, bool enabled) { - std::shared_ptr laserPointer = std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled); +unsigned int LaserPointerManager::createLaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, + const QHash& renderStates, const bool enabled) { + std::shared_ptr laserPointer = std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, renderStates, enabled); unsigned int uid = laserPointer->getUID(); _laserPointers[uid] = laserPointer; return uid; diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h index f8b3ae1a26..2abe909c01 100644 --- a/interface/src/raypick/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -16,7 +16,8 @@ #include #include -class LaserPointer; +#include "LaserPointer.h" + class RayPickResult; class LaserPointerManager { @@ -24,7 +25,8 @@ class LaserPointerManager { public: static LaserPointerManager& getInstance(); - unsigned int createLaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, bool enabled); + unsigned int createLaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, + const QHash& renderStates, const bool enabled); void removeLaserPointer(const unsigned int uid) { _laserPointers.remove(uid); } void enableLaserPointer(const unsigned int uid); void disableLaserPointer(const unsigned int uid); diff --git a/interface/src/raypick/LaserPointerScriptingInterface.cpp b/interface/src/raypick/LaserPointerScriptingInterface.cpp index 68f8423d73..a9c096c554 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.cpp +++ b/interface/src/raypick/LaserPointerScriptingInterface.cpp @@ -15,6 +15,8 @@ #include "RegisteredMetaTypes.h" #include "GLMHelpers.h" +#include "Application.h" + LaserPointerScriptingInterface* LaserPointerScriptingInterface::getInstance() { static LaserPointerScriptingInterface instance; return &instance; @@ -52,10 +54,46 @@ uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& prop enabled = propertyMap["enabled"].toBool(); } - // TODO: - // handle render state properties + QHash renderStates; + if (propertyMap["renderStates"].isValid()) { + QList renderStateVariants = propertyMap["renderStates"].toList(); + for (QVariant& renderStateVariant : renderStateVariants) { + if (renderStateVariant.isValid()) { + QVariantMap renderStateMap = renderStateVariant.toMap(); + if (renderStateMap["name"].isValid()) { + QString name = renderStateMap["name"].toString(); - return LaserPointerManager::getInstance().createLaserPointer(jointName, posOffset, dirOffset, filter, maxDistance, enabled); + QUuid startID; + if (renderStateMap["start"].isValid()) { + QVariantMap startMap = renderStateMap["start"].toMap(); + if (startMap["type"].isValid()) { + startID = qApp->getOverlays().addOverlay(startMap["type"].toString(), startMap); + } + } + + QUuid pathID; + if (renderStateMap["path"].isValid()) { + QVariantMap pathMap = renderStateMap["path"].toMap(); + if (pathMap["type"].isValid()) { + pathID = qApp->getOverlays().addOverlay(pathMap["type"].toString(), pathMap); + } + } + + QUuid endID; + if (renderStateMap["end"].isValid()) { + QVariantMap endMap = renderStateMap["end"].toMap(); + if (endMap["type"].isValid()) { + endID = qApp->getOverlays().addOverlay(endMap["type"].toString(), endMap); + } + } + + renderStates[name] = RenderState(startID, pathID, endID); + } + } + } + } + + return LaserPointerManager::getInstance().createLaserPointer(jointName, posOffset, dirOffset, filter, maxDistance, renderStates, enabled); } else { return 0; } diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp index c84fbfdd20..33dc16874f 100644 --- a/interface/src/raypick/RayPickManager.cpp +++ b/interface/src/raypick/RayPickManager.cpp @@ -49,7 +49,7 @@ void RayPickManager::cacheResult(const bool intersects, const RayPickResult& res void RayPickManager::update() { QHash, QHash> results; - for (auto &rayPick : _rayPicks) { + for (auto& rayPick : _rayPicks) { if (!rayPick->isEnabled() || rayPick->getFilter() == RayPickMask::PICK_NOTHING || rayPick->getMaxDistance() < 0.0f) { continue; } From 8f533636f508626ea3b8bec73a23d92b5d1b374a Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 14 Jul 2017 11:13:40 -0700 Subject: [PATCH 09/42] c++ side laserpointer rendering with renderstates --- interface/src/Application.cpp | 5 ++ interface/src/raypick/LaserPointer.cpp | 78 ++++++++++++++++++- interface/src/raypick/LaserPointer.h | 18 ++++- interface/src/raypick/LaserPointerManager.cpp | 12 +++ interface/src/raypick/LaserPointerManager.h | 3 + .../LaserPointerScriptingInterface.cpp | 3 +- .../raypick/LaserPointerScriptingInterface.h | 1 + interface/src/raypick/RayPickManager.cpp | 11 +++ interface/src/raypick/RayPickManager.h | 1 + 9 files changed, 127 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 384484488e..44f15ff16e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4925,6 +4925,11 @@ void Application::update(float deltaTime) { RayPickManager::getInstance().update(); } + { + PROFILE_RANGE(app, "LaserPointerManager"); + LaserPointerManager::getInstance().update(); + } + // Update _viewFrustum with latest camera and view frustum data... // NOTE: we get this from the view frustum, to make it simpler, since the // loadViewFrumstum() method will get the correct details from the camera diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 028b266009..1e3d6f5126 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -21,10 +21,19 @@ LaserPointer::LaserPointer(const QString& jointName, const glm::vec3& posOffset, _renderStates(renderStates) { _rayPickUID = RayPickManager::getInstance().addRayPick(std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled)); + + if (!enabled) { + disableCurrentRenderState(); + } } LaserPointer::~LaserPointer() { RayPickManager::getInstance().removeRayPick(_rayPickUID); + for (RenderState& renderState : _renderStates) { + if (!renderState.getStartID().isNull()) qApp->getOverlays().deleteOverlay(renderState.getStartID()); + if (!renderState.getPathID().isNull()) qApp->getOverlays().deleteOverlay(renderState.getPathID()); + if (!renderState.getEndID().isNull()) qApp->getOverlays().deleteOverlay(renderState.getEndID()); + } } void LaserPointer::enable() { @@ -35,20 +44,87 @@ void LaserPointer::enable() { void LaserPointer::disable() { RayPickManager::getInstance().disableRayPick(_rayPickUID); _renderingEnabled = false; + if (!_currentRenderState.isEmpty() && _renderStates.contains(_currentRenderState)) disableCurrentRenderState(); +} + +void LaserPointer::setRenderState(const QString& state) { + if (!_currentRenderState.isEmpty() && _renderStates.contains(_currentRenderState)) disableCurrentRenderState(); + _currentRenderState = state; } const RayPickResult& LaserPointer::getPrevRayPickResult() { return RayPickManager::getInstance().getPrevRayPickResult(_rayPickUID); } +void LaserPointer::disableCurrentRenderState() { + if (!_renderStates[_currentRenderState].getStartID().isNull()) { + QVariantMap startProps; + startProps.insert("visible", false); + startProps.insert("ignoreRayIntersection", true); + qApp->getOverlays().editOverlay(_renderStates[_currentRenderState].getStartID(), startProps); + } + if (!_renderStates[_currentRenderState].getPathID().isNull()) { + QVariantMap pathProps; + pathProps.insert("visible", false); + pathProps.insert("ignoreRayIntersection", true); + qApp->getOverlays().editOverlay(_renderStates[_currentRenderState].getPathID(), pathProps); + } + if (!_renderStates[_currentRenderState].getEndID().isNull()) { + QVariantMap endProps; + endProps.insert("visible", false); + endProps.insert("ignoreRayIntersection", true); + qApp->getOverlays().editOverlay(_renderStates[_currentRenderState].getEndID(), endProps); + } +} + +void LaserPointer::update() { + RayPickResult prevRayPickResult = RayPickManager::getInstance().getPrevRayPickResult(_rayPickUID); + if (_renderingEnabled && !_currentRenderState.isEmpty() && _renderStates.contains(_currentRenderState) && prevRayPickResult.type != IntersectionType::NONE) { + PickRay pickRay = RayPickManager::getInstance().getPickRay(_rayPickUID); + if (!_renderStates[_currentRenderState].getStartID().isNull()) { + QVariantMap startProps; + startProps.insert("position", vec3toVariant(pickRay.origin)); + startProps.insert("visible", true); + startProps.insert("ignoreRayIntersection", _renderStates[_currentRenderState].doesStartIgnoreRays()); + qApp->getOverlays().editOverlay(_renderStates[_currentRenderState].getStartID(), startProps); + } + QVariant end = vec3toVariant(pickRay.origin + pickRay.direction * prevRayPickResult.distance); + if (!_renderStates[_currentRenderState].getPathID().isNull()) { + QVariantMap pathProps; + pathProps.insert("start", vec3toVariant(pickRay.origin)); + pathProps.insert("end", end); + pathProps.insert("visible", true); + pathProps.insert("ignoreRayIntersection", _renderStates[_currentRenderState].doesPathIgnoreRays()); + qApp->getOverlays().editOverlay(_renderStates[_currentRenderState].getPathID(), pathProps); + } + if (!_renderStates[_currentRenderState].getEndID().isNull()) { + QVariantMap endProps; + endProps.insert("position", end); + endProps.insert("visible", true); + endProps.insert("ignoreRayIntersection", _renderStates[_currentRenderState].doesEndIgnoreRays()); + qApp->getOverlays().editOverlay(_renderStates[_currentRenderState].getEndID(), endProps); + } + } else { + disableCurrentRenderState(); + } +} + void LaserPointer::render(RenderArgs* args) { if (_renderingEnabled && !_currentRenderState.isEmpty() && _renderStates.contains(_currentRenderState)) { _renderStates[_currentRenderState].render(args); } } +RenderState::RenderState(const OverlayID& startID, const OverlayID& pathID, const OverlayID& endID) : + _startID(startID), _pathID(pathID), _endID(endID) +{ + if (!_startID.isNull()) _startIgnoreRays = qApp->getOverlays().getOverlay(_startID)->getProperty("ignoreRayIntersection").toBool(); + if (!_pathID.isNull()) _pathIgnoreRays = qApp->getOverlays().getOverlay(_pathID)->getProperty("ignoreRayIntersection").toBool(); + if (!_endID.isNull()) _endIgnoreRays = qApp->getOverlays().getOverlay(_endID)->getProperty("ignoreRayIntersection").toBool(); +} + void RenderState::render(RenderArgs * args) { if (!_startID.isNull()) qApp->getOverlays().getOverlay(_startID)->render(args); if (!_pathID.isNull()) qApp->getOverlays().getOverlay(_pathID)->render(args); if (!_endID.isNull()) qApp->getOverlays().getOverlay(_endID)->render(args); -} +} \ No newline at end of file diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index f970668bf1..2910805c74 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -22,15 +22,24 @@ class RenderState { public: RenderState() {} - RenderState(const OverlayID& startID, const OverlayID& pathID, const OverlayID& endID) : - _startID(startID), _pathID(pathID), _endID(endID) {} + RenderState(const OverlayID& startID, const OverlayID& pathID, const OverlayID& endID); void render(RenderArgs* args); + const OverlayID& getStartID() { return _startID; } + const OverlayID& getPathID() { return _pathID; } + const OverlayID& getEndID() { return _endID; } + const bool& doesStartIgnoreRays() { return _startIgnoreRays; } + const bool& doesPathIgnoreRays() { return _pathIgnoreRays; } + const bool& doesEndIgnoreRays() { return _endIgnoreRays; } + private: OverlayID _startID; OverlayID _pathID; OverlayID _endID; + bool _startIgnoreRays; + bool _pathIgnoreRays; + bool _endIgnoreRays; }; @@ -45,10 +54,13 @@ public: void enable(); void disable(); - void setRenderState(const QString& state) { _currentRenderState = state; } + void setRenderState(const QString& state); const RayPickResult& getPrevRayPickResult(); + void disableCurrentRenderState(); + + void update(); void render(RenderArgs* args); const render::ShapeKey getShapeKey() { return render::ShapeKey::Builder::ownPipeline(); } diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp index 86affdb3b4..9b4327b647 100644 --- a/interface/src/raypick/LaserPointerManager.cpp +++ b/interface/src/raypick/LaserPointerManager.cpp @@ -37,9 +37,21 @@ void LaserPointerManager::disableLaserPointer(const unsigned int uid) { } } +void LaserPointerManager::setRenderState(unsigned int uid, const QString & renderState) { + if (_laserPointers.contains(uid)) { + _laserPointers[uid]->setRenderState(renderState); + } +} + const RayPickResult& LaserPointerManager::getPrevRayPickResult(const unsigned int uid) { if (_laserPointers.contains(uid)) { return _laserPointers[uid]->getPrevRayPickResult(); } return RayPickResult(); } + +void LaserPointerManager::update() { + for (auto& laserPointer : _laserPointers) { + laserPointer->update(); + } +} \ No newline at end of file diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h index 2abe909c01..a9e3215b51 100644 --- a/interface/src/raypick/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -30,8 +30,11 @@ public: void removeLaserPointer(const unsigned int uid) { _laserPointers.remove(uid); } void enableLaserPointer(const unsigned int uid); void disableLaserPointer(const unsigned int uid); + void setRenderState(unsigned int uid, const QString& renderState); const RayPickResult& getPrevRayPickResult(const unsigned int uid); + void update(); + private: QHash> _laserPointers; diff --git a/interface/src/raypick/LaserPointerScriptingInterface.cpp b/interface/src/raypick/LaserPointerScriptingInterface.cpp index a9c096c554..b2848f5463 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.cpp +++ b/interface/src/raypick/LaserPointerScriptingInterface.cpp @@ -74,7 +74,8 @@ uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& prop QUuid pathID; if (renderStateMap["path"].isValid()) { QVariantMap pathMap = renderStateMap["path"].toMap(); - if (pathMap["type"].isValid()) { + // right now paths must be line3ds + if (pathMap["type"].isValid() && pathMap["type"].toString() == "line3d") { pathID = qApp->getOverlays().addOverlay(pathMap["type"].toString(), pathMap); } } diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h index 8d6758119a..b68a4532db 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -27,6 +27,7 @@ public slots: Q_INVOKABLE void enableLaserPointer(unsigned int uid) { LaserPointerManager::getInstance().enableLaserPointer(uid); } Q_INVOKABLE void disableLaserPointer(unsigned int uid) { LaserPointerManager::getInstance().disableLaserPointer(uid); } Q_INVOKABLE void removeLaserPointer(unsigned int uid) { LaserPointerManager::getInstance().removeLaserPointer(uid); } + Q_INVOKABLE void setRenderState(unsigned int uid, const QString& renderState) { LaserPointerManager::getInstance().setRenderState(uid, renderState); } Q_INVOKABLE RayPickResult getPrevRayPickResult(unsigned int uid) { return LaserPointerManager::getInstance().getPrevRayPickResult(uid); } }; diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp index 33dc16874f..68b979a97a 100644 --- a/interface/src/raypick/RayPickManager.cpp +++ b/interface/src/raypick/RayPickManager.cpp @@ -178,6 +178,17 @@ void RayPickManager::disableRayPick(const unsigned int uid) { } } +const PickRay& RayPickManager::getPickRay(const unsigned int uid) { + if (_rayPicks.contains(uid)) { + bool valid; + PickRay pickRay = _rayPicks[uid]->getPickRay(valid); + if (valid) { + return pickRay; + } + } + return PickRay(); +} + const RayPickResult& RayPickManager::getPrevRayPickResult(const unsigned int uid) { // TODO: // does this need to lock the individual ray? what happens with concurrent set/get? diff --git a/interface/src/raypick/RayPickManager.h b/interface/src/raypick/RayPickManager.h index 6dc98415e7..2af98d171c 100644 --- a/interface/src/raypick/RayPickManager.h +++ b/interface/src/raypick/RayPickManager.h @@ -63,6 +63,7 @@ public: void removeRayPick(const unsigned int uid); void enableRayPick(const unsigned int uid); void disableRayPick(const unsigned int uid); + const PickRay& getPickRay(const unsigned int uid); const RayPickResult& getPrevRayPickResult(const unsigned int uid); private: From af12b5a4bfeb5895a910985e009f005022bb5d1f Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 14 Jul 2017 18:35:27 -0700 Subject: [PATCH 10/42] can create static laser pointers, fixed a bug with multiple render states --- interface/src/raypick/LaserPointer.cpp | 51 ++++---- interface/src/raypick/LaserPointer.h | 13 +- interface/src/raypick/LaserPointerManager.cpp | 7 + interface/src/raypick/LaserPointerManager.h | 2 + .../LaserPointerScriptingInterface.cpp | 123 ++++++++++-------- 5 files changed, 106 insertions(+), 90 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 1e3d6f5126..b480d64374 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -12,6 +12,7 @@ #include "RayPickManager.h" #include "JointRayPick.h" +#include "StaticRayPick.h" #include "Application.h" @@ -22,8 +23,22 @@ LaserPointer::LaserPointer(const QString& jointName, const glm::vec3& posOffset, { _rayPickUID = RayPickManager::getInstance().addRayPick(std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled)); - if (!enabled) { - disableCurrentRenderState(); + for (auto& state : _renderStates.keys()) { + if (!enabled || state != _currentRenderState) + disableRenderState(state); + } +} + +LaserPointer::LaserPointer(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance, + const QHash& renderStates, const bool enabled) : + _renderingEnabled(enabled), + _renderStates(renderStates) +{ + _rayPickUID = RayPickManager::getInstance().addRayPick(std::make_shared(position, direction, filter, maxDistance, enabled)); + + for (auto& state : _renderStates.keys()) { + if (!enabled || state != _currentRenderState) + disableRenderState(state); } } @@ -44,11 +59,11 @@ void LaserPointer::enable() { void LaserPointer::disable() { RayPickManager::getInstance().disableRayPick(_rayPickUID); _renderingEnabled = false; - if (!_currentRenderState.isEmpty() && _renderStates.contains(_currentRenderState)) disableCurrentRenderState(); + if (!_currentRenderState.isEmpty() && _renderStates.contains(_currentRenderState)) disableRenderState(_currentRenderState); } void LaserPointer::setRenderState(const QString& state) { - if (!_currentRenderState.isEmpty() && _renderStates.contains(_currentRenderState)) disableCurrentRenderState(); + if (!_currentRenderState.isEmpty() && _renderStates.contains(_currentRenderState)) disableRenderState(_currentRenderState); _currentRenderState = state; } @@ -56,24 +71,24 @@ const RayPickResult& LaserPointer::getPrevRayPickResult() { return RayPickManager::getInstance().getPrevRayPickResult(_rayPickUID); } -void LaserPointer::disableCurrentRenderState() { - if (!_renderStates[_currentRenderState].getStartID().isNull()) { +void LaserPointer::disableRenderState(const QString& renderState) { + if (!_renderStates[renderState].getStartID().isNull()) { QVariantMap startProps; startProps.insert("visible", false); startProps.insert("ignoreRayIntersection", true); - qApp->getOverlays().editOverlay(_renderStates[_currentRenderState].getStartID(), startProps); + qApp->getOverlays().editOverlay(_renderStates[renderState].getStartID(), startProps); } - if (!_renderStates[_currentRenderState].getPathID().isNull()) { + if (!_renderStates[renderState].getPathID().isNull()) { QVariantMap pathProps; pathProps.insert("visible", false); pathProps.insert("ignoreRayIntersection", true); - qApp->getOverlays().editOverlay(_renderStates[_currentRenderState].getPathID(), pathProps); + qApp->getOverlays().editOverlay(_renderStates[renderState].getPathID(), pathProps); } - if (!_renderStates[_currentRenderState].getEndID().isNull()) { + if (!_renderStates[renderState].getEndID().isNull()) { QVariantMap endProps; endProps.insert("visible", false); endProps.insert("ignoreRayIntersection", true); - qApp->getOverlays().editOverlay(_renderStates[_currentRenderState].getEndID(), endProps); + qApp->getOverlays().editOverlay(_renderStates[renderState].getEndID(), endProps); } } @@ -105,13 +120,7 @@ void LaserPointer::update() { qApp->getOverlays().editOverlay(_renderStates[_currentRenderState].getEndID(), endProps); } } else { - disableCurrentRenderState(); - } -} - -void LaserPointer::render(RenderArgs* args) { - if (_renderingEnabled && !_currentRenderState.isEmpty() && _renderStates.contains(_currentRenderState)) { - _renderStates[_currentRenderState].render(args); + disableRenderState(_currentRenderState); } } @@ -121,10 +130,4 @@ RenderState::RenderState(const OverlayID& startID, const OverlayID& pathID, cons if (!_startID.isNull()) _startIgnoreRays = qApp->getOverlays().getOverlay(_startID)->getProperty("ignoreRayIntersection").toBool(); if (!_pathID.isNull()) _pathIgnoreRays = qApp->getOverlays().getOverlay(_pathID)->getProperty("ignoreRayIntersection").toBool(); if (!_endID.isNull()) _endIgnoreRays = qApp->getOverlays().getOverlay(_endID)->getProperty("ignoreRayIntersection").toBool(); -} - -void RenderState::render(RenderArgs * args) { - if (!_startID.isNull()) qApp->getOverlays().getOverlay(_startID)->render(args); - if (!_pathID.isNull()) qApp->getOverlays().getOverlay(_pathID)->render(args); - if (!_endID.isNull()) qApp->getOverlays().getOverlay(_endID)->render(args); } \ No newline at end of file diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index 2910805c74..ef834d8190 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -13,7 +13,6 @@ #include #include "glm/glm.hpp" -#include #include "ui/overlays/Overlay.h" class RayPickResult; @@ -24,8 +23,6 @@ public: RenderState() {} RenderState(const OverlayID& startID, const OverlayID& pathID, const OverlayID& endID); - void render(RenderArgs* args); - const OverlayID& getStartID() { return _startID; } const OverlayID& getPathID() { return _pathID; } const OverlayID& getEndID() { return _endID; } @@ -48,21 +45,19 @@ class LaserPointer { public: LaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, const QHash& renderStates, const bool enabled); + LaserPointer(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance, + const QHash& renderStates, const bool enabled); ~LaserPointer(); unsigned int getUID() { return _rayPickUID; } void enable(); void disable(); - - void setRenderState(const QString& state); - const RayPickResult& getPrevRayPickResult(); - void disableCurrentRenderState(); + void setRenderState(const QString& state); + void disableRenderState(const QString& renderState); void update(); - void render(RenderArgs* args); - const render::ShapeKey getShapeKey() { return render::ShapeKey::Builder::ownPipeline(); } private: bool _renderingEnabled; diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp index 9b4327b647..3d0aa1f4b1 100644 --- a/interface/src/raypick/LaserPointerManager.cpp +++ b/interface/src/raypick/LaserPointerManager.cpp @@ -25,6 +25,13 @@ unsigned int LaserPointerManager::createLaserPointer(const QString& jointName, c return uid; } +unsigned int LaserPointerManager::createLaserPointer(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance, const QHash& renderStates, const bool enabled) { + std::shared_ptr laserPointer = std::make_shared(position, direction, filter, maxDistance, renderStates, enabled); + unsigned int uid = laserPointer->getUID(); + _laserPointers[uid] = laserPointer; + return uid; +} + void LaserPointerManager::enableLaserPointer(const unsigned int uid) { if (_laserPointers.contains(uid)) { _laserPointers[uid]->enable(); diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h index a9e3215b51..f9b59e3bb5 100644 --- a/interface/src/raypick/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -27,6 +27,8 @@ public: unsigned int createLaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, const QHash& renderStates, const bool enabled); + unsigned int createLaserPointer(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance, + const QHash& renderStates, const bool enabled); void removeLaserPointer(const unsigned int uid) { _laserPointers.remove(uid); } void enableLaserPointer(const unsigned int uid); void disableLaserPointer(const unsigned int uid); diff --git a/interface/src/raypick/LaserPointerScriptingInterface.cpp b/interface/src/raypick/LaserPointerScriptingInterface.cpp index b2848f5463..48bbdb5278 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.cpp +++ b/interface/src/raypick/LaserPointerScriptingInterface.cpp @@ -25,6 +25,61 @@ LaserPointerScriptingInterface* LaserPointerScriptingInterface::getInstance() { uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& properties) { QVariantMap propertyMap = properties.toMap(); + uint16_t filter = 0; + if (propertyMap["filter"].isValid()) { + filter = propertyMap["filter"].toUInt(); + } + + float maxDistance = 0.0f; + if (propertyMap["maxDistance"].isValid()) { + maxDistance = propertyMap["maxDistance"].toFloat(); + } + + bool enabled = false; + if (propertyMap["enabled"].isValid()) { + enabled = propertyMap["enabled"].toBool(); + } + + QHash renderStates; + if (propertyMap["renderStates"].isValid()) { + QList renderStateVariants = propertyMap["renderStates"].toList(); + for (QVariant& renderStateVariant : renderStateVariants) { + if (renderStateVariant.isValid()) { + QVariantMap renderStateMap = renderStateVariant.toMap(); + if (renderStateMap["name"].isValid()) { + QString name = renderStateMap["name"].toString(); + + QUuid startID; + if (renderStateMap["start"].isValid()) { + QVariantMap startMap = renderStateMap["start"].toMap(); + if (startMap["type"].isValid()) { + startID = qApp->getOverlays().addOverlay(startMap["type"].toString(), startMap); + } + } + + QUuid pathID; + if (renderStateMap["path"].isValid()) { + QVariantMap pathMap = renderStateMap["path"].toMap(); + // right now paths must be line3ds + if (pathMap["type"].isValid() && pathMap["type"].toString() == "line3d") { + pathID = qApp->getOverlays().addOverlay(pathMap["type"].toString(), pathMap); + } + } + + QUuid endID; + if (renderStateMap["end"].isValid()) { + QVariantMap endMap = renderStateMap["end"].toMap(); + if (endMap["type"].isValid()) { + endID = qApp->getOverlays().addOverlay(endMap["type"].toString(), endMap); + } + } + + renderStates[name] = RenderState(startID, pathID, endID); + } + } + } + } + if (propertyMap["joint"].isValid()) { QString jointName = propertyMap["joint"].toString(); @@ -39,63 +94,17 @@ uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& prop dirOffset = vec3FromVariant(propertyMap["dirOffset"]); } - uint16_t filter = 0; - if (propertyMap["filter"].isValid()) { - filter = propertyMap["filter"].toUInt(); - } - - float maxDistance = 0.0f; - if (propertyMap["maxDistance"].isValid()) { - maxDistance = propertyMap["maxDistance"].toFloat(); - } - - bool enabled = false; - if (propertyMap["enabled"].isValid()) { - enabled = propertyMap["enabled"].toBool(); - } - - QHash renderStates; - if (propertyMap["renderStates"].isValid()) { - QList renderStateVariants = propertyMap["renderStates"].toList(); - for (QVariant& renderStateVariant : renderStateVariants) { - if (renderStateVariant.isValid()) { - QVariantMap renderStateMap = renderStateVariant.toMap(); - if (renderStateMap["name"].isValid()) { - QString name = renderStateMap["name"].toString(); - - QUuid startID; - if (renderStateMap["start"].isValid()) { - QVariantMap startMap = renderStateMap["start"].toMap(); - if (startMap["type"].isValid()) { - startID = qApp->getOverlays().addOverlay(startMap["type"].toString(), startMap); - } - } - - QUuid pathID; - if (renderStateMap["path"].isValid()) { - QVariantMap pathMap = renderStateMap["path"].toMap(); - // right now paths must be line3ds - if (pathMap["type"].isValid() && pathMap["type"].toString() == "line3d") { - pathID = qApp->getOverlays().addOverlay(pathMap["type"].toString(), pathMap); - } - } - - QUuid endID; - if (renderStateMap["end"].isValid()) { - QVariantMap endMap = renderStateMap["end"].toMap(); - if (endMap["type"].isValid()) { - endID = qApp->getOverlays().addOverlay(endMap["type"].toString(), endMap); - } - } - - renderStates[name] = RenderState(startID, pathID, endID); - } - } - } - } - return LaserPointerManager::getInstance().createLaserPointer(jointName, posOffset, dirOffset, filter, maxDistance, renderStates, enabled); - } else { - return 0; + } else if (propertyMap["position"].isValid()) { + glm::vec3 position = vec3FromVariant(propertyMap["position"]); + + glm::vec3 direction = -Vectors::UP; + if (propertyMap["direction"].isValid()) { + direction = vec3FromVariant(propertyMap["direction"]); + } + + return LaserPointerManager::getInstance().createLaserPointer(position, direction, filter, maxDistance, renderStates, enabled); } + + return 0; } \ No newline at end of file From ae99be0350a65038a3260e495d69486bfb82d413 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 17 Jul 2017 13:07:42 -0700 Subject: [PATCH 11/42] added faceAvatar and centerEndY, working on updating teleport.js, style fixes --- interface/src/raypick/LaserPointer.cpp | 72 ++- interface/src/raypick/LaserPointer.h | 10 +- interface/src/raypick/LaserPointerManager.cpp | 11 +- interface/src/raypick/LaserPointerManager.h | 6 +- .../LaserPointerScriptingInterface.cpp | 14 +- interface/src/raypick/RayPickManager.cpp | 4 +- interface/src/raypick/RayPickManager.h | 4 +- scripts/system/controllers/old_teleport.js | 538 ++++++++++++++++++ scripts/system/controllers/teleport.js | 284 ++++----- 9 files changed, 740 insertions(+), 203 deletions(-) create mode 100644 scripts/system/controllers/old_teleport.js diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index b480d64374..ed5fbd2ece 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -10,44 +10,56 @@ // #include "LaserPointer.h" -#include "RayPickManager.h" #include "JointRayPick.h" #include "StaticRayPick.h" #include "Application.h" +#include "avatar/AvatarManager.h" LaserPointer::LaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, - const QHash& renderStates, const bool enabled) : + const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool enabled) : _renderingEnabled(enabled), - _renderStates(renderStates) + _renderStates(renderStates), + _faceAvatar(faceAvatar), + _centerEndY(centerEndY) { _rayPickUID = RayPickManager::getInstance().addRayPick(std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled)); for (auto& state : _renderStates.keys()) { - if (!enabled || state != _currentRenderState) - disableRenderState(state); + if (!enabled || state != _currentRenderState) { + disableRenderState(state); + } } } LaserPointer::LaserPointer(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance, - const QHash& renderStates, const bool enabled) : + const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool enabled) : _renderingEnabled(enabled), - _renderStates(renderStates) + _renderStates(renderStates), + _faceAvatar(faceAvatar), + _centerEndY(centerEndY) { _rayPickUID = RayPickManager::getInstance().addRayPick(std::make_shared(position, direction, filter, maxDistance, enabled)); for (auto& state : _renderStates.keys()) { - if (!enabled || state != _currentRenderState) + if (!enabled || state != _currentRenderState) { disableRenderState(state); + } } } LaserPointer::~LaserPointer() { RayPickManager::getInstance().removeRayPick(_rayPickUID); for (RenderState& renderState : _renderStates) { - if (!renderState.getStartID().isNull()) qApp->getOverlays().deleteOverlay(renderState.getStartID()); - if (!renderState.getPathID().isNull()) qApp->getOverlays().deleteOverlay(renderState.getPathID()); - if (!renderState.getEndID().isNull()) qApp->getOverlays().deleteOverlay(renderState.getEndID()); + if (!renderState.getStartID().isNull()) { + qApp->getOverlays().deleteOverlay(renderState.getStartID()); + } + if (!renderState.getPathID().isNull()) { + qApp->getOverlays().deleteOverlay(renderState.getPathID()); + } + if (!renderState.getEndID().isNull()) { + qApp->getOverlays().deleteOverlay(renderState.getEndID()); + } } } @@ -59,18 +71,18 @@ void LaserPointer::enable() { void LaserPointer::disable() { RayPickManager::getInstance().disableRayPick(_rayPickUID); _renderingEnabled = false; - if (!_currentRenderState.isEmpty() && _renderStates.contains(_currentRenderState)) disableRenderState(_currentRenderState); + if (!_currentRenderState.isEmpty() && _renderStates.contains(_currentRenderState)) { + disableRenderState(_currentRenderState); + } } void LaserPointer::setRenderState(const QString& state) { - if (!_currentRenderState.isEmpty() && _renderStates.contains(_currentRenderState)) disableRenderState(_currentRenderState); + if (!_currentRenderState.isEmpty() && _renderStates.contains(_currentRenderState)) { + disableRenderState(_currentRenderState); + } _currentRenderState = state; } -const RayPickResult& LaserPointer::getPrevRayPickResult() { - return RayPickManager::getInstance().getPrevRayPickResult(_rayPickUID); -} - void LaserPointer::disableRenderState(const QString& renderState) { if (!_renderStates[renderState].getStartID().isNull()) { QVariantMap startProps; @@ -103,7 +115,8 @@ void LaserPointer::update() { startProps.insert("ignoreRayIntersection", _renderStates[_currentRenderState].doesStartIgnoreRays()); qApp->getOverlays().editOverlay(_renderStates[_currentRenderState].getStartID(), startProps); } - QVariant end = vec3toVariant(pickRay.origin + pickRay.direction * prevRayPickResult.distance); + glm::vec3 endVec = pickRay.origin + pickRay.direction * prevRayPickResult.distance; + QVariant end = vec3toVariant(endVec); if (!_renderStates[_currentRenderState].getPathID().isNull()) { QVariantMap pathProps; pathProps.insert("start", vec3toVariant(pickRay.origin)); @@ -114,7 +127,16 @@ void LaserPointer::update() { } if (!_renderStates[_currentRenderState].getEndID().isNull()) { QVariantMap endProps; - endProps.insert("position", end); + if (_centerEndY) { + endProps.insert("position", end); + } else { + glm::vec3 dim = vec3FromVariant(qApp->getOverlays().getProperty(_renderStates[_currentRenderState].getEndID(), "dimensions").value); + endProps.insert("position", vec3toVariant(endVec + glm::vec3(0, 0.5f * dim.y, 0))); + } + if (_faceAvatar) { + glm::quat rotation = glm::inverse(glm::quat_cast(glm::lookAt(endVec, DependencyManager::get()->getMyAvatar()->getPosition(), Vectors::UP))); + endProps.insert("rotation", quatToVariant(glm::quat(glm::radians(glm::vec3(0, glm::degrees(safeEulerAngles(rotation)).y, 0))))); + } endProps.insert("visible", true); endProps.insert("ignoreRayIntersection", _renderStates[_currentRenderState].doesEndIgnoreRays()); qApp->getOverlays().editOverlay(_renderStates[_currentRenderState].getEndID(), endProps); @@ -127,7 +149,13 @@ void LaserPointer::update() { RenderState::RenderState(const OverlayID& startID, const OverlayID& pathID, const OverlayID& endID) : _startID(startID), _pathID(pathID), _endID(endID) { - if (!_startID.isNull()) _startIgnoreRays = qApp->getOverlays().getOverlay(_startID)->getProperty("ignoreRayIntersection").toBool(); - if (!_pathID.isNull()) _pathIgnoreRays = qApp->getOverlays().getOverlay(_pathID)->getProperty("ignoreRayIntersection").toBool(); - if (!_endID.isNull()) _endIgnoreRays = qApp->getOverlays().getOverlay(_endID)->getProperty("ignoreRayIntersection").toBool(); + if (!_startID.isNull()) { + _startIgnoreRays = qApp->getOverlays().getOverlay(_startID)->getProperty("ignoreRayIntersection").toBool(); + } + if (!_pathID.isNull()) { + _pathIgnoreRays = qApp->getOverlays().getOverlay(_pathID)->getProperty("ignoreRayIntersection").toBool(); + } + if (!_endID.isNull()) { + _endIgnoreRays = qApp->getOverlays().getOverlay(_endID)->getProperty("ignoreRayIntersection").toBool(); + } } \ No newline at end of file diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index ef834d8190..23f3f2a943 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -14,6 +14,7 @@ #include #include "glm/glm.hpp" #include "ui/overlays/Overlay.h" +#include "RayPickManager.h" class RayPickResult; @@ -44,15 +45,15 @@ class LaserPointer { public: LaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, - const QHash& renderStates, const bool enabled); + const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool enabled); LaserPointer(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance, - const QHash& renderStates, const bool enabled); + const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool enabled); ~LaserPointer(); unsigned int getUID() { return _rayPickUID; } void enable(); void disable(); - const RayPickResult& getPrevRayPickResult(); + const RayPickResult& getPrevRayPickResult() { return RayPickManager::getInstance().getPrevRayPickResult(_rayPickUID); } void setRenderState(const QString& state); void disableRenderState(const QString& renderState); @@ -63,6 +64,9 @@ private: bool _renderingEnabled; QString _currentRenderState { "" }; QHash _renderStates; + bool _faceAvatar; + bool _centerEndY; + unsigned int _rayPickUID; }; diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp index 3d0aa1f4b1..e4c9e18127 100644 --- a/interface/src/raypick/LaserPointerManager.cpp +++ b/interface/src/raypick/LaserPointerManager.cpp @@ -18,15 +18,16 @@ LaserPointerManager& LaserPointerManager::getInstance() { } unsigned int LaserPointerManager::createLaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, - const QHash& renderStates, const bool enabled) { - std::shared_ptr laserPointer = std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, renderStates, enabled); + const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool enabled) { + std::shared_ptr laserPointer = std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, renderStates, faceAvatar, centerEndY, enabled); unsigned int uid = laserPointer->getUID(); _laserPointers[uid] = laserPointer; return uid; } -unsigned int LaserPointerManager::createLaserPointer(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance, const QHash& renderStates, const bool enabled) { - std::shared_ptr laserPointer = std::make_shared(position, direction, filter, maxDistance, renderStates, enabled); +unsigned int LaserPointerManager::createLaserPointer(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance, + const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool enabled) { + std::shared_ptr laserPointer = std::make_shared(position, direction, filter, maxDistance, renderStates, faceAvatar, centerEndY, enabled); unsigned int uid = laserPointer->getUID(); _laserPointers[uid] = laserPointer; return uid; @@ -50,7 +51,7 @@ void LaserPointerManager::setRenderState(unsigned int uid, const QString & rende } } -const RayPickResult& LaserPointerManager::getPrevRayPickResult(const unsigned int uid) { +const RayPickResult LaserPointerManager::getPrevRayPickResult(const unsigned int uid) { if (_laserPointers.contains(uid)) { return _laserPointers[uid]->getPrevRayPickResult(); } diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h index f9b59e3bb5..09423bd18a 100644 --- a/interface/src/raypick/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -26,14 +26,14 @@ public: static LaserPointerManager& getInstance(); unsigned int createLaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, - const QHash& renderStates, const bool enabled); + const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool enabled); unsigned int createLaserPointer(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance, - const QHash& renderStates, const bool enabled); + const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool enabled); void removeLaserPointer(const unsigned int uid) { _laserPointers.remove(uid); } void enableLaserPointer(const unsigned int uid); void disableLaserPointer(const unsigned int uid); void setRenderState(unsigned int uid, const QString& renderState); - const RayPickResult& getPrevRayPickResult(const unsigned int uid); + const RayPickResult getPrevRayPickResult(const unsigned int uid); void update(); diff --git a/interface/src/raypick/LaserPointerScriptingInterface.cpp b/interface/src/raypick/LaserPointerScriptingInterface.cpp index 48bbdb5278..cf0289c44b 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.cpp +++ b/interface/src/raypick/LaserPointerScriptingInterface.cpp @@ -35,6 +35,16 @@ uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& prop maxDistance = propertyMap["maxDistance"].toFloat(); } + bool faceAvatar = false; + if (propertyMap["faceAvatar"].isValid()) { + faceAvatar = propertyMap["faceAvatar"].toBool(); + } + + bool centerEndY = true; + if (propertyMap["centerEndY"].isValid()) { + centerEndY = propertyMap["centerEndY"].toBool(); + } + bool enabled = false; if (propertyMap["enabled"].isValid()) { enabled = propertyMap["enabled"].toBool(); @@ -94,7 +104,7 @@ uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& prop dirOffset = vec3FromVariant(propertyMap["dirOffset"]); } - return LaserPointerManager::getInstance().createLaserPointer(jointName, posOffset, dirOffset, filter, maxDistance, renderStates, enabled); + return LaserPointerManager::getInstance().createLaserPointer(jointName, posOffset, dirOffset, filter, maxDistance, renderStates, faceAvatar, centerEndY, enabled); } else if (propertyMap["position"].isValid()) { glm::vec3 position = vec3FromVariant(propertyMap["position"]); @@ -103,7 +113,7 @@ uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& prop direction = vec3FromVariant(propertyMap["direction"]); } - return LaserPointerManager::getInstance().createLaserPointer(position, direction, filter, maxDistance, renderStates, enabled); + return LaserPointerManager::getInstance().createLaserPointer(position, direction, filter, maxDistance, renderStates, faceAvatar, centerEndY, enabled); } return 0; diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp index 68b979a97a..5f1c5add7b 100644 --- a/interface/src/raypick/RayPickManager.cpp +++ b/interface/src/raypick/RayPickManager.cpp @@ -178,7 +178,7 @@ void RayPickManager::disableRayPick(const unsigned int uid) { } } -const PickRay& RayPickManager::getPickRay(const unsigned int uid) { +const PickRay RayPickManager::getPickRay(const unsigned int uid) { if (_rayPicks.contains(uid)) { bool valid; PickRay pickRay = _rayPicks[uid]->getPickRay(valid); @@ -189,7 +189,7 @@ const PickRay& RayPickManager::getPickRay(const unsigned int uid) { return PickRay(); } -const RayPickResult& RayPickManager::getPrevRayPickResult(const unsigned int uid) { +const RayPickResult RayPickManager::getPrevRayPickResult(const unsigned int uid) { // TODO: // does this need to lock the individual ray? what happens with concurrent set/get? if (_rayPicks.contains(uid)) { diff --git a/interface/src/raypick/RayPickManager.h b/interface/src/raypick/RayPickManager.h index 2af98d171c..d798e8a742 100644 --- a/interface/src/raypick/RayPickManager.h +++ b/interface/src/raypick/RayPickManager.h @@ -63,8 +63,8 @@ public: void removeRayPick(const unsigned int uid); void enableRayPick(const unsigned int uid); void disableRayPick(const unsigned int uid); - const PickRay& getPickRay(const unsigned int uid); - const RayPickResult& getPrevRayPickResult(const unsigned int uid); + const PickRay getPickRay(const unsigned int uid); + const RayPickResult getPrevRayPickResult(const unsigned int uid); private: QHash> _rayPicks; diff --git a/scripts/system/controllers/old_teleport.js b/scripts/system/controllers/old_teleport.js new file mode 100644 index 0000000000..b058ec670f --- /dev/null +++ b/scripts/system/controllers/old_teleport.js @@ -0,0 +1,538 @@ +"use strict"; + +// Created by james b. pollack @imgntn on 7/2/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Creates a beam and target and then teleports you there. Release when its close to you to cancel. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +(function() { // BEGIN LOCAL_SCOPE + +var inTeleportMode = false; + +var SMOOTH_ARRIVAL_SPACING = 33; +var NUMBER_OF_STEPS = 6; + +var TARGET_MODEL_URL = Script.resolvePath("../assets/models/teleport-destination.fbx"); +var TOO_CLOSE_MODEL_URL = Script.resolvePath("../assets/models/teleport-cancel.fbx"); +var SEAT_MODEL_URL = Script.resolvePath("../assets/models/teleport-seat.fbx"); + +var TARGET_MODEL_DIMENSIONS = { + x: 1.15, + y: 0.5, + z: 1.15 +}; + +var COLORS_TELEPORT_SEAT = { + red: 255, + green: 0, + blue: 170 +}; + +var COLORS_TELEPORT_CAN_TELEPORT = { + red: 97, + green: 247, + blue: 255 +}; + +var COLORS_TELEPORT_CANNOT_TELEPORT = { + red: 0, + green: 121, + blue: 141 +}; + +var COLORS_TELEPORT_CANCEL = { + red: 255, + green: 184, + blue: 73 +}; + +var TELEPORT_CANCEL_RANGE = 1; +var COOL_IN_DURATION = 500; + +var handInfo = { + right: { + controllerInput: Controller.Standard.RightHand + }, + left: { + controllerInput: Controller.Standard.LeftHand + } +}; + +function ThumbPad(hand) { + this.hand = hand; + var _thisPad = this; + + this.buttonPress = function(value) { + _thisPad.buttonValue = value; + }; +} + +function Trigger(hand) { + this.hand = hand; + var _this = this; + + this.buttonPress = function(value) { + _this.buttonValue = value; + }; + + this.down = function() { + var down = _this.buttonValue === 1 ? 1.0 : 0.0; + return down; + }; +} + +var coolInTimeout = null; +var ignoredEntities = []; + +var TELEPORTER_STATES = { + IDLE: 'idle', + COOL_IN: 'cool_in', + TARGETTING: 'targetting', + TARGETTING_INVALID: 'targetting_invalid', +}; + +var TARGET = { + NONE: 'none', // Not currently targetting anything + INVISIBLE: 'invisible', // The current target is an invvsible surface + INVALID: 'invalid', // The current target is invalid (wall, ceiling, etc.) + SURFACE: 'surface', // The current target is a valid surface + SEAT: 'seat', // The current target is a seat +}; + +function Teleporter() { + var _this = this; + this.active = false; + this.state = TELEPORTER_STATES.IDLE; + this.currentTarget = TARGET.INVALID; + + this.overlayLines = { + left: null, + right: null, + }; + this.updateConnected = null; + this.activeHand = null; + + this.teleporterMappingInternalName = 'Hifi-Teleporter-Internal-Dev-' + Math.random(); + this.teleportMappingInternal = Controller.newMapping(this.teleporterMappingInternalName); + + // Setup overlays + this.cancelOverlay = Overlays.addOverlay("model", { + url: TOO_CLOSE_MODEL_URL, + dimensions: TARGET_MODEL_DIMENSIONS, + visible: false + }); + this.targetOverlay = Overlays.addOverlay("model", { + url: TARGET_MODEL_URL, + dimensions: TARGET_MODEL_DIMENSIONS, + visible: false + }); + this.seatOverlay = Overlays.addOverlay("model", { + url: SEAT_MODEL_URL, + dimensions: TARGET_MODEL_DIMENSIONS, + visible: false + }); + + this.enableMappings = function() { + Controller.enableMapping(this.teleporterMappingInternalName); + }; + + this.disableMappings = function() { + Controller.disableMapping(teleporter.teleporterMappingInternalName); + }; + + this.cleanup = function() { + this.disableMappings(); + + Overlays.deleteOverlay(this.targetOverlay); + this.targetOverlay = null; + + Overlays.deleteOverlay(this.cancelOverlay); + this.cancelOverlay = null; + + Overlays.deleteOverlay(this.seatOverlay); + this.seatOverlay = null; + + this.deleteOverlayBeams(); + if (this.updateConnected === true) { + Script.update.disconnect(this, this.update); + } + }; + + this.enterTeleportMode = function(hand) { + if (inTeleportMode === true) { + return; + } + if (isDisabled === 'both' || isDisabled === hand) { + return; + } + + inTeleportMode = true; + + if (coolInTimeout !== null) { + Script.clearTimeout(coolInTimeout); + } + + this.state = TELEPORTER_STATES.COOL_IN; + coolInTimeout = Script.setTimeout(function() { + if (_this.state === TELEPORTER_STATES.COOL_IN) { + _this.state = TELEPORTER_STATES.TARGETTING; + } + }, COOL_IN_DURATION); + + this.activeHand = hand; + this.enableMappings(); + Script.update.connect(this, this.update); + this.updateConnected = true; + }; + + this.exitTeleportMode = function(value) { + if (this.updateConnected === true) { + Script.update.disconnect(this, this.update); + } + + this.disableMappings(); + this.deleteOverlayBeams(); + this.hideTargetOverlay(); + this.hideCancelOverlay(); + + this.updateConnected = null; + this.state = TELEPORTER_STATES.IDLE; + inTeleportMode = false; + }; + + this.deleteOverlayBeams = function() { + for (var key in this.overlayLines) { + if (this.overlayLines[key] !== null) { + Overlays.deleteOverlay(this.overlayLines[key]); + this.overlayLines[key] = null; + } + } + }; + + this.update = function() { + if (_this.state === TELEPORTER_STATES.IDLE) { + return; + } + + // Get current hand pose information so that we can get the direction of the teleport beam + var pose = Controller.getPoseValue(handInfo[_this.activeHand].controllerInput); + var handPosition = pose.valid ? Vec3.sum(Vec3.multiplyQbyV(MyAvatar.orientation, pose.translation), MyAvatar.position) : MyAvatar.getHeadPosition(); + var handRotation = pose.valid ? Quat.multiply(MyAvatar.orientation, pose.rotation) : + Quat.multiply(MyAvatar.headOrientation, Quat.angleAxis(-90, { + x: 1, + y: 0, + z: 0 + })); + + var pickRay = { + origin: handPosition, + direction: Quat.getUp(handRotation), + }; + + // We do up to 2 ray picks to find a teleport location. + // There are 2 types of teleport locations we are interested in: + // 1. A visible floor. This can be any entity surface that points within some degree of "up" + // 2. A seat. The seat can be visible or invisible. + // + // * In the first pass we pick against visible and invisible entities so that we can find invisible seats. + // We might hit an invisible entity that is not a seat, so we need to do a second pass. + // * In the second pass we pick against visible entities only. + // + var intersection = Entities.findRayIntersection(pickRay, true, [], [this.targetEntity].concat(ignoredEntities), false, true); + + var teleportLocationType = getTeleportTargetType(intersection); + if (teleportLocationType === TARGET.INVISIBLE) { + intersection = Entities.findRayIntersection(pickRay, true, [], [this.targetEntity].concat(ignoredEntities), true, true); + teleportLocationType = getTeleportTargetType(intersection); + } + + if (teleportLocationType === TARGET.NONE) { + this.hideTargetOverlay(); + this.hideCancelOverlay(); + this.hideSeatOverlay(); + + var farPosition = Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction, 50)); + this.updateLineOverlay(_this.activeHand, pickRay.origin, farPosition, COLORS_TELEPORT_CANNOT_TELEPORT); + } else if (teleportLocationType === TARGET.INVALID || teleportLocationType === TARGET.INVISIBLE) { + this.hideTargetOverlay(); + this.hideSeatOverlay(); + + this.updateLineOverlay(_this.activeHand, pickRay.origin, intersection.intersection, COLORS_TELEPORT_CANCEL); + this.updateDestinationOverlay(this.cancelOverlay, intersection); + } else if (teleportLocationType === TARGET.SURFACE) { + if (this.state === TELEPORTER_STATES.COOL_IN) { + this.hideTargetOverlay(); + this.hideSeatOverlay(); + + this.updateLineOverlay(_this.activeHand, pickRay.origin, intersection.intersection, COLORS_TELEPORT_CANCEL); + this.updateDestinationOverlay(this.cancelOverlay, intersection); + } else { + this.hideCancelOverlay(); + this.hideSeatOverlay(); + + this.updateLineOverlay(_this.activeHand, pickRay.origin, intersection.intersection, + COLORS_TELEPORT_CAN_TELEPORT); + this.updateDestinationOverlay(this.targetOverlay, intersection); + } + } else if (teleportLocationType === TARGET.SEAT) { + this.hideCancelOverlay(); + this.hideTargetOverlay(); + + this.updateLineOverlay(_this.activeHand, pickRay.origin, intersection.intersection, COLORS_TELEPORT_SEAT); + this.updateDestinationOverlay(this.seatOverlay, intersection); + } + + + if (((_this.activeHand === 'left' ? leftPad : rightPad).buttonValue === 0) && inTeleportMode === true) { + // remember the state before we exit teleport mode and set it back to IDLE + var previousState = this.state; + this.exitTeleportMode(); + this.hideCancelOverlay(); + this.hideTargetOverlay(); + this.hideSeatOverlay(); + + if (teleportLocationType === TARGET.NONE || teleportLocationType === TARGET.INVALID || previousState === TELEPORTER_STATES.COOL_IN) { + // Do nothing + } else if (teleportLocationType === TARGET.SEAT) { + Entities.callEntityMethod(intersection.entityID, 'sit'); + } else if (teleportLocationType === TARGET.SURFACE) { + var offset = getAvatarFootOffset(); + intersection.intersection.y += offset; + MyAvatar.goToLocation(intersection.intersection, false, {x: 0, y: 0, z: 0, w: 1}, false); + HMD.centerUI(); + MyAvatar.centerBody(); + } + } + }; + + this.updateLineOverlay = function(hand, closePoint, farPoint, color) { + if (this.overlayLines[hand] === null) { + var lineProperties = { + start: closePoint, + end: farPoint, + color: color, + ignoreRayIntersection: true, + visible: true, + alpha: 1, + solid: true, + drawInFront: true, + glow: 1.0 + }; + + this.overlayLines[hand] = Overlays.addOverlay("line3d", lineProperties); + + } else { + Overlays.editOverlay(this.overlayLines[hand], { + start: closePoint, + end: farPoint, + color: color + }); + } + }; + + this.hideCancelOverlay = function() { + Overlays.editOverlay(this.cancelOverlay, { visible: false }); + }; + + this.hideTargetOverlay = function() { + Overlays.editOverlay(this.targetOverlay, { visible: false }); + }; + + this.hideSeatOverlay = function() { + Overlays.editOverlay(this.seatOverlay, { visible: false }); + }; + + this.updateDestinationOverlay = function(overlayID, intersection) { + var rotation = Quat.lookAt(intersection.intersection, MyAvatar.position, Vec3.UP); + var euler = Quat.safeEulerAngles(rotation); + var position = { + x: intersection.intersection.x, + y: intersection.intersection.y + TARGET_MODEL_DIMENSIONS.y / 2, + z: intersection.intersection.z + }; + + var towardUs = Quat.fromPitchYawRollDegrees(0, euler.y, 0); + + Overlays.editOverlay(overlayID, { + visible: true, + position: position, + rotation: towardUs + }); + + }; +} + +// related to repositioning the avatar after you teleport +var FOOT_JOINT_NAMES = ["RightToe_End", "RightToeBase", "RightFoot"]; +var DEFAULT_ROOT_TO_FOOT_OFFSET = 0.5; +function getAvatarFootOffset() { + + // find a valid foot jointIndex + var footJointIndex = -1; + var i, l = FOOT_JOINT_NAMES.length; + for (i = 0; i < l; i++) { + footJointIndex = MyAvatar.getJointIndex(FOOT_JOINT_NAMES[i]); + if (footJointIndex != -1) { + break; + } + } + if (footJointIndex != -1) { + // default vertical offset from foot to avatar root. + return -MyAvatar.getAbsoluteDefaultJointTranslationInObjectFrame(footJointIndex).y; + } else { + return DEFAULT_ROOT_TO_FOOT_OFFSET * MyAvatar.scale; + } +} + +var leftPad = new ThumbPad('left'); +var rightPad = new ThumbPad('right'); +var leftTrigger = new Trigger('left'); +var rightTrigger = new Trigger('right'); + +var mappingName, teleportMapping; + +var TELEPORT_DELAY = 0; + +function isMoving() { + var LY = Controller.getValue(Controller.Standard.LY); + var LX = Controller.getValue(Controller.Standard.LX); + if (LY !== 0 || LX !== 0) { + return true; + } else { + return false; + } +} + +function parseJSON(json) { + try { + return JSON.parse(json); + } catch (e) { + return undefined; + } +} +// When determininig whether you can teleport to a location, the normal of the +// point that is being intersected with is looked at. If this normal is more +// than MAX_ANGLE_FROM_UP_TO_TELEPORT degrees from <0, 1, 0> (straight up), then +// you can't teleport there. +var MAX_ANGLE_FROM_UP_TO_TELEPORT = 70; +function getTeleportTargetType(intersection) { + if (!intersection.intersects) { + return TARGET.NONE; + } + + var props = Entities.getEntityProperties(intersection.entityID, ['userData', 'visible']); + var data = parseJSON(props.userData); + if (data !== undefined && data.seat !== undefined) { + var avatarUuid = Uuid.fromString(data.seat.user); + if (Uuid.isNull(avatarUuid) || !AvatarList.getAvatar(avatarUuid)) { + return TARGET.SEAT; + } else { + return TARGET.INVALID; + } + } + + if (!props.visible) { + return TARGET.INVISIBLE; + } + + var surfaceNormal = intersection.surfaceNormal; + var adj = Math.sqrt(surfaceNormal.x * surfaceNormal.x + surfaceNormal.z * surfaceNormal.z); + var angleUp = Math.atan2(surfaceNormal.y, adj) * (180 / Math.PI); + + if (angleUp < (90 - MAX_ANGLE_FROM_UP_TO_TELEPORT) || + angleUp > (90 + MAX_ANGLE_FROM_UP_TO_TELEPORT) || + Vec3.distance(MyAvatar.position, intersection.intersection) <= TELEPORT_CANCEL_RANGE) { + return TARGET.INVALID; + } else { + return TARGET.SURFACE; + } +} + +function registerMappings() { + mappingName = 'Hifi-Teleporter-Dev-' + Math.random(); + teleportMapping = Controller.newMapping(mappingName); + teleportMapping.from(Controller.Standard.RT).peek().to(rightTrigger.buttonPress); + teleportMapping.from(Controller.Standard.LT).peek().to(leftTrigger.buttonPress); + + teleportMapping.from(Controller.Standard.RightPrimaryThumb).peek().to(rightPad.buttonPress); + teleportMapping.from(Controller.Standard.LeftPrimaryThumb).peek().to(leftPad.buttonPress); + + teleportMapping.from(Controller.Standard.LeftPrimaryThumb) + .to(function(value) { + if (isDisabled === 'left' || isDisabled === 'both') { + return; + } + if (leftTrigger.down()) { + return; + } + if (isMoving() === true) { + return; + } + teleporter.enterTeleportMode('left'); + return; + }); + teleportMapping.from(Controller.Standard.RightPrimaryThumb) + .to(function(value) { + if (isDisabled === 'right' || isDisabled === 'both') { + return; + } + if (rightTrigger.down()) { + return; + } + if (isMoving() === true) { + return; + } + + teleporter.enterTeleportMode('right'); + return; + }); +} + +registerMappings(); + +var teleporter = new Teleporter(); + +Controller.enableMapping(mappingName); + +function cleanup() { + teleportMapping.disable(); + teleporter.cleanup(); +} +Script.scriptEnding.connect(cleanup); + +var isDisabled = false; +var handleTeleportMessages = function(channel, message, sender) { + if (sender === MyAvatar.sessionUUID) { + if (channel === 'Hifi-Teleport-Disabler') { + if (message === 'both') { + isDisabled = 'both'; + } + if (message === 'left') { + isDisabled = 'left'; + } + if (message === 'right') { + isDisabled = 'right'; + } + if (message === 'none') { + isDisabled = false; + } + } else if (channel === 'Hifi-Teleport-Ignore-Add' && !Uuid.isNull(message) && ignoredEntities.indexOf(message) === -1) { + ignoredEntities.push(message); + } else if (channel === 'Hifi-Teleport-Ignore-Remove' && !Uuid.isNull(message)) { + var removeIndex = ignoredEntities.indexOf(message); + if (removeIndex > -1) { + ignoredEntities.splice(removeIndex, 1); + } + } + } +}; + +Messages.subscribe('Hifi-Teleport-Disabler'); +Messages.subscribe('Hifi-Teleport-Ignore-Add'); +Messages.subscribe('Hifi-Teleport-Ignore-Remove'); +Messages.messageReceived.connect(handleTeleportMessages); + +}()); // END LOCAL_SCOPE diff --git a/scripts/system/controllers/teleport.js b/scripts/system/controllers/teleport.js index b058ec670f..b72828ea6b 100644 --- a/scripts/system/controllers/teleport.js +++ b/scripts/system/controllers/teleport.js @@ -37,12 +37,6 @@ var COLORS_TELEPORT_CAN_TELEPORT = { blue: 255 }; -var COLORS_TELEPORT_CANNOT_TELEPORT = { - red: 0, - green: 121, - blue: 141 -}; - var COLORS_TELEPORT_CANCEL = { red: 255, green: 184, @@ -52,14 +46,55 @@ var COLORS_TELEPORT_CANCEL = { var TELEPORT_CANCEL_RANGE = 1; var COOL_IN_DURATION = 500; -var handInfo = { - right: { - controllerInput: Controller.Standard.RightHand - }, - left: { - controllerInput: Controller.Standard.LeftHand - } +var cancelPath = { + type: "line3d", + color: COLORS_TELEPORT_CANCEL, + ignoreRayIntersection: true, + alpha: 1, + solid: true, + drawInFront: true, + glow: 1.0 }; +var teleportPath = { + type: "line3d", + color: COLORS_TELEPORT_CAN_TELEPORT, + ignoreRayIntersection: true, + alpha: 1, + solid: true, + drawInFront: true, + glow: 1.0 +}; +var seatPath = { + type: "line3d", + color: COLORS_TELEPORT_SEAT, + ignoreRayIntersection: true, + alpha: 1, + solid: true, + drawInFront: true, + glow: 1.0 +}; +var cancelEnd = { + type: "model", + url: TOO_CLOSE_MODEL_URL, + dimensions: TARGET_MODEL_DIMENSIONS, + ignoreRayIntersection: true +}; +var teleportEnd = { + type: "model", + url: TARGET_MODEL_URL, + dimensions: TARGET_MODEL_DIMENSIONS, + ignoreRayIntersection: true +}; +var seatEnd = { + type: "model", + url: SEAT_MODEL_URL, + dimensions: TARGET_MODEL_DIMENSIONS, + ignoreRayIntersection: true +} + +var teleportRenderStates = [{name: "cancel", path: cancelPath, end: cancelEnd}, + {name: "teleport", path: teleportPath, end: teleportEnd}, + {name: "seat", path: seatPath, end: seatEnd}]; function ThumbPad(hand) { this.hand = hand; @@ -108,33 +143,41 @@ function Teleporter() { this.state = TELEPORTER_STATES.IDLE; this.currentTarget = TARGET.INVALID; - this.overlayLines = { - left: null, - right: null, - }; + this.teleportRayLeftVisible = LaserPointers.createLaserPointer({ + joint: "LeftHand", + filter: RayPick.PICK_ENTITIES, + faceAvatar: true, + centerEndY: false, + renderStates: teleportRenderStates + }); + this.teleportRayLeftInvisible = LaserPointers.createLaserPointer({ + joint: "LeftHand", + filter: RayPick.PICK_ENTITIES | RayPick.PICK_INCLUDE_INVISIBLE, + faceAvatar: true, + centerEndY: false, + renderStates: teleportRenderStates + }); + this.teleportRayRightVisible = LaserPointers.createLaserPointer({ + joint: "RightHand", + filter: RayPick.PICK_ENTITIES, + faceAvatar: true, + centerEndY: false, + renderStates: teleportRenderStates + }); + this.teleportRayRightInvisible = LaserPointers.createLaserPointer({ + joint: "RightHand", + filter: RayPick.PICK_ENTITIES | RayPick.PICK_INCLUDE_INVISIBLE, + faceAvatar: true, + centerEndY: false, + renderStates: teleportRenderStates + }); + this.updateConnected = null; this.activeHand = null; this.teleporterMappingInternalName = 'Hifi-Teleporter-Internal-Dev-' + Math.random(); this.teleportMappingInternal = Controller.newMapping(this.teleporterMappingInternalName); - // Setup overlays - this.cancelOverlay = Overlays.addOverlay("model", { - url: TOO_CLOSE_MODEL_URL, - dimensions: TARGET_MODEL_DIMENSIONS, - visible: false - }); - this.targetOverlay = Overlays.addOverlay("model", { - url: TARGET_MODEL_URL, - dimensions: TARGET_MODEL_DIMENSIONS, - visible: false - }); - this.seatOverlay = Overlays.addOverlay("model", { - url: SEAT_MODEL_URL, - dimensions: TARGET_MODEL_DIMENSIONS, - visible: false - }); - this.enableMappings = function() { Controller.enableMapping(this.teleporterMappingInternalName); }; @@ -146,16 +189,11 @@ function Teleporter() { this.cleanup = function() { this.disableMappings(); - Overlays.deleteOverlay(this.targetOverlay); - this.targetOverlay = null; + LaserPointers.removeLaserPointer(this.teleportRayLeftVisible); + LaserPointers.removeLaserPointer(this.teleportRayLeftInvisible); + LaserPointers.removeLaserPointer(this.teleportRayRightVisible); + LaserPointers.removeLaserPointer(this.teleportRayRightInvisible); - Overlays.deleteOverlay(this.cancelOverlay); - this.cancelOverlay = null; - - Overlays.deleteOverlay(this.seatOverlay); - this.seatOverlay = null; - - this.deleteOverlayBeams(); if (this.updateConnected === true) { Script.update.disconnect(this, this.update); } @@ -175,6 +213,14 @@ function Teleporter() { Script.clearTimeout(coolInTimeout); } + if (hand === 'right') { + LaserPointers.enableLaserPointer(_this.teleportRayRightVisible); + LaserPointers.enableLaserPointer(_this.teleportRayRightInvisible); + } else { + LaserPointers.enableLaserPointer(_this.teleportRayLeftVisible); + LaserPointers.enableLaserPointer(_this.teleportRayLeftInvisible); + } + this.state = TELEPORTER_STATES.COOL_IN; coolInTimeout = Script.setTimeout(function() { if (_this.state === TELEPORTER_STATES.COOL_IN) { @@ -194,44 +240,21 @@ function Teleporter() { } this.disableMappings(); - this.deleteOverlayBeams(); - this.hideTargetOverlay(); - this.hideCancelOverlay(); + LaserPointers.disableLaserPointer(this.teleportRayLeftVisible); + LaserPointers.disableLaserPointer(this.teleportRayLeftInvisible); + LaserPointers.disableLaserPointer(this.teleportRayRightVisible); + LaserPointers.disableLaserPointer(this.teleportRayRightInvisible); this.updateConnected = null; this.state = TELEPORTER_STATES.IDLE; inTeleportMode = false; }; - this.deleteOverlayBeams = function() { - for (var key in this.overlayLines) { - if (this.overlayLines[key] !== null) { - Overlays.deleteOverlay(this.overlayLines[key]); - this.overlayLines[key] = null; - } - } - }; - this.update = function() { if (_this.state === TELEPORTER_STATES.IDLE) { return; } - // Get current hand pose information so that we can get the direction of the teleport beam - var pose = Controller.getPoseValue(handInfo[_this.activeHand].controllerInput); - var handPosition = pose.valid ? Vec3.sum(Vec3.multiplyQbyV(MyAvatar.orientation, pose.translation), MyAvatar.position) : MyAvatar.getHeadPosition(); - var handRotation = pose.valid ? Quat.multiply(MyAvatar.orientation, pose.rotation) : - Quat.multiply(MyAvatar.headOrientation, Quat.angleAxis(-90, { - x: 1, - y: 0, - z: 0 - })); - - var pickRay = { - origin: handPosition, - direction: Quat.getUp(handRotation), - }; - // We do up to 2 ray picks to find a teleport location. // There are 2 types of teleport locations we are interested in: // 1. A visible floor. This can be any entity surface that points within some degree of "up" @@ -241,48 +264,28 @@ function Teleporter() { // We might hit an invisible entity that is not a seat, so we need to do a second pass. // * In the second pass we pick against visible entities only. // - var intersection = Entities.findRayIntersection(pickRay, true, [], [this.targetEntity].concat(ignoredEntities), false, true); + var result = (_this.activeHand === 'right') ? LaserPointers.getPrevRayPickResult(_this.teleportRayRightInvisible) : + LaserPointers.getPrevRayPickResult(_this.teleportRayLeftInvisible); - var teleportLocationType = getTeleportTargetType(intersection); + var teleportLocationType = getTeleportTargetType(result); if (teleportLocationType === TARGET.INVISIBLE) { - intersection = Entities.findRayIntersection(pickRay, true, [], [this.targetEntity].concat(ignoredEntities), true, true); - teleportLocationType = getTeleportTargetType(intersection); + result = (_this.activeHand === 'right') ? LaserPointers.getPrevRayPickResult(_this.teleportRayRightVisible) : + LaserPointers.getPrevRayPickResult(_this.teleportRayLeftVisible); + teleportLocationType = getTeleportTargetType(result); } if (teleportLocationType === TARGET.NONE) { - this.hideTargetOverlay(); - this.hideCancelOverlay(); - this.hideSeatOverlay(); - - var farPosition = Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction, 50)); - this.updateLineOverlay(_this.activeHand, pickRay.origin, farPosition, COLORS_TELEPORT_CANNOT_TELEPORT); + this.setTeleportState(_this.activeHand, "", ""); } else if (teleportLocationType === TARGET.INVALID || teleportLocationType === TARGET.INVISIBLE) { - this.hideTargetOverlay(); - this.hideSeatOverlay(); - - this.updateLineOverlay(_this.activeHand, pickRay.origin, intersection.intersection, COLORS_TELEPORT_CANCEL); - this.updateDestinationOverlay(this.cancelOverlay, intersection); + this.setTeleportState(_this.activeHand, "", "cancel"); } else if (teleportLocationType === TARGET.SURFACE) { if (this.state === TELEPORTER_STATES.COOL_IN) { - this.hideTargetOverlay(); - this.hideSeatOverlay(); - - this.updateLineOverlay(_this.activeHand, pickRay.origin, intersection.intersection, COLORS_TELEPORT_CANCEL); - this.updateDestinationOverlay(this.cancelOverlay, intersection); + this.setTeleportState(_this.activeHand, "cancel", ""); } else { - this.hideCancelOverlay(); - this.hideSeatOverlay(); - - this.updateLineOverlay(_this.activeHand, pickRay.origin, intersection.intersection, - COLORS_TELEPORT_CAN_TELEPORT); - this.updateDestinationOverlay(this.targetOverlay, intersection); + this.setTeleportState(_this.activeHand, "teleport", ""); } } else if (teleportLocationType === TARGET.SEAT) { - this.hideCancelOverlay(); - this.hideTargetOverlay(); - - this.updateLineOverlay(_this.activeHand, pickRay.origin, intersection.intersection, COLORS_TELEPORT_SEAT); - this.updateDestinationOverlay(this.seatOverlay, intersection); + this.setTeleportState(_this.activeHand, "", "seat"); } @@ -290,79 +293,30 @@ function Teleporter() { // remember the state before we exit teleport mode and set it back to IDLE var previousState = this.state; this.exitTeleportMode(); - this.hideCancelOverlay(); - this.hideTargetOverlay(); - this.hideSeatOverlay(); if (teleportLocationType === TARGET.NONE || teleportLocationType === TARGET.INVALID || previousState === TELEPORTER_STATES.COOL_IN) { // Do nothing } else if (teleportLocationType === TARGET.SEAT) { - Entities.callEntityMethod(intersection.entityID, 'sit'); + Entities.callEntityMethod(result.objectID, 'sit'); } else if (teleportLocationType === TARGET.SURFACE) { var offset = getAvatarFootOffset(); - intersection.intersection.y += offset; - MyAvatar.goToLocation(intersection.intersection, false, {x: 0, y: 0, z: 0, w: 1}, false); + result.intersection.y += offset; + MyAvatar.goToLocation(result.intersection, false, {x: 0, y: 0, z: 0, w: 1}, false); HMD.centerUI(); MyAvatar.centerBody(); } } }; - this.updateLineOverlay = function(hand, closePoint, farPoint, color) { - if (this.overlayLines[hand] === null) { - var lineProperties = { - start: closePoint, - end: farPoint, - color: color, - ignoreRayIntersection: true, - visible: true, - alpha: 1, - solid: true, - drawInFront: true, - glow: 1.0 - }; - - this.overlayLines[hand] = Overlays.addOverlay("line3d", lineProperties); - + this.setTeleportState = function(hand, visibleState, invisibleState) { + if (hand === 'right') { + LaserPointers.setRenderState(_this.teleportRayRightVisible, visibleState); + LaserPointers.setRenderState(_this.teleportRayRightInvisible, invisibleState); } else { - Overlays.editOverlay(this.overlayLines[hand], { - start: closePoint, - end: farPoint, - color: color - }); + LaserPointers.setRenderState(_this.teleportRayLeftVisible, visibleState); + LaserPointers.setRenderState(_this.teleportRayLeftInvisible, invisibleState); } }; - - this.hideCancelOverlay = function() { - Overlays.editOverlay(this.cancelOverlay, { visible: false }); - }; - - this.hideTargetOverlay = function() { - Overlays.editOverlay(this.targetOverlay, { visible: false }); - }; - - this.hideSeatOverlay = function() { - Overlays.editOverlay(this.seatOverlay, { visible: false }); - }; - - this.updateDestinationOverlay = function(overlayID, intersection) { - var rotation = Quat.lookAt(intersection.intersection, MyAvatar.position, Vec3.UP); - var euler = Quat.safeEulerAngles(rotation); - var position = { - x: intersection.intersection.x, - y: intersection.intersection.y + TARGET_MODEL_DIMENSIONS.y / 2, - z: intersection.intersection.z - }; - - var towardUs = Quat.fromPitchYawRollDegrees(0, euler.y, 0); - - Overlays.editOverlay(overlayID, { - visible: true, - position: position, - rotation: towardUs - }); - - }; } // related to repositioning the avatar after you teleport @@ -418,12 +372,12 @@ function parseJSON(json) { // than MAX_ANGLE_FROM_UP_TO_TELEPORT degrees from <0, 1, 0> (straight up), then // you can't teleport there. var MAX_ANGLE_FROM_UP_TO_TELEPORT = 70; -function getTeleportTargetType(intersection) { - if (!intersection.intersects) { +function getTeleportTargetType(result) { + if (result.type == RayPick.INTERSECTED_NONE) { return TARGET.NONE; } - var props = Entities.getEntityProperties(intersection.entityID, ['userData', 'visible']); + var props = Entities.getEntityProperties(result.objectID, ['userData', 'visible']); var data = parseJSON(props.userData); if (data !== undefined && data.seat !== undefined) { var avatarUuid = Uuid.fromString(data.seat.user); @@ -438,13 +392,13 @@ function getTeleportTargetType(intersection) { return TARGET.INVISIBLE; } - var surfaceNormal = intersection.surfaceNormal; + var surfaceNormal = result.surfaceNormal; var adj = Math.sqrt(surfaceNormal.x * surfaceNormal.x + surfaceNormal.z * surfaceNormal.z); var angleUp = Math.atan2(surfaceNormal.y, adj) * (180 / Math.PI); if (angleUp < (90 - MAX_ANGLE_FROM_UP_TO_TELEPORT) || angleUp > (90 + MAX_ANGLE_FROM_UP_TO_TELEPORT) || - Vec3.distance(MyAvatar.position, intersection.intersection) <= TELEPORT_CANCEL_RANGE) { + Vec3.distance(MyAvatar.position, result.intersection) <= TELEPORT_CANCEL_RANGE) { return TARGET.INVALID; } else { return TARGET.SURFACE; @@ -520,6 +474,8 @@ var handleTeleportMessages = function(channel, message, sender) { isDisabled = false; } } else if (channel === 'Hifi-Teleport-Ignore-Add' && !Uuid.isNull(message) && ignoredEntities.indexOf(message) === -1) { + // TODO: + // add ability to ignore entities to LaserPointers ignoredEntities.push(message); } else if (channel === 'Hifi-Teleport-Ignore-Remove' && !Uuid.isNull(message)) { var removeIndex = ignoredEntities.indexOf(message); From 197ba83b103ab1caf74d2905b8936d87df8e838d Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 17 Jul 2017 13:46:23 -0700 Subject: [PATCH 12/42] remove old_teleport --- scripts/system/controllers/old_teleport.js | 538 --------------------- 1 file changed, 538 deletions(-) delete mode 100644 scripts/system/controllers/old_teleport.js diff --git a/scripts/system/controllers/old_teleport.js b/scripts/system/controllers/old_teleport.js deleted file mode 100644 index b058ec670f..0000000000 --- a/scripts/system/controllers/old_teleport.js +++ /dev/null @@ -1,538 +0,0 @@ -"use strict"; - -// Created by james b. pollack @imgntn on 7/2/2016 -// Copyright 2016 High Fidelity, Inc. -// -// Creates a beam and target and then teleports you there. Release when its close to you to cancel. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -(function() { // BEGIN LOCAL_SCOPE - -var inTeleportMode = false; - -var SMOOTH_ARRIVAL_SPACING = 33; -var NUMBER_OF_STEPS = 6; - -var TARGET_MODEL_URL = Script.resolvePath("../assets/models/teleport-destination.fbx"); -var TOO_CLOSE_MODEL_URL = Script.resolvePath("../assets/models/teleport-cancel.fbx"); -var SEAT_MODEL_URL = Script.resolvePath("../assets/models/teleport-seat.fbx"); - -var TARGET_MODEL_DIMENSIONS = { - x: 1.15, - y: 0.5, - z: 1.15 -}; - -var COLORS_TELEPORT_SEAT = { - red: 255, - green: 0, - blue: 170 -}; - -var COLORS_TELEPORT_CAN_TELEPORT = { - red: 97, - green: 247, - blue: 255 -}; - -var COLORS_TELEPORT_CANNOT_TELEPORT = { - red: 0, - green: 121, - blue: 141 -}; - -var COLORS_TELEPORT_CANCEL = { - red: 255, - green: 184, - blue: 73 -}; - -var TELEPORT_CANCEL_RANGE = 1; -var COOL_IN_DURATION = 500; - -var handInfo = { - right: { - controllerInput: Controller.Standard.RightHand - }, - left: { - controllerInput: Controller.Standard.LeftHand - } -}; - -function ThumbPad(hand) { - this.hand = hand; - var _thisPad = this; - - this.buttonPress = function(value) { - _thisPad.buttonValue = value; - }; -} - -function Trigger(hand) { - this.hand = hand; - var _this = this; - - this.buttonPress = function(value) { - _this.buttonValue = value; - }; - - this.down = function() { - var down = _this.buttonValue === 1 ? 1.0 : 0.0; - return down; - }; -} - -var coolInTimeout = null; -var ignoredEntities = []; - -var TELEPORTER_STATES = { - IDLE: 'idle', - COOL_IN: 'cool_in', - TARGETTING: 'targetting', - TARGETTING_INVALID: 'targetting_invalid', -}; - -var TARGET = { - NONE: 'none', // Not currently targetting anything - INVISIBLE: 'invisible', // The current target is an invvsible surface - INVALID: 'invalid', // The current target is invalid (wall, ceiling, etc.) - SURFACE: 'surface', // The current target is a valid surface - SEAT: 'seat', // The current target is a seat -}; - -function Teleporter() { - var _this = this; - this.active = false; - this.state = TELEPORTER_STATES.IDLE; - this.currentTarget = TARGET.INVALID; - - this.overlayLines = { - left: null, - right: null, - }; - this.updateConnected = null; - this.activeHand = null; - - this.teleporterMappingInternalName = 'Hifi-Teleporter-Internal-Dev-' + Math.random(); - this.teleportMappingInternal = Controller.newMapping(this.teleporterMappingInternalName); - - // Setup overlays - this.cancelOverlay = Overlays.addOverlay("model", { - url: TOO_CLOSE_MODEL_URL, - dimensions: TARGET_MODEL_DIMENSIONS, - visible: false - }); - this.targetOverlay = Overlays.addOverlay("model", { - url: TARGET_MODEL_URL, - dimensions: TARGET_MODEL_DIMENSIONS, - visible: false - }); - this.seatOverlay = Overlays.addOverlay("model", { - url: SEAT_MODEL_URL, - dimensions: TARGET_MODEL_DIMENSIONS, - visible: false - }); - - this.enableMappings = function() { - Controller.enableMapping(this.teleporterMappingInternalName); - }; - - this.disableMappings = function() { - Controller.disableMapping(teleporter.teleporterMappingInternalName); - }; - - this.cleanup = function() { - this.disableMappings(); - - Overlays.deleteOverlay(this.targetOverlay); - this.targetOverlay = null; - - Overlays.deleteOverlay(this.cancelOverlay); - this.cancelOverlay = null; - - Overlays.deleteOverlay(this.seatOverlay); - this.seatOverlay = null; - - this.deleteOverlayBeams(); - if (this.updateConnected === true) { - Script.update.disconnect(this, this.update); - } - }; - - this.enterTeleportMode = function(hand) { - if (inTeleportMode === true) { - return; - } - if (isDisabled === 'both' || isDisabled === hand) { - return; - } - - inTeleportMode = true; - - if (coolInTimeout !== null) { - Script.clearTimeout(coolInTimeout); - } - - this.state = TELEPORTER_STATES.COOL_IN; - coolInTimeout = Script.setTimeout(function() { - if (_this.state === TELEPORTER_STATES.COOL_IN) { - _this.state = TELEPORTER_STATES.TARGETTING; - } - }, COOL_IN_DURATION); - - this.activeHand = hand; - this.enableMappings(); - Script.update.connect(this, this.update); - this.updateConnected = true; - }; - - this.exitTeleportMode = function(value) { - if (this.updateConnected === true) { - Script.update.disconnect(this, this.update); - } - - this.disableMappings(); - this.deleteOverlayBeams(); - this.hideTargetOverlay(); - this.hideCancelOverlay(); - - this.updateConnected = null; - this.state = TELEPORTER_STATES.IDLE; - inTeleportMode = false; - }; - - this.deleteOverlayBeams = function() { - for (var key in this.overlayLines) { - if (this.overlayLines[key] !== null) { - Overlays.deleteOverlay(this.overlayLines[key]); - this.overlayLines[key] = null; - } - } - }; - - this.update = function() { - if (_this.state === TELEPORTER_STATES.IDLE) { - return; - } - - // Get current hand pose information so that we can get the direction of the teleport beam - var pose = Controller.getPoseValue(handInfo[_this.activeHand].controllerInput); - var handPosition = pose.valid ? Vec3.sum(Vec3.multiplyQbyV(MyAvatar.orientation, pose.translation), MyAvatar.position) : MyAvatar.getHeadPosition(); - var handRotation = pose.valid ? Quat.multiply(MyAvatar.orientation, pose.rotation) : - Quat.multiply(MyAvatar.headOrientation, Quat.angleAxis(-90, { - x: 1, - y: 0, - z: 0 - })); - - var pickRay = { - origin: handPosition, - direction: Quat.getUp(handRotation), - }; - - // We do up to 2 ray picks to find a teleport location. - // There are 2 types of teleport locations we are interested in: - // 1. A visible floor. This can be any entity surface that points within some degree of "up" - // 2. A seat. The seat can be visible or invisible. - // - // * In the first pass we pick against visible and invisible entities so that we can find invisible seats. - // We might hit an invisible entity that is not a seat, so we need to do a second pass. - // * In the second pass we pick against visible entities only. - // - var intersection = Entities.findRayIntersection(pickRay, true, [], [this.targetEntity].concat(ignoredEntities), false, true); - - var teleportLocationType = getTeleportTargetType(intersection); - if (teleportLocationType === TARGET.INVISIBLE) { - intersection = Entities.findRayIntersection(pickRay, true, [], [this.targetEntity].concat(ignoredEntities), true, true); - teleportLocationType = getTeleportTargetType(intersection); - } - - if (teleportLocationType === TARGET.NONE) { - this.hideTargetOverlay(); - this.hideCancelOverlay(); - this.hideSeatOverlay(); - - var farPosition = Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction, 50)); - this.updateLineOverlay(_this.activeHand, pickRay.origin, farPosition, COLORS_TELEPORT_CANNOT_TELEPORT); - } else if (teleportLocationType === TARGET.INVALID || teleportLocationType === TARGET.INVISIBLE) { - this.hideTargetOverlay(); - this.hideSeatOverlay(); - - this.updateLineOverlay(_this.activeHand, pickRay.origin, intersection.intersection, COLORS_TELEPORT_CANCEL); - this.updateDestinationOverlay(this.cancelOverlay, intersection); - } else if (teleportLocationType === TARGET.SURFACE) { - if (this.state === TELEPORTER_STATES.COOL_IN) { - this.hideTargetOverlay(); - this.hideSeatOverlay(); - - this.updateLineOverlay(_this.activeHand, pickRay.origin, intersection.intersection, COLORS_TELEPORT_CANCEL); - this.updateDestinationOverlay(this.cancelOverlay, intersection); - } else { - this.hideCancelOverlay(); - this.hideSeatOverlay(); - - this.updateLineOverlay(_this.activeHand, pickRay.origin, intersection.intersection, - COLORS_TELEPORT_CAN_TELEPORT); - this.updateDestinationOverlay(this.targetOverlay, intersection); - } - } else if (teleportLocationType === TARGET.SEAT) { - this.hideCancelOverlay(); - this.hideTargetOverlay(); - - this.updateLineOverlay(_this.activeHand, pickRay.origin, intersection.intersection, COLORS_TELEPORT_SEAT); - this.updateDestinationOverlay(this.seatOverlay, intersection); - } - - - if (((_this.activeHand === 'left' ? leftPad : rightPad).buttonValue === 0) && inTeleportMode === true) { - // remember the state before we exit teleport mode and set it back to IDLE - var previousState = this.state; - this.exitTeleportMode(); - this.hideCancelOverlay(); - this.hideTargetOverlay(); - this.hideSeatOverlay(); - - if (teleportLocationType === TARGET.NONE || teleportLocationType === TARGET.INVALID || previousState === TELEPORTER_STATES.COOL_IN) { - // Do nothing - } else if (teleportLocationType === TARGET.SEAT) { - Entities.callEntityMethod(intersection.entityID, 'sit'); - } else if (teleportLocationType === TARGET.SURFACE) { - var offset = getAvatarFootOffset(); - intersection.intersection.y += offset; - MyAvatar.goToLocation(intersection.intersection, false, {x: 0, y: 0, z: 0, w: 1}, false); - HMD.centerUI(); - MyAvatar.centerBody(); - } - } - }; - - this.updateLineOverlay = function(hand, closePoint, farPoint, color) { - if (this.overlayLines[hand] === null) { - var lineProperties = { - start: closePoint, - end: farPoint, - color: color, - ignoreRayIntersection: true, - visible: true, - alpha: 1, - solid: true, - drawInFront: true, - glow: 1.0 - }; - - this.overlayLines[hand] = Overlays.addOverlay("line3d", lineProperties); - - } else { - Overlays.editOverlay(this.overlayLines[hand], { - start: closePoint, - end: farPoint, - color: color - }); - } - }; - - this.hideCancelOverlay = function() { - Overlays.editOverlay(this.cancelOverlay, { visible: false }); - }; - - this.hideTargetOverlay = function() { - Overlays.editOverlay(this.targetOverlay, { visible: false }); - }; - - this.hideSeatOverlay = function() { - Overlays.editOverlay(this.seatOverlay, { visible: false }); - }; - - this.updateDestinationOverlay = function(overlayID, intersection) { - var rotation = Quat.lookAt(intersection.intersection, MyAvatar.position, Vec3.UP); - var euler = Quat.safeEulerAngles(rotation); - var position = { - x: intersection.intersection.x, - y: intersection.intersection.y + TARGET_MODEL_DIMENSIONS.y / 2, - z: intersection.intersection.z - }; - - var towardUs = Quat.fromPitchYawRollDegrees(0, euler.y, 0); - - Overlays.editOverlay(overlayID, { - visible: true, - position: position, - rotation: towardUs - }); - - }; -} - -// related to repositioning the avatar after you teleport -var FOOT_JOINT_NAMES = ["RightToe_End", "RightToeBase", "RightFoot"]; -var DEFAULT_ROOT_TO_FOOT_OFFSET = 0.5; -function getAvatarFootOffset() { - - // find a valid foot jointIndex - var footJointIndex = -1; - var i, l = FOOT_JOINT_NAMES.length; - for (i = 0; i < l; i++) { - footJointIndex = MyAvatar.getJointIndex(FOOT_JOINT_NAMES[i]); - if (footJointIndex != -1) { - break; - } - } - if (footJointIndex != -1) { - // default vertical offset from foot to avatar root. - return -MyAvatar.getAbsoluteDefaultJointTranslationInObjectFrame(footJointIndex).y; - } else { - return DEFAULT_ROOT_TO_FOOT_OFFSET * MyAvatar.scale; - } -} - -var leftPad = new ThumbPad('left'); -var rightPad = new ThumbPad('right'); -var leftTrigger = new Trigger('left'); -var rightTrigger = new Trigger('right'); - -var mappingName, teleportMapping; - -var TELEPORT_DELAY = 0; - -function isMoving() { - var LY = Controller.getValue(Controller.Standard.LY); - var LX = Controller.getValue(Controller.Standard.LX); - if (LY !== 0 || LX !== 0) { - return true; - } else { - return false; - } -} - -function parseJSON(json) { - try { - return JSON.parse(json); - } catch (e) { - return undefined; - } -} -// When determininig whether you can teleport to a location, the normal of the -// point that is being intersected with is looked at. If this normal is more -// than MAX_ANGLE_FROM_UP_TO_TELEPORT degrees from <0, 1, 0> (straight up), then -// you can't teleport there. -var MAX_ANGLE_FROM_UP_TO_TELEPORT = 70; -function getTeleportTargetType(intersection) { - if (!intersection.intersects) { - return TARGET.NONE; - } - - var props = Entities.getEntityProperties(intersection.entityID, ['userData', 'visible']); - var data = parseJSON(props.userData); - if (data !== undefined && data.seat !== undefined) { - var avatarUuid = Uuid.fromString(data.seat.user); - if (Uuid.isNull(avatarUuid) || !AvatarList.getAvatar(avatarUuid)) { - return TARGET.SEAT; - } else { - return TARGET.INVALID; - } - } - - if (!props.visible) { - return TARGET.INVISIBLE; - } - - var surfaceNormal = intersection.surfaceNormal; - var adj = Math.sqrt(surfaceNormal.x * surfaceNormal.x + surfaceNormal.z * surfaceNormal.z); - var angleUp = Math.atan2(surfaceNormal.y, adj) * (180 / Math.PI); - - if (angleUp < (90 - MAX_ANGLE_FROM_UP_TO_TELEPORT) || - angleUp > (90 + MAX_ANGLE_FROM_UP_TO_TELEPORT) || - Vec3.distance(MyAvatar.position, intersection.intersection) <= TELEPORT_CANCEL_RANGE) { - return TARGET.INVALID; - } else { - return TARGET.SURFACE; - } -} - -function registerMappings() { - mappingName = 'Hifi-Teleporter-Dev-' + Math.random(); - teleportMapping = Controller.newMapping(mappingName); - teleportMapping.from(Controller.Standard.RT).peek().to(rightTrigger.buttonPress); - teleportMapping.from(Controller.Standard.LT).peek().to(leftTrigger.buttonPress); - - teleportMapping.from(Controller.Standard.RightPrimaryThumb).peek().to(rightPad.buttonPress); - teleportMapping.from(Controller.Standard.LeftPrimaryThumb).peek().to(leftPad.buttonPress); - - teleportMapping.from(Controller.Standard.LeftPrimaryThumb) - .to(function(value) { - if (isDisabled === 'left' || isDisabled === 'both') { - return; - } - if (leftTrigger.down()) { - return; - } - if (isMoving() === true) { - return; - } - teleporter.enterTeleportMode('left'); - return; - }); - teleportMapping.from(Controller.Standard.RightPrimaryThumb) - .to(function(value) { - if (isDisabled === 'right' || isDisabled === 'both') { - return; - } - if (rightTrigger.down()) { - return; - } - if (isMoving() === true) { - return; - } - - teleporter.enterTeleportMode('right'); - return; - }); -} - -registerMappings(); - -var teleporter = new Teleporter(); - -Controller.enableMapping(mappingName); - -function cleanup() { - teleportMapping.disable(); - teleporter.cleanup(); -} -Script.scriptEnding.connect(cleanup); - -var isDisabled = false; -var handleTeleportMessages = function(channel, message, sender) { - if (sender === MyAvatar.sessionUUID) { - if (channel === 'Hifi-Teleport-Disabler') { - if (message === 'both') { - isDisabled = 'both'; - } - if (message === 'left') { - isDisabled = 'left'; - } - if (message === 'right') { - isDisabled = 'right'; - } - if (message === 'none') { - isDisabled = false; - } - } else if (channel === 'Hifi-Teleport-Ignore-Add' && !Uuid.isNull(message) && ignoredEntities.indexOf(message) === -1) { - ignoredEntities.push(message); - } else if (channel === 'Hifi-Teleport-Ignore-Remove' && !Uuid.isNull(message)) { - var removeIndex = ignoredEntities.indexOf(message); - if (removeIndex > -1) { - ignoredEntities.splice(removeIndex, 1); - } - } - } -}; - -Messages.subscribe('Hifi-Teleport-Disabler'); -Messages.subscribe('Hifi-Teleport-Ignore-Add'); -Messages.subscribe('Hifi-Teleport-Ignore-Remove'); -Messages.messageReceived.connect(handleTeleportMessages); - -}()); // END LOCAL_SCOPE From 7084a0607ab7d17fb488dd29d18343a9bcde7d1a Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 17 Jul 2017 14:26:22 -0700 Subject: [PATCH 13/42] fix warnings --- interface/src/raypick/JointRayPick.h | 2 +- interface/src/raypick/LaserPointer.h | 4 +-- interface/src/raypick/LaserPointerManager.h | 2 +- .../raypick/LaserPointerScriptingInterface.h | 2 +- interface/src/raypick/RayPick.h | 8 +++--- interface/src/raypick/RayPickManager.h | 28 +++++++++---------- interface/src/raypick/StaticRayPick.h | 2 +- 7 files changed, 24 insertions(+), 24 deletions(-) diff --git a/interface/src/raypick/JointRayPick.h b/interface/src/raypick/JointRayPick.h index 54d393ab46..99ffb14f01 100644 --- a/interface/src/raypick/JointRayPick.h +++ b/interface/src/raypick/JointRayPick.h @@ -29,4 +29,4 @@ private: }; -#endif hifi_JointRayPick_h \ No newline at end of file +#endif hifi_JointRayPick_h diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index 23f3f2a943..d0e28f59d0 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -53,7 +53,7 @@ public: unsigned int getUID() { return _rayPickUID; } void enable(); void disable(); - const RayPickResult& getPrevRayPickResult() { return RayPickManager::getInstance().getPrevRayPickResult(_rayPickUID); } + const RayPickResult getPrevRayPickResult() { return RayPickManager::getInstance().getPrevRayPickResult(_rayPickUID); } void setRenderState(const QString& state); void disableRenderState(const QString& renderState); @@ -70,4 +70,4 @@ private: unsigned int _rayPickUID; }; -#endif hifi_LaserPointer_h \ No newline at end of file +#endif hifi_LaserPointer_h diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h index 09423bd18a..427568c87c 100644 --- a/interface/src/raypick/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -42,4 +42,4 @@ private: }; -#endif hifi_LaserPointerManager_h \ No newline at end of file +#endif hifi_LaserPointerManager_h diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h index b68a4532db..19298cffd9 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -32,4 +32,4 @@ public slots: }; -#endif hifi_LaserPointerScriptingInterface_h \ No newline at end of file +#endif hifi_LaserPointerScriptingInterface_h diff --git a/interface/src/raypick/RayPick.h b/interface/src/raypick/RayPick.h index 855cd53ba8..72fea450aa 100644 --- a/interface/src/raypick/RayPick.h +++ b/interface/src/raypick/RayPick.h @@ -24,9 +24,9 @@ public: void enable() { _enabled = true; } void disable() { _enabled = false; } - const uint16_t getFilter() { return _filter; } - const float getMaxDistance() { return _maxDistance; } - const bool isEnabled() { return _enabled; } + const uint16_t& getFilter() { return _filter; } + const float& getMaxDistance() { return _maxDistance; } + const bool& isEnabled() { return _enabled; } const RayPickResult& getPrevRayPickResult() { return _prevResult; } void setRayPickResult(const RayPickResult& rayPickResult) { _prevResult = rayPickResult; } @@ -39,4 +39,4 @@ private: }; -#endif hifi_RayPick_h \ No newline at end of file +#endif hifi_RayPick_h diff --git a/interface/src/raypick/RayPickManager.h b/interface/src/raypick/RayPickManager.h index d798e8a742..80f28572b1 100644 --- a/interface/src/raypick/RayPickManager.h +++ b/interface/src/raypick/RayPickManager.h @@ -70,20 +70,20 @@ private: QHash> _rayPicks; unsigned int _nextUID { 1 }; // 0 is invalid - const unsigned int PICK_NOTHING() { return RayPickMask::PICK_NOTHING; } - const unsigned int PICK_ENTITIES() { return RayPickMask::PICK_ENTITIES; } - const unsigned int PICK_OVERLAYS() { return RayPickMask::PICK_OVERLAYS; } - const unsigned int PICK_AVATARS() { return RayPickMask::PICK_AVATARS; } - const unsigned int PICK_HUD() { return RayPickMask::PICK_HUD; } - const unsigned int PICK_BOUNDING_BOX() { return RayPickMask::PICK_BOUNDING_BOX; } - const unsigned int PICK_INCLUDE_INVISIBLE() { return RayPickMask::PICK_INCLUDE_INVISIBLE; } - const unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return RayPickMask::PICK_INCLUDE_NONCOLLIDABLE; } - const unsigned int PICK_ALL_INTERSECTIONS() { return RayPickMask::PICK_ALL_INTERSECTIONS; } - const unsigned int INTERSECTED_NONE() { return IntersectionType::NONE; } - const unsigned int INTERSECTED_ENTITY() { return IntersectionType::ENTITY; } - const unsigned int INTERSECTED_OVERLAY() { return IntersectionType::OVERLAY; } - const unsigned int INTERSECTED_AVATAR() { return IntersectionType::AVATAR; } - const unsigned int INTERSECTED_HUD() { return IntersectionType::HUD; } + unsigned int PICK_NOTHING() { return RayPickMask::PICK_NOTHING; } + unsigned int PICK_ENTITIES() { return RayPickMask::PICK_ENTITIES; } + unsigned int PICK_OVERLAYS() { return RayPickMask::PICK_OVERLAYS; } + unsigned int PICK_AVATARS() { return RayPickMask::PICK_AVATARS; } + unsigned int PICK_HUD() { return RayPickMask::PICK_HUD; } + unsigned int PICK_BOUNDING_BOX() { return RayPickMask::PICK_BOUNDING_BOX; } + unsigned int PICK_INCLUDE_INVISIBLE() { return RayPickMask::PICK_INCLUDE_INVISIBLE; } + unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return RayPickMask::PICK_INCLUDE_NONCOLLIDABLE; } + unsigned int PICK_ALL_INTERSECTIONS() { return RayPickMask::PICK_ALL_INTERSECTIONS; } + unsigned int INTERSECTED_NONE() { return IntersectionType::NONE; } + unsigned int INTERSECTED_ENTITY() { return IntersectionType::ENTITY; } + unsigned int INTERSECTED_OVERLAY() { return IntersectionType::OVERLAY; } + unsigned int INTERSECTED_AVATAR() { return IntersectionType::AVATAR; } + unsigned int INTERSECTED_HUD() { return IntersectionType::HUD; } }; diff --git a/interface/src/raypick/StaticRayPick.h b/interface/src/raypick/StaticRayPick.h index f4f2b769e3..c2e418164e 100644 --- a/interface/src/raypick/StaticRayPick.h +++ b/interface/src/raypick/StaticRayPick.h @@ -25,4 +25,4 @@ private: }; -#endif hifi_StaticRayPick_h \ No newline at end of file +#endif hifi_StaticRayPick_h From 0c8c6ff5d677abe7b9ba5792920a9c286ec3702d Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 17 Jul 2017 15:05:31 -0700 Subject: [PATCH 14/42] silly me --- interface/src/raypick/JointRayPick.h | 2 +- interface/src/raypick/LaserPointer.h | 2 +- interface/src/raypick/LaserPointerManager.h | 2 +- interface/src/raypick/LaserPointerScriptingInterface.h | 2 +- interface/src/raypick/RayPick.h | 2 +- interface/src/raypick/RayPickManager.h | 2 +- interface/src/raypick/StaticRayPick.h | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/interface/src/raypick/JointRayPick.h b/interface/src/raypick/JointRayPick.h index 99ffb14f01..8b57583238 100644 --- a/interface/src/raypick/JointRayPick.h +++ b/interface/src/raypick/JointRayPick.h @@ -29,4 +29,4 @@ private: }; -#endif hifi_JointRayPick_h +#endif // hifi_JointRayPick_h diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index d0e28f59d0..075ec5e7f7 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -70,4 +70,4 @@ private: unsigned int _rayPickUID; }; -#endif hifi_LaserPointer_h +#endif // hifi_LaserPointer_h diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h index 427568c87c..f5a8484054 100644 --- a/interface/src/raypick/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -42,4 +42,4 @@ private: }; -#endif hifi_LaserPointerManager_h +#endif // hifi_LaserPointerManager_h diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h index 19298cffd9..b16daedda6 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -32,4 +32,4 @@ public slots: }; -#endif hifi_LaserPointerScriptingInterface_h +#endif // hifi_LaserPointerScriptingInterface_h diff --git a/interface/src/raypick/RayPick.h b/interface/src/raypick/RayPick.h index 72fea450aa..26d09ab8a8 100644 --- a/interface/src/raypick/RayPick.h +++ b/interface/src/raypick/RayPick.h @@ -39,4 +39,4 @@ private: }; -#endif hifi_RayPick_h +#endif // hifi_RayPick_h diff --git a/interface/src/raypick/RayPickManager.h b/interface/src/raypick/RayPickManager.h index 80f28572b1..12d12de30d 100644 --- a/interface/src/raypick/RayPickManager.h +++ b/interface/src/raypick/RayPickManager.h @@ -87,4 +87,4 @@ private: }; -#endif hifi_RayPickManager_h \ No newline at end of file +#endif // hifi_RayPickManager_h \ No newline at end of file diff --git a/interface/src/raypick/StaticRayPick.h b/interface/src/raypick/StaticRayPick.h index c2e418164e..6e2fe89e8c 100644 --- a/interface/src/raypick/StaticRayPick.h +++ b/interface/src/raypick/StaticRayPick.h @@ -25,4 +25,4 @@ private: }; -#endif hifi_StaticRayPick_h +#endif // hifi_StaticRayPick_h From 298faa9f0fe0a5f3bc47bacda6c681d129aaf8bf Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 18 Jul 2017 12:13:16 -0700 Subject: [PATCH 15/42] threading pass --- interface/src/raypick/JointRayPick.cpp | 2 +- interface/src/raypick/JointRayPick.h | 2 +- interface/src/raypick/RayPick.h | 2 +- interface/src/raypick/RayPickManager.cpp | 44 ++++++++++++++++++------ interface/src/raypick/RayPickManager.h | 8 +++++ interface/src/raypick/StaticRayPick.cpp | 2 +- interface/src/raypick/StaticRayPick.h | 2 +- 7 files changed, 47 insertions(+), 15 deletions(-) diff --git a/interface/src/raypick/JointRayPick.cpp b/interface/src/raypick/JointRayPick.cpp index 9309f0d826..3281d307d9 100644 --- a/interface/src/raypick/JointRayPick.cpp +++ b/interface/src/raypick/JointRayPick.cpp @@ -21,7 +21,7 @@ JointRayPick::JointRayPick(const QString& jointName, const glm::vec3& posOffset, { } -const PickRay JointRayPick::getPickRay(bool& valid) { +const PickRay JointRayPick::getPickRay(bool& valid) const { auto myAvatar = DependencyManager::get()->getMyAvatar(); int jointIndex = myAvatar->getJointIndex(_jointName); if (jointIndex != -1) { diff --git a/interface/src/raypick/JointRayPick.h b/interface/src/raypick/JointRayPick.h index 8b57583238..0631372bdb 100644 --- a/interface/src/raypick/JointRayPick.h +++ b/interface/src/raypick/JointRayPick.h @@ -20,7 +20,7 @@ class JointRayPick : public RayPick { public: JointRayPick(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance = 0.0f, const bool enabled = false); - const PickRay getPickRay(bool& valid) override; + const PickRay getPickRay(bool& valid) const override; private: QString _jointName; diff --git a/interface/src/raypick/RayPick.h b/interface/src/raypick/RayPick.h index 26d09ab8a8..e149611210 100644 --- a/interface/src/raypick/RayPick.h +++ b/interface/src/raypick/RayPick.h @@ -19,7 +19,7 @@ class RayPick { public: RayPick(const uint16_t filter, const float maxDistance, const bool enabled); - virtual const PickRay getPickRay(bool& valid) = 0; + virtual const PickRay getPickRay(bool& valid) const = 0; void enable() { _enabled = true; } void disable() { _enabled = false; } diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp index 5f1c5add7b..8ca503114c 100644 --- a/interface/src/raypick/RayPickManager.cpp +++ b/interface/src/raypick/RayPickManager.cpp @@ -49,7 +49,8 @@ void RayPickManager::cacheResult(const bool intersects, const RayPickResult& res void RayPickManager::update() { QHash, QHash> results; - for (auto& rayPick : _rayPicks) { + for (auto& uid : _rayPicks.keys()) { + std::shared_ptr rayPick = _rayPicks[uid]; if (!rayPick->isEnabled() || rayPick->getFilter() == RayPickMask::PICK_NOTHING || rayPick->getMaxDistance() < 0.0f) { continue; } @@ -145,40 +146,63 @@ void RayPickManager::update() { } } - if (rayPick->getMaxDistance() == 0.0f || (rayPick->getMaxDistance() > 0.0f && res.distance < rayPick->getMaxDistance())) { + QWriteLocker lock(_rayPickLocks[uid].get()); + if (rayPick->getMaxDistance() == 0.0f || (rayPick->getMaxDistance() > 0.0f && res.distance < rayPick->getMaxDistance())) { rayPick->setRayPickResult(res); } else { rayPick->setRayPickResult(RayPickResult()); } } + + QWriteLocker containsLock(&_containsLock); + { + QWriteLocker lock(&_addLock); + while (!_rayPicksToAdd.isEmpty()) { + QPair> rayPickToAdd = _rayPicksToAdd.dequeue(); + _rayPicks[rayPickToAdd.first] = rayPickToAdd.second; + _rayPickLocks[rayPickToAdd.first] = std::make_shared(); + } + } + + { + QWriteLocker lock(&_removeLock); + while (!_rayPicksToRemove.isEmpty()) { + unsigned int uid = _rayPicksToRemove.dequeue(); + _rayPicks.remove(uid); + _rayPickLocks.remove(uid); + } + } } unsigned int RayPickManager::addRayPick(std::shared_ptr rayPick) { - // TODO: - // use lock and defer adding to prevent issues - _rayPicks[_nextUID] = rayPick; + QWriteLocker lock(&_addLock); + _rayPicksToAdd.enqueue(QPair>(_nextUID, rayPick)); return _nextUID++; } void RayPickManager::removeRayPick(const unsigned int uid) { - // TODO: - // use lock and defer removing to prevent issues - _rayPicks.remove(uid); + QWriteLocker lock(&_removeLock); + _rayPicksToRemove.enqueue(uid); } void RayPickManager::enableRayPick(const unsigned int uid) { + QReadLocker containsLock(&_containsLock); if (_rayPicks.contains(uid)) { + QWriteLocker rayPickLock(_rayPickLocks[uid].get()); _rayPicks[uid]->enable(); } } void RayPickManager::disableRayPick(const unsigned int uid) { + QReadLocker containsLock(&_containsLock); if (_rayPicks.contains(uid)) { + QWriteLocker rayPickLock(_rayPickLocks[uid].get()); _rayPicks[uid]->disable(); } } const PickRay RayPickManager::getPickRay(const unsigned int uid) { + QReadLocker containsLock(&_containsLock); if (_rayPicks.contains(uid)) { bool valid; PickRay pickRay = _rayPicks[uid]->getPickRay(valid); @@ -190,9 +214,9 @@ const PickRay RayPickManager::getPickRay(const unsigned int uid) { } const RayPickResult RayPickManager::getPrevRayPickResult(const unsigned int uid) { - // TODO: - // does this need to lock the individual ray? what happens with concurrent set/get? + QReadLocker containsLock(&_containsLock); if (_rayPicks.contains(uid)) { + QReadLocker lock(_rayPickLocks[uid].get()); return _rayPicks[uid]->getPrevRayPickResult(); } return RayPickResult(); diff --git a/interface/src/raypick/RayPickManager.h b/interface/src/raypick/RayPickManager.h index 12d12de30d..ad4fb3f286 100644 --- a/interface/src/raypick/RayPickManager.h +++ b/interface/src/raypick/RayPickManager.h @@ -14,6 +14,8 @@ #include "RegisteredMetaTypes.h" #include +#include +#include #include #include @@ -68,7 +70,13 @@ public: private: QHash> _rayPicks; + QHash> _rayPickLocks; unsigned int _nextUID { 1 }; // 0 is invalid + QReadWriteLock _addLock; + QQueue>> _rayPicksToAdd; + QReadWriteLock _removeLock; + QQueue _rayPicksToRemove; + QReadWriteLock _containsLock; unsigned int PICK_NOTHING() { return RayPickMask::PICK_NOTHING; } unsigned int PICK_ENTITIES() { return RayPickMask::PICK_ENTITIES; } diff --git a/interface/src/raypick/StaticRayPick.cpp b/interface/src/raypick/StaticRayPick.cpp index 9edd992a17..43088150ad 100644 --- a/interface/src/raypick/StaticRayPick.cpp +++ b/interface/src/raypick/StaticRayPick.cpp @@ -16,7 +16,7 @@ StaticRayPick::StaticRayPick(const glm::vec3& position, const glm::vec3& directi { } -const PickRay StaticRayPick::getPickRay(bool& valid) { +const PickRay StaticRayPick::getPickRay(bool& valid) const { valid = true; return _pickRay; } \ No newline at end of file diff --git a/interface/src/raypick/StaticRayPick.h b/interface/src/raypick/StaticRayPick.h index 6e2fe89e8c..05ff4ef397 100644 --- a/interface/src/raypick/StaticRayPick.h +++ b/interface/src/raypick/StaticRayPick.h @@ -18,7 +18,7 @@ class StaticRayPick : public RayPick { public: StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance = 0.0f, const bool enabled = false); - const PickRay getPickRay(bool& valid) override; + const PickRay getPickRay(bool& valid) const override; private: PickRay _pickRay; From 55a025b827ab5184e3d1311bf225f1004d0f25ee Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 18 Jul 2017 12:43:34 -0700 Subject: [PATCH 16/42] initial code review --- interface/src/Application.cpp | 12 ++++--- interface/src/raypick/JointRayPick.cpp | 3 +- interface/src/raypick/LaserPointer.cpp | 14 ++++---- interface/src/raypick/LaserPointer.h | 4 ++- interface/src/raypick/LaserPointerManager.cpp | 5 --- interface/src/raypick/LaserPointerManager.h | 6 ++-- .../LaserPointerScriptingInterface.cpp | 9 ++--- .../raypick/LaserPointerScriptingInterface.h | 17 +++++---- interface/src/raypick/RayPickManager.cpp | 13 ++----- interface/src/raypick/RayPickManager.h | 35 ++++++++++--------- 10 files changed, 55 insertions(+), 63 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 44f15ff16e..69835caff0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -591,6 +591,10 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(); + DependencyManager::set(); + DependencyManager::set(); + return previousSessionCrashed; } @@ -4922,12 +4926,12 @@ void Application::update(float deltaTime) { { PROFILE_RANGE(app, "RayPick"); - RayPickManager::getInstance().update(); + DependencyManager::get()->update(); } { PROFILE_RANGE(app, "LaserPointerManager"); - LaserPointerManager::getInstance().update(); + DependencyManager::get()->update(); } // Update _viewFrustum with latest camera and view frustum data... @@ -5775,7 +5779,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("AudioScope", DependencyManager::get().data()); scriptEngine->registerGlobalObject("AvatarBookmarks", DependencyManager::get().data()); scriptEngine->registerGlobalObject("LocationBookmarks", DependencyManager::get().data()); - scriptEngine->registerGlobalObject("LaserPointers", LaserPointerScriptingInterface::getInstance()); + scriptEngine->registerGlobalObject("LaserPointers", DependencyManager::get().data()); // Caches scriptEngine->registerGlobalObject("AnimationCache", DependencyManager::get().data()); @@ -5828,7 +5832,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("EntityScriptServerLog", entityScriptServerLog.data()); scriptEngine->registerGlobalObject("AvatarInputs", AvatarInputs::getInstance()); - scriptEngine->registerGlobalObject("RayPick", &RayPickManager::getInstance()); + scriptEngine->registerGlobalObject("RayPick", DependencyManager::get().data()); qScriptRegisterMetaType(scriptEngine, OverlayIDtoScriptValue, OverlayIDfromScriptValue); diff --git a/interface/src/raypick/JointRayPick.cpp b/interface/src/raypick/JointRayPick.cpp index 3281d307d9..f6be58437f 100644 --- a/interface/src/raypick/JointRayPick.cpp +++ b/interface/src/raypick/JointRayPick.cpp @@ -24,7 +24,8 @@ JointRayPick::JointRayPick(const QString& jointName, const glm::vec3& posOffset, const PickRay JointRayPick::getPickRay(bool& valid) const { auto myAvatar = DependencyManager::get()->getMyAvatar(); int jointIndex = myAvatar->getJointIndex(_jointName); - if (jointIndex != -1) { + const int INVALID_JOINT = -1; + if (jointIndex != INVALID_JOINT) { glm::vec3 jointPos = myAvatar->getAbsoluteJointTranslationInObjectFrame(jointIndex); glm::quat jointRot = myAvatar->getAbsoluteJointRotationInObjectFrame(jointIndex); glm::vec3 avatarPos = myAvatar->getPosition(); diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index ed5fbd2ece..930e72a6fe 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -23,7 +23,7 @@ LaserPointer::LaserPointer(const QString& jointName, const glm::vec3& posOffset, _faceAvatar(faceAvatar), _centerEndY(centerEndY) { - _rayPickUID = RayPickManager::getInstance().addRayPick(std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled)); + _rayPickUID = DependencyManager::get()->addRayPick(std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled)); for (auto& state : _renderStates.keys()) { if (!enabled || state != _currentRenderState) { @@ -39,7 +39,7 @@ LaserPointer::LaserPointer(const glm::vec3& position, const glm::vec3& direction _faceAvatar(faceAvatar), _centerEndY(centerEndY) { - _rayPickUID = RayPickManager::getInstance().addRayPick(std::make_shared(position, direction, filter, maxDistance, enabled)); + _rayPickUID = DependencyManager::get()->addRayPick(std::make_shared(position, direction, filter, maxDistance, enabled)); for (auto& state : _renderStates.keys()) { if (!enabled || state != _currentRenderState) { @@ -49,7 +49,7 @@ LaserPointer::LaserPointer(const glm::vec3& position, const glm::vec3& direction } LaserPointer::~LaserPointer() { - RayPickManager::getInstance().removeRayPick(_rayPickUID); + DependencyManager::get()->removeRayPick(_rayPickUID); for (RenderState& renderState : _renderStates) { if (!renderState.getStartID().isNull()) { qApp->getOverlays().deleteOverlay(renderState.getStartID()); @@ -64,12 +64,12 @@ LaserPointer::~LaserPointer() { } void LaserPointer::enable() { - RayPickManager::getInstance().enableRayPick(_rayPickUID); + DependencyManager::get()->enableRayPick(_rayPickUID); _renderingEnabled = true; } void LaserPointer::disable() { - RayPickManager::getInstance().disableRayPick(_rayPickUID); + DependencyManager::get()->disableRayPick(_rayPickUID); _renderingEnabled = false; if (!_currentRenderState.isEmpty() && _renderStates.contains(_currentRenderState)) { disableRenderState(_currentRenderState); @@ -105,9 +105,9 @@ void LaserPointer::disableRenderState(const QString& renderState) { } void LaserPointer::update() { - RayPickResult prevRayPickResult = RayPickManager::getInstance().getPrevRayPickResult(_rayPickUID); + RayPickResult prevRayPickResult = DependencyManager::get()->getPrevRayPickResult(_rayPickUID); if (_renderingEnabled && !_currentRenderState.isEmpty() && _renderStates.contains(_currentRenderState) && prevRayPickResult.type != IntersectionType::NONE) { - PickRay pickRay = RayPickManager::getInstance().getPickRay(_rayPickUID); + PickRay pickRay = DependencyManager::get()->getPickRay(_rayPickUID); if (!_renderStates[_currentRenderState].getStartID().isNull()) { QVariantMap startProps; startProps.insert("position", vec3toVariant(pickRay.origin)); diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index 075ec5e7f7..ba9a876556 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -14,6 +14,8 @@ #include #include "glm/glm.hpp" #include "ui/overlays/Overlay.h" + +#include #include "RayPickManager.h" class RayPickResult; @@ -53,7 +55,7 @@ public: unsigned int getUID() { return _rayPickUID; } void enable(); void disable(); - const RayPickResult getPrevRayPickResult() { return RayPickManager::getInstance().getPrevRayPickResult(_rayPickUID); } + const RayPickResult getPrevRayPickResult() { return DependencyManager::get()->getPrevRayPickResult(_rayPickUID); } void setRenderState(const QString& state); void disableRenderState(const QString& renderState); diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp index e4c9e18127..b8086c2f89 100644 --- a/interface/src/raypick/LaserPointerManager.cpp +++ b/interface/src/raypick/LaserPointerManager.cpp @@ -12,11 +12,6 @@ #include "LaserPointer.h" #include "RayPick.h" -LaserPointerManager& LaserPointerManager::getInstance() { - static LaserPointerManager instance; - return instance; -} - unsigned int LaserPointerManager::createLaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool enabled) { std::shared_ptr laserPointer = std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, renderStates, faceAvatar, centerEndY, enabled); diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h index f5a8484054..fc043a9685 100644 --- a/interface/src/raypick/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -17,14 +17,14 @@ #include #include "LaserPointer.h" +#include "DependencyManager.h" class RayPickResult; -class LaserPointerManager { +class LaserPointerManager : public Dependency { + SINGLETON_DEPENDENCY public: - static LaserPointerManager& getInstance(); - unsigned int createLaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool enabled); unsigned int createLaserPointer(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance, diff --git a/interface/src/raypick/LaserPointerScriptingInterface.cpp b/interface/src/raypick/LaserPointerScriptingInterface.cpp index cf0289c44b..a53b3dbf01 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.cpp +++ b/interface/src/raypick/LaserPointerScriptingInterface.cpp @@ -17,11 +17,6 @@ #include "Application.h" -LaserPointerScriptingInterface* LaserPointerScriptingInterface::getInstance() { - static LaserPointerScriptingInterface instance; - return &instance; -} - uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& properties) { QVariantMap propertyMap = properties.toMap(); @@ -104,7 +99,7 @@ uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& prop dirOffset = vec3FromVariant(propertyMap["dirOffset"]); } - return LaserPointerManager::getInstance().createLaserPointer(jointName, posOffset, dirOffset, filter, maxDistance, renderStates, faceAvatar, centerEndY, enabled); + return DependencyManager::get()->createLaserPointer(jointName, posOffset, dirOffset, filter, maxDistance, renderStates, faceAvatar, centerEndY, enabled); } else if (propertyMap["position"].isValid()) { glm::vec3 position = vec3FromVariant(propertyMap["position"]); @@ -113,7 +108,7 @@ uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& prop direction = vec3FromVariant(propertyMap["direction"]); } - return LaserPointerManager::getInstance().createLaserPointer(position, direction, filter, maxDistance, renderStates, faceAvatar, centerEndY, enabled); + return DependencyManager::get()->createLaserPointer(position, direction, filter, maxDistance, renderStates, faceAvatar, centerEndY, enabled); } return 0; diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h index b16daedda6..708c378abb 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -15,20 +15,19 @@ #include "LaserPointerManager.h" #include "RegisteredMetaTypes.h" +#include "DependencyManager.h" -class LaserPointerScriptingInterface : public QObject { +class LaserPointerScriptingInterface : public QObject, public Dependency { Q_OBJECT - -public: - static LaserPointerScriptingInterface* getInstance(); + SINGLETON_DEPENDENCY public slots: Q_INVOKABLE unsigned int createLaserPointer(const QVariant& properties); - Q_INVOKABLE void enableLaserPointer(unsigned int uid) { LaserPointerManager::getInstance().enableLaserPointer(uid); } - Q_INVOKABLE void disableLaserPointer(unsigned int uid) { LaserPointerManager::getInstance().disableLaserPointer(uid); } - Q_INVOKABLE void removeLaserPointer(unsigned int uid) { LaserPointerManager::getInstance().removeLaserPointer(uid); } - Q_INVOKABLE void setRenderState(unsigned int uid, const QString& renderState) { LaserPointerManager::getInstance().setRenderState(uid, renderState); } - Q_INVOKABLE RayPickResult getPrevRayPickResult(unsigned int uid) { return LaserPointerManager::getInstance().getPrevRayPickResult(uid); } + Q_INVOKABLE void enableLaserPointer(unsigned int uid) { DependencyManager::get()->enableLaserPointer(uid); } + Q_INVOKABLE void disableLaserPointer(unsigned int uid) { DependencyManager::get()->disableLaserPointer(uid); } + Q_INVOKABLE void removeLaserPointer(unsigned int uid) { DependencyManager::get()->removeLaserPointer(uid); } + Q_INVOKABLE void setRenderState(unsigned int uid, const QString& renderState) { DependencyManager::get()->setRenderState(uid, renderState); } + Q_INVOKABLE RayPickResult getPrevRayPickResult(unsigned int uid) { return DependencyManager::get()->getPrevRayPickResult(uid); } }; diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp index 8ca503114c..ff4fca3f50 100644 --- a/interface/src/raypick/RayPickManager.cpp +++ b/interface/src/raypick/RayPickManager.cpp @@ -19,13 +19,7 @@ #include "scripting/HMDScriptingInterface.h" #include "DependencyManager.h" -RayPickManager& RayPickManager::getInstance() { - static RayPickManager instance; - return instance; -} - -// Returns true if this ray exists in the cache, and if it does, update res if the cached result is closer -bool RayPickManager::checkAndCompareCachedResults(QPair& ray, QHash, QHash>& cache, RayPickResult& res, unsigned int mask) { +bool RayPickManager::checkAndCompareCachedResults(QPair& ray, RayPickCache& cache, RayPickResult& res, unsigned int mask) { if (cache.contains(ray) && cache[ray].contains(mask)) { if (cache[ray][mask].distance < res.distance) { res = cache[ray][mask]; @@ -35,8 +29,7 @@ bool RayPickManager::checkAndCompareCachedResults(QPair& r return false; } -void RayPickManager::cacheResult(const bool intersects, const RayPickResult& resTemp, unsigned int mask, RayPickResult& res, - QPair& ray, QHash, QHash>& cache) { +void RayPickManager::cacheResult(const bool intersects, const RayPickResult& resTemp, unsigned int mask, RayPickResult& res, QPair& ray, RayPickCache& cache) { if (intersects) { cache[ray][mask] = resTemp; if (resTemp.distance < res.distance) { @@ -48,7 +41,7 @@ void RayPickManager::cacheResult(const bool intersects, const RayPickResult& res } void RayPickManager::update() { - QHash, QHash> results; + RayPickCache results; for (auto& uid : _rayPicks.keys()) { std::shared_ptr rayPick = _rayPicks[uid]; if (!rayPick->isEnabled() || rayPick->getFilter() == RayPickMask::PICK_NOTHING || rayPick->getMaxDistance() < 0.0f) { diff --git a/interface/src/raypick/RayPickManager.h b/interface/src/raypick/RayPickManager.h index ad4fb3f286..7ecb028d29 100644 --- a/interface/src/raypick/RayPickManager.h +++ b/interface/src/raypick/RayPickManager.h @@ -11,33 +11,34 @@ #ifndef hifi_RayPickManager_h #define hifi_RayPickManager_h -#include "RegisteredMetaTypes.h" - #include #include #include #include #include +#include "RegisteredMetaTypes.h" +#include "DependencyManager.h" + class RayPick; class RayPickResult; enum RayPickMask { PICK_NOTHING = 0, - PICK_ENTITIES = 1, - PICK_OVERLAYS = 2, - PICK_AVATARS = 4, - PICK_HUD = 8, + PICK_ENTITIES = 1 << 0, + PICK_OVERLAYS = 1 << 1, + PICK_AVATARS = 1 << 2, + PICK_HUD = 1 << 3, - PICK_BOUNDING_BOX = 16, // if not set, picks again physics mesh (can't pick against graphics mesh, yet) + PICK_BOUNDING_BOX = 1 << 4, // if not set, picks again physics mesh (can't pick against graphics mesh, yet) - PICK_INCLUDE_INVISIBLE = 32, // if not set, will not intersect invisible elements, otherwise, intersects both visible and invisible elements - PICK_INCLUDE_NONCOLLIDABLE = 64, // if not set, will not intersect noncollidable elements, otherwise, intersects both collidable and noncollidable elements + PICK_INCLUDE_INVISIBLE = 1 << 5, // if not set, will not intersect invisible elements, otherwise, intersects both visible and invisible elements + PICK_INCLUDE_NONCOLLIDABLE = 1 << 6, // if not set, will not intersect noncollidable elements, otherwise, intersects both collidable and noncollidable elements - PICK_ALL_INTERSECTIONS = 128 // if not set, returns closest intersection, otherwise, returns list of all intersections + PICK_ALL_INTERSECTIONS = 1 << 7 // if not set, returns closest intersection, otherwise, returns list of all intersections }; -class RayPickManager : public QObject { +class RayPickManager : public QObject, public Dependency { Q_OBJECT Q_PROPERTY(unsigned int PICK_NOTHING READ PICK_NOTHING CONSTANT) Q_PROPERTY(unsigned int PICK_ENTITIES READ PICK_ENTITIES CONSTANT) @@ -53,14 +54,10 @@ class RayPickManager : public QObject { Q_PROPERTY(unsigned int INTERSECTED_OVERLAY READ INTERSECTED_OVERLAY CONSTANT) Q_PROPERTY(unsigned int INTERSECTED_AVATAR READ INTERSECTED_AVATAR CONSTANT) Q_PROPERTY(unsigned int INTERSECTED_HUD READ INTERSECTED_HUD CONSTANT) + SINGLETON_DEPENDENCY public: - static RayPickManager& getInstance(); - void update(); - bool checkAndCompareCachedResults(QPair& ray, QHash, QHash>& cache, RayPickResult& res, unsigned int mask); - void cacheResult(const bool intersects, const RayPickResult& resTemp, unsigned int mask, RayPickResult& res, - QPair& ray, QHash, QHash>& cache); unsigned int addRayPick(std::shared_ptr rayPick); void removeRayPick(const unsigned int uid); void enableRayPick(const unsigned int uid); @@ -78,6 +75,12 @@ private: QQueue _rayPicksToRemove; QReadWriteLock _containsLock; + typedef QHash, QHash> RayPickCache; + + // Returns true if this ray exists in the cache, and if it does, update res if the cached result is closer + bool checkAndCompareCachedResults(QPair& ray, RayPickCache& cache, RayPickResult& res, unsigned int mask); + void cacheResult(const bool intersects, const RayPickResult& resTemp, unsigned int mask, RayPickResult& res, QPair& ray, RayPickCache& cache); + unsigned int PICK_NOTHING() { return RayPickMask::PICK_NOTHING; } unsigned int PICK_ENTITIES() { return RayPickMask::PICK_ENTITIES; } unsigned int PICK_OVERLAYS() { return RayPickMask::PICK_OVERLAYS; } From c6b3f69db0af9033d0aaad93bb871ef66c5c0792 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 19 Jul 2017 11:51:31 -0700 Subject: [PATCH 17/42] teleport third eye laser on invalid hand pose --- interface/src/raypick/JointRayPick.cpp | 11 +-- scripts/system/controllers/teleport.js | 99 ++++++++++++++++++++------ 2 files changed, 85 insertions(+), 25 deletions(-) diff --git a/interface/src/raypick/JointRayPick.cpp b/interface/src/raypick/JointRayPick.cpp index f6be58437f..6803700e4b 100644 --- a/interface/src/raypick/JointRayPick.cpp +++ b/interface/src/raypick/JointRayPick.cpp @@ -24,15 +24,16 @@ JointRayPick::JointRayPick(const QString& jointName, const glm::vec3& posOffset, const PickRay JointRayPick::getPickRay(bool& valid) const { auto myAvatar = DependencyManager::get()->getMyAvatar(); int jointIndex = myAvatar->getJointIndex(_jointName); + bool useAvatarHead = _jointName == "Avatar"; const int INVALID_JOINT = -1; - if (jointIndex != INVALID_JOINT) { - glm::vec3 jointPos = myAvatar->getAbsoluteJointTranslationInObjectFrame(jointIndex); - glm::quat jointRot = myAvatar->getAbsoluteJointRotationInObjectFrame(jointIndex); + if (jointIndex != INVALID_JOINT || useAvatarHead) { + glm::vec3 jointPos = useAvatarHead ? myAvatar->getHeadPosition() : myAvatar->getAbsoluteJointTranslationInObjectFrame(jointIndex); + glm::quat jointRot = useAvatarHead ? myAvatar->getHeadOrientation() : myAvatar->getAbsoluteJointRotationInObjectFrame(jointIndex); glm::vec3 avatarPos = myAvatar->getPosition(); glm::quat avatarRot = myAvatar->getOrientation(); - glm::vec3 pos = avatarPos + (avatarRot * jointPos); - glm::quat rot = avatarRot * jointRot; + glm::vec3 pos = useAvatarHead ? jointPos : avatarPos + (avatarRot * jointPos); + glm::quat rot = useAvatarHead ? jointRot * glm::angleAxis(-PI / 2.0f, Vectors::RIGHT) : avatarRot * jointRot; // Apply offset pos = pos + (rot * _posOffset); diff --git a/scripts/system/controllers/teleport.js b/scripts/system/controllers/teleport.js index b72828ea6b..eaeb7767ac 100644 --- a/scripts/system/controllers/teleport.js +++ b/scripts/system/controllers/teleport.js @@ -46,6 +46,15 @@ var COLORS_TELEPORT_CANCEL = { var TELEPORT_CANCEL_RANGE = 1; var COOL_IN_DURATION = 500; +var handInfo = { + right: { + controllerInput: Controller.Standard.RightHand + }, + left: { + controllerInput: Controller.Standard.LeftHand + } +}; + var cancelPath = { type: "line3d", color: COLORS_TELEPORT_CANCEL, @@ -172,6 +181,21 @@ function Teleporter() { renderStates: teleportRenderStates }); + this.teleportRayHeadVisible = LaserPointers.createLaserPointer({ + joint: "Avatar", + filter: RayPick.PICK_ENTITIES, + faceAvatar: true, + centerEndY: false, + renderStates: teleportRenderStates + }); + this.teleportRayHeadInvisible = LaserPointers.createLaserPointer({ + joint: "Avatar", + filter: RayPick.PICK_ENTITIES | RayPick.PICK_INCLUDE_INVISIBLE, + faceAvatar: true, + centerEndY: false, + renderStates: teleportRenderStates + }); + this.updateConnected = null; this.activeHand = null; @@ -193,6 +217,8 @@ function Teleporter() { LaserPointers.removeLaserPointer(this.teleportRayLeftInvisible); LaserPointers.removeLaserPointer(this.teleportRayRightVisible); LaserPointers.removeLaserPointer(this.teleportRayRightInvisible); + LaserPointers.removeLaserPointer(this.teleportRayHeadVisible); + LaserPointers.removeLaserPointer(this.teleportRayHeadInvisible); if (this.updateConnected === true) { Script.update.disconnect(this, this.update); @@ -213,14 +239,6 @@ function Teleporter() { Script.clearTimeout(coolInTimeout); } - if (hand === 'right') { - LaserPointers.enableLaserPointer(_this.teleportRayRightVisible); - LaserPointers.enableLaserPointer(_this.teleportRayRightInvisible); - } else { - LaserPointers.enableLaserPointer(_this.teleportRayLeftVisible); - LaserPointers.enableLaserPointer(_this.teleportRayLeftInvisible); - } - this.state = TELEPORTER_STATES.COOL_IN; coolInTimeout = Script.setTimeout(function() { if (_this.state === TELEPORTER_STATES.COOL_IN) { @@ -244,6 +262,8 @@ function Teleporter() { LaserPointers.disableLaserPointer(this.teleportRayLeftInvisible); LaserPointers.disableLaserPointer(this.teleportRayRightVisible); LaserPointers.disableLaserPointer(this.teleportRayRightInvisible); + LaserPointers.disableLaserPointer(this.teleportRayHeadVisible); + LaserPointers.disableLaserPointer(this.teleportRayHeadInvisible); this.updateConnected = null; this.state = TELEPORTER_STATES.IDLE; @@ -255,6 +275,31 @@ function Teleporter() { return; } + // Get current hand pose information to see if the pose is valid + var pose = Controller.getPoseValue(handInfo[_this.activeHand].controllerInput); + var mode = pose.valid ? _this.activeHand : 'head'; + if (!pose.valid) { + if (mode === 'right') { + LaserPointers.disableLaserPointer(_this.teleportRayRightVisible); + LaserPointers.disableLaserPointer(_this.teleportRayRightInvisible); + } else { + LaserPointers.disableLaserPointer(_this.teleportRayLeftVisible); + LaserPointers.disableLaserPointer(_this.teleportRayLeftInvisible); + } + LaserPointers.enableLaserPointer(_this.teleportRayHeadVisible); + LaserPointers.enableLaserPointer(_this.teleportRayHeadInvisible); + } else { + if (mode === 'right') { + LaserPointers.enableLaserPointer(_this.teleportRayRightVisible); + LaserPointers.enableLaserPointer(_this.teleportRayRightInvisible); + } else { + LaserPointers.enableLaserPointer(_this.teleportRayLeftVisible); + LaserPointers.enableLaserPointer(_this.teleportRayLeftInvisible); + } + LaserPointers.disableLaserPointer(_this.teleportRayHeadVisible); + LaserPointers.disableLaserPointer(_this.teleportRayHeadInvisible); + } + // We do up to 2 ray picks to find a teleport location. // There are 2 types of teleport locations we are interested in: // 1. A visible floor. This can be any entity surface that points within some degree of "up" @@ -264,28 +309,39 @@ function Teleporter() { // We might hit an invisible entity that is not a seat, so we need to do a second pass. // * In the second pass we pick against visible entities only. // - var result = (_this.activeHand === 'right') ? LaserPointers.getPrevRayPickResult(_this.teleportRayRightInvisible) : - LaserPointers.getPrevRayPickResult(_this.teleportRayLeftInvisible); + var result; + if (mode === 'right') { + result = LaserPointers.getPrevRayPickResult(_this.teleportRayRightInvisible); + } else if (mode === 'left') { + result = LaserPointers.getPrevRayPickResult(_this.teleportRayLeftInvisible); + } else { + result = LaserPointers.getPrevRayPickResult(_this.teleportRayHeadInvisible); + } var teleportLocationType = getTeleportTargetType(result); if (teleportLocationType === TARGET.INVISIBLE) { - result = (_this.activeHand === 'right') ? LaserPointers.getPrevRayPickResult(_this.teleportRayRightVisible) : - LaserPointers.getPrevRayPickResult(_this.teleportRayLeftVisible); + if (mode === 'right') { + result = LaserPointers.getPrevRayPickResult(_this.teleportRayRightVisible); + } else if (mode === 'left') { + result = LaserPointers.getPrevRayPickResult(_this.teleportRayLeftVisible); + } else { + result = LaserPointers.getPrevRayPickResult(_this.teleportRayHeadVisible); + } teleportLocationType = getTeleportTargetType(result); } if (teleportLocationType === TARGET.NONE) { - this.setTeleportState(_this.activeHand, "", ""); + this.setTeleportState(mode, "", ""); } else if (teleportLocationType === TARGET.INVALID || teleportLocationType === TARGET.INVISIBLE) { - this.setTeleportState(_this.activeHand, "", "cancel"); + this.setTeleportState(mode, "", "cancel"); } else if (teleportLocationType === TARGET.SURFACE) { if (this.state === TELEPORTER_STATES.COOL_IN) { - this.setTeleportState(_this.activeHand, "cancel", ""); + this.setTeleportState(mode, "cancel", ""); } else { - this.setTeleportState(_this.activeHand, "teleport", ""); + this.setTeleportState(mode, "teleport", ""); } } else if (teleportLocationType === TARGET.SEAT) { - this.setTeleportState(_this.activeHand, "", "seat"); + this.setTeleportState(mode, "", "seat"); } @@ -308,13 +364,16 @@ function Teleporter() { } }; - this.setTeleportState = function(hand, visibleState, invisibleState) { - if (hand === 'right') { + this.setTeleportState = function(mode, visibleState, invisibleState) { + if (mode === 'right') { LaserPointers.setRenderState(_this.teleportRayRightVisible, visibleState); LaserPointers.setRenderState(_this.teleportRayRightInvisible, invisibleState); - } else { + } else if (mode === 'left') { LaserPointers.setRenderState(_this.teleportRayLeftVisible, visibleState); LaserPointers.setRenderState(_this.teleportRayLeftInvisible, invisibleState); + } else { + LaserPointers.setRenderState(_this.teleportRayHeadVisible, visibleState); + LaserPointers.setRenderState(_this.teleportRayHeadInvisible, invisibleState); } }; } From 912b417dd4574c65ac142fb3d3540e56b06550ce Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 19 Jul 2017 13:56:18 -0700 Subject: [PATCH 18/42] mouse ray pick --- interface/src/raypick/LaserPointer.cpp | 16 ++++++++++ interface/src/raypick/LaserPointer.h | 2 ++ interface/src/raypick/LaserPointerManager.cpp | 7 ++++ interface/src/raypick/LaserPointerManager.h | 2 ++ .../LaserPointerScriptingInterface.cpp | 24 ++++++++------ interface/src/raypick/MouseRayPick.cpp | 32 +++++++++++++++++++ interface/src/raypick/MouseRayPick.h | 26 +++++++++++++++ 7 files changed, 99 insertions(+), 10 deletions(-) create mode 100644 interface/src/raypick/MouseRayPick.cpp create mode 100644 interface/src/raypick/MouseRayPick.h diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 930e72a6fe..a4538e4aff 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -12,6 +12,7 @@ #include "JointRayPick.h" #include "StaticRayPick.h" +#include "MouseRayPick.h" #include "Application.h" #include "avatar/AvatarManager.h" @@ -48,6 +49,21 @@ LaserPointer::LaserPointer(const glm::vec3& position, const glm::vec3& direction } } +LaserPointer::LaserPointer(const uint16_t filter, const float maxDistance, const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool enabled) : + _renderingEnabled(enabled), + _renderStates(renderStates), + _faceAvatar(faceAvatar), + _centerEndY(centerEndY) +{ + _rayPickUID = DependencyManager::get()->addRayPick(std::make_shared(filter, maxDistance, enabled)); + + for (auto& state : _renderStates.keys()) { + if (!enabled || state != _currentRenderState) { + disableRenderState(state); + } + } +} + LaserPointer::~LaserPointer() { DependencyManager::get()->removeRayPick(_rayPickUID); for (RenderState& renderState : _renderStates) { diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index ba9a876556..fef7fe62f1 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -50,6 +50,8 @@ public: const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool enabled); LaserPointer(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance, const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool enabled); + LaserPointer(const uint16_t filter, const float maxDistance, const QHash& renderStates, const bool faceAvatar, + const bool centerEndY, const bool enabled); ~LaserPointer(); unsigned int getUID() { return _rayPickUID; } diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp index b8086c2f89..12f0223297 100644 --- a/interface/src/raypick/LaserPointerManager.cpp +++ b/interface/src/raypick/LaserPointerManager.cpp @@ -28,6 +28,13 @@ unsigned int LaserPointerManager::createLaserPointer(const glm::vec3& position, return uid; } +unsigned int LaserPointerManager::createLaserPointer(const uint16_t filter, const float maxDistance, const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool enabled) { + std::shared_ptr laserPointer = std::make_shared(filter, maxDistance, renderStates, faceAvatar, centerEndY, enabled); + unsigned int uid = laserPointer->getUID(); + _laserPointers[uid] = laserPointer; + return uid; +} + void LaserPointerManager::enableLaserPointer(const unsigned int uid) { if (_laserPointers.contains(uid)) { _laserPointers[uid]->enable(); diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h index fc043a9685..6eb649efd4 100644 --- a/interface/src/raypick/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -29,6 +29,8 @@ public: const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool enabled); unsigned int createLaserPointer(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance, const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool enabled); + unsigned int createLaserPointer(const uint16_t filter, const float maxDistance, const QHash& renderStates, const bool faceAvatar, + const bool centerEndY, const bool enabled); void removeLaserPointer(const unsigned int uid) { _laserPointers.remove(uid); } void enableLaserPointer(const unsigned int uid); void disableLaserPointer(const unsigned int uid); diff --git a/interface/src/raypick/LaserPointerScriptingInterface.cpp b/interface/src/raypick/LaserPointerScriptingInterface.cpp index a53b3dbf01..3260ffc165 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.cpp +++ b/interface/src/raypick/LaserPointerScriptingInterface.cpp @@ -88,18 +88,22 @@ uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& prop if (propertyMap["joint"].isValid()) { QString jointName = propertyMap["joint"].toString(); - // x = upward, y = forward, z = lateral - glm::vec3 posOffset = Vectors::ZERO; - if (propertyMap["posOffset"].isValid()) { - posOffset = vec3FromVariant(propertyMap["posOffset"]); - } + if (jointName != "Mouse") { + // x = upward, y = forward, z = lateral + glm::vec3 posOffset = Vectors::ZERO; + if (propertyMap["posOffset"].isValid()) { + posOffset = vec3FromVariant(propertyMap["posOffset"]); + } - glm::vec3 dirOffset = Vectors::UP; - if (propertyMap["dirOffset"].isValid()) { - dirOffset = vec3FromVariant(propertyMap["dirOffset"]); - } + glm::vec3 dirOffset = Vectors::UP; + if (propertyMap["dirOffset"].isValid()) { + dirOffset = vec3FromVariant(propertyMap["dirOffset"]); + } - return DependencyManager::get()->createLaserPointer(jointName, posOffset, dirOffset, filter, maxDistance, renderStates, faceAvatar, centerEndY, enabled); + return DependencyManager::get()->createLaserPointer(jointName, posOffset, dirOffset, filter, maxDistance, renderStates, faceAvatar, centerEndY, enabled); + } else { + return DependencyManager::get()->createLaserPointer(filter, maxDistance, renderStates, faceAvatar, centerEndY, enabled); + } } else if (propertyMap["position"].isValid()) { glm::vec3 position = vec3FromVariant(propertyMap["position"]); diff --git a/interface/src/raypick/MouseRayPick.cpp b/interface/src/raypick/MouseRayPick.cpp new file mode 100644 index 0000000000..39dcb74090 --- /dev/null +++ b/interface/src/raypick/MouseRayPick.cpp @@ -0,0 +1,32 @@ +// +// MouseRayPick.cpp +// interface/src/raypick +// +// Created by Sam Gondelman 7/19/2017 +// Copyright 2017 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 "MouseRayPick.h" + +#include "DependencyManager.h" +#include "Application.h" +#include "display-plugins/CompositorHelper.h" + +MouseRayPick::MouseRayPick(const uint16_t filter, const float maxDistance, const bool enabled) : + RayPick(filter, maxDistance, enabled) +{ +} + +const PickRay MouseRayPick::getPickRay(bool& valid) const { + QVariant position = qApp->getApplicationCompositor().getReticleInterface()->getPosition(); + if (position.isValid()) { + QVariantMap posMap = position.toMap(); + valid = true; + return qApp->getCamera().computePickRay(posMap["x"].toFloat(), posMap["y"].toFloat()); + } + + valid = false; + return PickRay(); +} diff --git a/interface/src/raypick/MouseRayPick.h b/interface/src/raypick/MouseRayPick.h new file mode 100644 index 0000000000..473d1871e8 --- /dev/null +++ b/interface/src/raypick/MouseRayPick.h @@ -0,0 +1,26 @@ +// +// MouseRayPick.h +// interface/src/raypick +// +// Created by Sam Gondelman 7/19/2017 +// Copyright 2017 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_MouseRayPick_h +#define hifi_MouseRayPick_h + +#include "RayPick.h" + +#include + +class MouseRayPick : public RayPick { + +public: + MouseRayPick(const uint16_t filter, const float maxDistance = 0.0f, const bool enabled = false); + + const PickRay getPickRay(bool& valid) const override; +}; + +#endif // hifi_MouseRayPick_h From bf243d60255c8ce940ae86ef9f59e8bba7493bc7 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 19 Jul 2017 17:45:21 -0700 Subject: [PATCH 19/42] lockEnd, editRenderState, and updated grab.js --- interface/src/raypick/LaserPointer.cpp | 50 ++++++-- interface/src/raypick/LaserPointer.h | 15 ++- interface/src/raypick/LaserPointerManager.cpp | 19 ++- interface/src/raypick/LaserPointerManager.h | 7 +- .../LaserPointerScriptingInterface.cpp | 89 ++++++++----- .../raypick/LaserPointerScriptingInterface.h | 4 + scripts/system/controllers/grab.js | 119 +++++++++--------- 7 files changed, 191 insertions(+), 112 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index a4538e4aff..057901bdb6 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -18,11 +18,12 @@ #include "avatar/AvatarManager.h" LaserPointer::LaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, - const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool enabled) : + const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) : _renderingEnabled(enabled), _renderStates(renderStates), _faceAvatar(faceAvatar), - _centerEndY(centerEndY) + _centerEndY(centerEndY), + _lockEnd(lockEnd) { _rayPickUID = DependencyManager::get()->addRayPick(std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled)); @@ -34,11 +35,12 @@ LaserPointer::LaserPointer(const QString& jointName, const glm::vec3& posOffset, } LaserPointer::LaserPointer(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance, - const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool enabled) : + const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) : _renderingEnabled(enabled), _renderStates(renderStates), _faceAvatar(faceAvatar), - _centerEndY(centerEndY) + _centerEndY(centerEndY), + _lockEnd(lockEnd) { _rayPickUID = DependencyManager::get()->addRayPick(std::make_shared(position, direction, filter, maxDistance, enabled)); @@ -49,11 +51,13 @@ LaserPointer::LaserPointer(const glm::vec3& position, const glm::vec3& direction } } -LaserPointer::LaserPointer(const uint16_t filter, const float maxDistance, const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool enabled) : +LaserPointer::LaserPointer(const uint16_t filter, const float maxDistance, const QHash& renderStates, const bool faceAvatar, const bool centerEndY, + const bool lockEnd, const bool enabled) : _renderingEnabled(enabled), _renderStates(renderStates), _faceAvatar(faceAvatar), - _centerEndY(centerEndY) + _centerEndY(centerEndY), + _lockEnd(lockEnd) { _rayPickUID = DependencyManager::get()->addRayPick(std::make_shared(filter, maxDistance, enabled)); @@ -99,6 +103,27 @@ void LaserPointer::setRenderState(const QString& state) { _currentRenderState = state; } +void LaserPointer::editRenderState(const QString& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) { + _renderStates[state].setStartID(updateRenderStateOverlay(_renderStates[state].getStartID(), startProps)); + _renderStates[state].setPathID(updateRenderStateOverlay(_renderStates[state].getPathID(), pathProps)); + _renderStates[state].setEndID(updateRenderStateOverlay(_renderStates[state].getEndID(), endProps)); +} + +OverlayID LaserPointer::updateRenderStateOverlay(const OverlayID& id, const QVariant& props) { + if (props.isValid()) { + if (!id.isNull()) { + qApp->getOverlays().editOverlay(id, props); + return id; + } else { + QVariantMap propsMap = props.toMap(); + if (propsMap["type"].isValid()) { + return qApp->getOverlays().addOverlay(propsMap["type"].toString(), props); + } + } + } + return OverlayID(); +} + void LaserPointer::disableRenderState(const QString& renderState) { if (!_renderStates[renderState].getStartID().isNull()) { QVariantMap startProps; @@ -131,7 +156,18 @@ void LaserPointer::update() { startProps.insert("ignoreRayIntersection", _renderStates[_currentRenderState].doesStartIgnoreRays()); qApp->getOverlays().editOverlay(_renderStates[_currentRenderState].getStartID(), startProps); } - glm::vec3 endVec = pickRay.origin + pickRay.direction * prevRayPickResult.distance; + glm::vec3 endVec; + if (!_lockEnd || prevRayPickResult.type == IntersectionType::HUD) { + endVec = pickRay.origin + pickRay.direction * prevRayPickResult.distance; + } else { + if (prevRayPickResult.type == IntersectionType::ENTITY) { + endVec = DependencyManager::get()->getEntityTransform(prevRayPickResult.objectID)[3]; + } else if (prevRayPickResult.type == IntersectionType::OVERLAY) { + endVec = vec3FromVariant(qApp->getOverlays().getProperty(prevRayPickResult.objectID, "position").value); + } else if (prevRayPickResult.type == IntersectionType::AVATAR) { + endVec = DependencyManager::get()->getAvatar(prevRayPickResult.objectID)->getPosition(); + } + } QVariant end = vec3toVariant(endVec); if (!_renderStates[_currentRenderState].getPathID().isNull()) { QVariantMap pathProps; diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index fef7fe62f1..de302ca6dc 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -29,6 +29,9 @@ public: const OverlayID& getStartID() { return _startID; } const OverlayID& getPathID() { return _pathID; } const OverlayID& getEndID() { return _endID; } + void setStartID(const OverlayID& startID) { _startID = startID; } + void setPathID(const OverlayID& pathID) { _pathID = pathID; } + void setEndID(const OverlayID& endID) { _endID = endID; } const bool& doesStartIgnoreRays() { return _startIgnoreRays; } const bool& doesPathIgnoreRays() { return _pathIgnoreRays; } const bool& doesEndIgnoreRays() { return _endIgnoreRays; } @@ -47,11 +50,11 @@ class LaserPointer { public: LaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, - const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool enabled); + const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled); LaserPointer(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance, - const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool enabled); + const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled); LaserPointer(const uint16_t filter, const float maxDistance, const QHash& renderStates, const bool faceAvatar, - const bool centerEndY, const bool enabled); + const bool centerEndY, const bool lockEnd, const bool enabled); ~LaserPointer(); unsigned int getUID() { return _rayPickUID; } @@ -60,7 +63,7 @@ public: const RayPickResult getPrevRayPickResult() { return DependencyManager::get()->getPrevRayPickResult(_rayPickUID); } void setRenderState(const QString& state); - void disableRenderState(const QString& renderState); + void editRenderState(const QString& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps); void update(); @@ -70,8 +73,12 @@ private: QHash _renderStates; bool _faceAvatar; bool _centerEndY; + bool _lockEnd; unsigned int _rayPickUID; + + OverlayID updateRenderStateOverlay(const OverlayID& id, const QVariant& props); + void disableRenderState(const QString& renderState); }; #endif // hifi_LaserPointer_h diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp index 12f0223297..f60d9639ac 100644 --- a/interface/src/raypick/LaserPointerManager.cpp +++ b/interface/src/raypick/LaserPointerManager.cpp @@ -13,23 +13,24 @@ #include "RayPick.h" unsigned int LaserPointerManager::createLaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, - const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool enabled) { - std::shared_ptr laserPointer = std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, renderStates, faceAvatar, centerEndY, enabled); + const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) { + std::shared_ptr laserPointer = std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, renderStates, faceAvatar, centerEndY, lockEnd, enabled); unsigned int uid = laserPointer->getUID(); _laserPointers[uid] = laserPointer; return uid; } unsigned int LaserPointerManager::createLaserPointer(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance, - const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool enabled) { - std::shared_ptr laserPointer = std::make_shared(position, direction, filter, maxDistance, renderStates, faceAvatar, centerEndY, enabled); + const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) { + std::shared_ptr laserPointer = std::make_shared(position, direction, filter, maxDistance, renderStates, faceAvatar, centerEndY, lockEnd, enabled); unsigned int uid = laserPointer->getUID(); _laserPointers[uid] = laserPointer; return uid; } -unsigned int LaserPointerManager::createLaserPointer(const uint16_t filter, const float maxDistance, const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool enabled) { - std::shared_ptr laserPointer = std::make_shared(filter, maxDistance, renderStates, faceAvatar, centerEndY, enabled); +unsigned int LaserPointerManager::createLaserPointer(const uint16_t filter, const float maxDistance, const QHash& renderStates, const bool faceAvatar, + const bool centerEndY, const bool lockEnd, const bool enabled) { + std::shared_ptr laserPointer = std::make_shared(filter, maxDistance, renderStates, faceAvatar, centerEndY, lockEnd, enabled); unsigned int uid = laserPointer->getUID(); _laserPointers[uid] = laserPointer; return uid; @@ -53,6 +54,12 @@ void LaserPointerManager::setRenderState(unsigned int uid, const QString & rende } } +void LaserPointerManager::editRenderState(unsigned int uid, const QString& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) { + if (_laserPointers.contains(uid)) { + _laserPointers[uid]->editRenderState(state, startProps, pathProps, endProps); + } +} + const RayPickResult LaserPointerManager::getPrevRayPickResult(const unsigned int uid) { if (_laserPointers.contains(uid)) { return _laserPointers[uid]->getPrevRayPickResult(); diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h index 6eb649efd4..574a4d9e96 100644 --- a/interface/src/raypick/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -26,15 +26,16 @@ class LaserPointerManager : public Dependency { public: unsigned int createLaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, - const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool enabled); + const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled); unsigned int createLaserPointer(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance, - const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool enabled); + const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled); unsigned int createLaserPointer(const uint16_t filter, const float maxDistance, const QHash& renderStates, const bool faceAvatar, - const bool centerEndY, const bool enabled); + const bool centerEndY, const bool lockEnd, const bool enabled); void removeLaserPointer(const unsigned int uid) { _laserPointers.remove(uid); } void enableLaserPointer(const unsigned int uid); void disableLaserPointer(const unsigned int uid); void setRenderState(unsigned int uid, const QString& renderState); + void editRenderState(unsigned int uid, const QString& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps); const RayPickResult getPrevRayPickResult(const unsigned int uid); void update(); diff --git a/interface/src/raypick/LaserPointerScriptingInterface.cpp b/interface/src/raypick/LaserPointerScriptingInterface.cpp index 3260ffc165..1cc3a967c4 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.cpp +++ b/interface/src/raypick/LaserPointerScriptingInterface.cpp @@ -40,6 +40,11 @@ uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& prop centerEndY = propertyMap["centerEndY"].toBool(); } + bool lockEnd = false; + if (propertyMap["lockEnd"].isValid()) { + lockEnd = propertyMap["lockEnd"].toBool(); + } + bool enabled = false; if (propertyMap["enabled"].isValid()) { enabled = propertyMap["enabled"].toBool(); @@ -53,33 +58,7 @@ uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& prop QVariantMap renderStateMap = renderStateVariant.toMap(); if (renderStateMap["name"].isValid()) { QString name = renderStateMap["name"].toString(); - - QUuid startID; - if (renderStateMap["start"].isValid()) { - QVariantMap startMap = renderStateMap["start"].toMap(); - if (startMap["type"].isValid()) { - startID = qApp->getOverlays().addOverlay(startMap["type"].toString(), startMap); - } - } - - QUuid pathID; - if (renderStateMap["path"].isValid()) { - QVariantMap pathMap = renderStateMap["path"].toMap(); - // right now paths must be line3ds - if (pathMap["type"].isValid() && pathMap["type"].toString() == "line3d") { - pathID = qApp->getOverlays().addOverlay(pathMap["type"].toString(), pathMap); - } - } - - QUuid endID; - if (renderStateMap["end"].isValid()) { - QVariantMap endMap = renderStateMap["end"].toMap(); - if (endMap["type"].isValid()) { - endID = qApp->getOverlays().addOverlay(endMap["type"].toString(), endMap); - } - } - - renderStates[name] = RenderState(startID, pathID, endID); + renderStates[name] = buildRenderState(renderStateMap); } } } @@ -100,9 +79,9 @@ uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& prop dirOffset = vec3FromVariant(propertyMap["dirOffset"]); } - return DependencyManager::get()->createLaserPointer(jointName, posOffset, dirOffset, filter, maxDistance, renderStates, faceAvatar, centerEndY, enabled); + return DependencyManager::get()->createLaserPointer(jointName, posOffset, dirOffset, filter, maxDistance, renderStates, faceAvatar, centerEndY, lockEnd, enabled); } else { - return DependencyManager::get()->createLaserPointer(filter, maxDistance, renderStates, faceAvatar, centerEndY, enabled); + return DependencyManager::get()->createLaserPointer(filter, maxDistance, renderStates, faceAvatar, centerEndY, lockEnd, enabled); } } else if (propertyMap["position"].isValid()) { glm::vec3 position = vec3FromVariant(propertyMap["position"]); @@ -112,8 +91,58 @@ uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& prop direction = vec3FromVariant(propertyMap["direction"]); } - return DependencyManager::get()->createLaserPointer(position, direction, filter, maxDistance, renderStates, faceAvatar, centerEndY, enabled); + return DependencyManager::get()->createLaserPointer(position, direction, filter, maxDistance, renderStates, faceAvatar, centerEndY, lockEnd, enabled); } return 0; +} + +void LaserPointerScriptingInterface::editRenderState(unsigned int uid, const QString& renderState, const QVariant& properties) { + QVariantMap propMap = properties.toMap(); + + QVariant startProps; + if (propMap["start"].isValid()) { + startProps = propMap["start"]; + } + + QVariant pathProps; + if (propMap["path"].isValid()) { + pathProps = propMap["path"]; + } + + QVariant endProps; + if (propMap["end"].isValid()) { + endProps = propMap["end"]; + } + + DependencyManager::get()->editRenderState(uid, renderState, startProps, pathProps, endProps); +} + +const RenderState LaserPointerScriptingInterface::buildRenderState(const QVariantMap& propMap) { + QUuid startID; + if (propMap["start"].isValid()) { + QVariantMap startMap = propMap["start"].toMap(); + if (startMap["type"].isValid()) { + startID = qApp->getOverlays().addOverlay(startMap["type"].toString(), startMap); + } + } + + QUuid pathID; + if (propMap["path"].isValid()) { + QVariantMap pathMap = propMap["path"].toMap(); + // right now paths must be line3ds + if (pathMap["type"].isValid() && pathMap["type"].toString() == "line3d") { + pathID = qApp->getOverlays().addOverlay(pathMap["type"].toString(), pathMap); + } + } + + QUuid endID; + if (propMap["end"].isValid()) { + QVariantMap endMap = propMap["end"].toMap(); + if (endMap["type"].isValid()) { + endID = qApp->getOverlays().addOverlay(endMap["type"].toString(), endMap); + } + } + + return RenderState(startID, pathID, endID); } \ No newline at end of file diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h index 708c378abb..f91fa617ae 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -26,9 +26,13 @@ public slots: Q_INVOKABLE void enableLaserPointer(unsigned int uid) { DependencyManager::get()->enableLaserPointer(uid); } Q_INVOKABLE void disableLaserPointer(unsigned int uid) { DependencyManager::get()->disableLaserPointer(uid); } Q_INVOKABLE void removeLaserPointer(unsigned int uid) { DependencyManager::get()->removeLaserPointer(uid); } + Q_INVOKABLE void editRenderState(unsigned int uid, const QString& renderState, const QVariant& properties); Q_INVOKABLE void setRenderState(unsigned int uid, const QString& renderState) { DependencyManager::get()->setRenderState(uid, renderState); } Q_INVOKABLE RayPickResult getPrevRayPickResult(unsigned int uid) { return DependencyManager::get()->getPrevRayPickResult(uid); } +private: + const RenderState buildRenderState(const QVariantMap & propMap); + }; #endif // hifi_LaserPointerScriptingInterface_h diff --git a/scripts/system/controllers/grab.js b/scripts/system/controllers/grab.js index da8add5117..ae1474f140 100644 --- a/scripts/system/controllers/grab.js +++ b/scripts/system/controllers/grab.js @@ -197,53 +197,24 @@ Mouse.prototype.restoreRotateCursor = function() { var mouse = new Mouse(); - -// Beacon class stores info for drawing a line at object's target position -function Beacon() { - this.height = 0.10; - this.overlayID = Overlays.addOverlay("line3d", { - color: { - red: 200, - green: 200, - blue: 200 - }, - alpha: 1, - visible: false, - lineWidth: 2 - }); -} - -Beacon.prototype.enable = function() { - Overlays.editOverlay(this.overlayID, { - visible: true - }); +var beacon = { + type: "cube", + dimensions: { + x: 0.01, + y: 0, + z: 0.01 + }, + color: { + red: 200, + green: 200, + blue: 200 + }, + alpha: 1, + solid: true, + ignoreRayIntersection: true, + visible: true }; -Beacon.prototype.disable = function() { - Overlays.editOverlay(this.overlayID, { - visible: false - }); -}; - -Beacon.prototype.updatePosition = function(position) { - Overlays.editOverlay(this.overlayID, { - visible: true, - start: { - x: position.x, - y: position.y + this.height, - z: position.z - }, - end: { - x: position.x, - y: position.y - this.height, - z: position.z - } - }); -}; - -var beacon = new Beacon(); - - // TODO: play sounds again when we aren't leaking AudioInjector threads // var grabSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/CloseClamp.wav"); // var releaseSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/ReleaseClamp.wav"); @@ -285,6 +256,19 @@ function Grabber() { this.liftKey = false; // SHIFT this.rotateKey = false; // CONTROL + + this.mouseRayOverlays = LaserPointers.createLaserPointer({ + joint: "Mouse", + filter: RayPick.PICK_OVERLAYS, + enabled: true + }); + this.mouseRayEntities = LaserPointers.createLaserPointer({ + joint: "Mouse", + filter: RayPick.PICK_ENTITIES, + lockEnd: true, + faceAvatar: true, + enabled: true + }); } Grabber.prototype.computeNewGrabPlane = function() { @@ -333,40 +317,43 @@ Grabber.prototype.pressEvent = function(event) { return; } - var pickRay = Camera.computePickRay(event.x, event.y); + var overlayResult = LaserPointers.getPrevRayPickResult(this.mouseRayOverlays); + if (overlayResult.type != RayPick.INTERSECTED_NONE) { + if (overlayResult.objectID == HMD.tabletID || overlayResult.objectID == HMD.tabletScreenID || overlayResult.objectID == HMD.homeButtonID) { + return; + } + } - var overlayResult = Overlays.findRayIntersection(pickRay, true, [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID]); - if (overlayResult.intersects) { + var pickResults = LaserPointers.getPrevRayPickResult(this.mouseRayEntities); + if (pickResults.type == RayPick.INTERSECTED_NONE) { + LaserPointers.setRenderState(this.mouseRayEntities, ""); return; } - var pickResults = Entities.findRayIntersection(pickRay, true); // accurate picking - if (!pickResults.intersects) { - // didn't click on anything - return; - } - - var isDynamic = Entities.getEntityProperties(pickResults.entityID, "dynamic").dynamic; + var isDynamic = Entities.getEntityProperties(pickResults.objectID, "dynamic").dynamic; if (!isDynamic) { // only grab dynamic objects return; } - var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, pickResults.entityID, DEFAULT_GRABBABLE_DATA); + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, pickResults.objectID, DEFAULT_GRABBABLE_DATA); if (grabbableData.grabbable === false) { return; } + LaserPointers.setRenderState(this.mouseRayEntities, "grabbed"); + mouse.startDrag(event); - var clickedEntity = pickResults.entityID; + var clickedEntity = pickResults.objectID; var entityProperties = Entities.getEntityProperties(clickedEntity); this.startPosition = entityProperties.position; this.lastRotation = entityProperties.rotation; var cameraPosition = Camera.getPosition(); var objectBoundingDiameter = Vec3.length(entityProperties.dimensions); - beacon.height = objectBoundingDiameter; + beacon.dimensions.y = objectBoundingDiameter; + LaserPointers.editRenderState(this.mouseRayEntities, "grabbed", {end: beacon}); this.maxDistance = objectBoundingDiameter / MAX_SOLID_ANGLE; if (Vec3.distance(this.startPosition, cameraPosition) > this.maxDistance) { // don't allow grabs of things far away @@ -385,6 +372,7 @@ Grabber.prototype.pressEvent = function(event) { }; // compute the grab point + var pickRay = Camera.computePickRay(event.x, event.y); var nearestPoint = Vec3.subtract(this.startPosition, cameraPosition); var distanceToGrab = Vec3.dot(nearestPoint, pickRay.direction); nearestPoint = Vec3.multiply(distanceToGrab, pickRay.direction); @@ -395,8 +383,6 @@ Grabber.prototype.pressEvent = function(event) { this.computeNewGrabPlane(); - beacon.updatePosition(this.startPosition); - if (!entityIsGrabbedByOther(this.entityID)) { this.moveEvent(event); } @@ -431,7 +417,7 @@ Grabber.prototype.releaseEvent = function(event) { } this.actionID = null; - beacon.disable(); + LaserPointers.setRenderState(this.mouseRayEntities, ""); var args = "mouse"; Entities.callEntityMethod(this.entityID, "releaseGrab", args); @@ -552,7 +538,6 @@ Grabber.prototype.moveEventProcess = function() { ttl: ACTION_TTL }; - beacon.updatePosition(this.targetPosition); } if (!this.actionID) { @@ -586,6 +571,11 @@ Grabber.prototype.keyPressEvent = function(event) { this.computeNewGrabPlane(); }; +Grabber.prototype.cleanup = function() { + LaserPointers.removeLaserPointer(this.mouseRayEntities); + LaserPointers.removeLaserPointer(this.mouseRayOverlays); +}; + var grabber = new Grabber(); function pressEvent(event) { @@ -608,10 +598,15 @@ function keyReleaseEvent(event) { grabber.keyReleaseEvent(event); } +function cleanup() { + grabber.cleanup(); +} + Controller.mousePressEvent.connect(pressEvent); Controller.mouseMoveEvent.connect(moveEvent); Controller.mouseReleaseEvent.connect(releaseEvent); Controller.keyPressEvent.connect(keyPressEvent); Controller.keyReleaseEvent.connect(keyReleaseEvent); +Script.scriptEnding.connect(cleanup); }()); // END LOCAL_SCOPE From d156680bc8c00ef78bc53adf662ddc706ff75ade Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 20 Jul 2017 12:15:06 -0700 Subject: [PATCH 20/42] ignore/include by ID, simplified caching logic --- interface/src/raypick/LaserPointer.h | 7 ++ interface/src/raypick/LaserPointerManager.cpp | 77 ++++++++++++- interface/src/raypick/LaserPointerManager.h | 11 +- .../raypick/LaserPointerScriptingInterface.h | 7 ++ interface/src/raypick/MouseRayPick.h | 2 - interface/src/raypick/RayPick.h | 19 +++ interface/src/raypick/RayPickManager.cpp | 108 ++++++++++-------- interface/src/raypick/RayPickManager.h | 7 ++ scripts/system/controllers/grab.js | 5 +- 9 files changed, 190 insertions(+), 53 deletions(-) diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index de302ca6dc..ec96dfd76f 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -65,6 +65,13 @@ public: void setRenderState(const QString& state); void editRenderState(const QString& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps); + void setIgnoreEntities(const QScriptValue& ignoreEntities) { DependencyManager::get()->setIgnoreEntities(_rayPickUID, ignoreEntities); } + void setIncludeEntities(const QScriptValue& includeEntities) { DependencyManager::get()->setIncludeEntities(_rayPickUID, includeEntities); } + void setIgnoreOverlays(const QScriptValue& ignoreOverlays) { DependencyManager::get()->setIgnoreOverlays(_rayPickUID, ignoreOverlays); } + void setIncludeOverlays(const QScriptValue& includeOverlays) { DependencyManager::get()->setIncludeOverlays(_rayPickUID, includeOverlays); } + void setIgnoreAvatars(const QScriptValue& ignoreAvatars) { DependencyManager::get()->setIgnoreAvatars(_rayPickUID, ignoreAvatars); } + void setIncludeAvatars(const QScriptValue& includeAvatars) { DependencyManager::get()->setIncludeAvatars(_rayPickUID, includeAvatars); } + void update(); private: diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp index f60d9639ac..5235c7736a 100644 --- a/interface/src/raypick/LaserPointerManager.cpp +++ b/interface/src/raypick/LaserPointerManager.cpp @@ -16,7 +16,9 @@ unsigned int LaserPointerManager::createLaserPointer(const QString& jointName, c const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) { std::shared_ptr laserPointer = std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, renderStates, faceAvatar, centerEndY, lockEnd, enabled); unsigned int uid = laserPointer->getUID(); + QWriteLocker lock(&_lock); _laserPointers[uid] = laserPointer; + _laserPointerLocks[uid] = std::make_shared(); return uid; } @@ -24,7 +26,9 @@ unsigned int LaserPointerManager::createLaserPointer(const glm::vec3& position, const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) { std::shared_ptr laserPointer = std::make_shared(position, direction, filter, maxDistance, renderStates, faceAvatar, centerEndY, lockEnd, enabled); unsigned int uid = laserPointer->getUID(); + QWriteLocker lock(&_lock); _laserPointers[uid] = laserPointer; + _laserPointerLocks[uid] = std::make_shared(); return uid; } @@ -32,43 +36,112 @@ unsigned int LaserPointerManager::createLaserPointer(const uint16_t filter, cons const bool centerEndY, const bool lockEnd, const bool enabled) { std::shared_ptr laserPointer = std::make_shared(filter, maxDistance, renderStates, faceAvatar, centerEndY, lockEnd, enabled); unsigned int uid = laserPointer->getUID(); + QWriteLocker lock(&_lock); _laserPointers[uid] = laserPointer; + _laserPointerLocks[uid] = std::make_shared(); return uid; } +void LaserPointerManager::removeLaserPointer(const unsigned int uid) { + QWriteLocker lock(&_lock); + _laserPointers.remove(uid); + _laserPointerLocks.remove(uid); +} + void LaserPointerManager::enableLaserPointer(const unsigned int uid) { + QReadLocker lock(&_lock); if (_laserPointers.contains(uid)) { + QWriteLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->enable(); } } void LaserPointerManager::disableLaserPointer(const unsigned int uid) { + QReadLocker lock(&_lock); if (_laserPointers.contains(uid)) { + QWriteLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->disable(); } } void LaserPointerManager::setRenderState(unsigned int uid, const QString & renderState) { + QReadLocker lock(&_lock); if (_laserPointers.contains(uid)) { + QWriteLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->setRenderState(renderState); } } void LaserPointerManager::editRenderState(unsigned int uid, const QString& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) { + QReadLocker lock(&_lock); if (_laserPointers.contains(uid)) { + QWriteLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->editRenderState(state, startProps, pathProps, endProps); } } const RayPickResult LaserPointerManager::getPrevRayPickResult(const unsigned int uid) { + QReadLocker lock(&_lock); if (_laserPointers.contains(uid)) { + QReadLocker laserLock(_laserPointerLocks[uid].get()); return _laserPointers[uid]->getPrevRayPickResult(); } return RayPickResult(); } void LaserPointerManager::update() { - for (auto& laserPointer : _laserPointers) { - laserPointer->update(); + QReadLocker lock(&_lock); + for (unsigned int uid : _laserPointers.keys()) { + // This only needs to be a read lock because update won't change any of the properties that can be modified from scripts + QReadLocker laserLock(_laserPointerLocks[uid].get()); + _laserPointers[uid]->update(); + } +} + +void LaserPointerManager::setIgnoreEntities(unsigned int uid, const QScriptValue& ignoreEntities) { + QReadLocker lock(&_lock); + if (_laserPointers.contains(uid)) { + QWriteLocker laserLock(_laserPointerLocks[uid].get()); + _laserPointers[uid]->setIgnoreEntities(ignoreEntities); + } +} + +void LaserPointerManager::setIncludeEntities(unsigned int uid, const QScriptValue& includeEntities) { + QReadLocker lock(&_lock); + if (_laserPointers.contains(uid)) { + QWriteLocker laserLock(_laserPointerLocks[uid].get()); + _laserPointers[uid]->setIncludeEntities(includeEntities); + } +} + +void LaserPointerManager::setIgnoreOverlays(unsigned int uid, const QScriptValue& ignoreOverlays) { + QReadLocker lock(&_lock); + if (_laserPointers.contains(uid)) { + QWriteLocker laserLock(_laserPointerLocks[uid].get()); + _laserPointers[uid]->setIgnoreOverlays(ignoreOverlays); + } +} + +void LaserPointerManager::setIncludeOverlays(unsigned int uid, const QScriptValue& includeOverlays) { + QReadLocker lock(&_lock); + if (_laserPointers.contains(uid)) { + QWriteLocker laserLock(_laserPointerLocks[uid].get()); + _laserPointers[uid]->setIncludeOverlays(includeOverlays); + } +} + +void LaserPointerManager::setIgnoreAvatars(unsigned int uid, const QScriptValue& ignoreAvatars) { + QReadLocker lock(&_lock); + if (_laserPointers.contains(uid)) { + QWriteLocker laserLock(_laserPointerLocks[uid].get()); + _laserPointers[uid]->setIgnoreAvatars(ignoreAvatars); + } +} + +void LaserPointerManager::setIncludeAvatars(unsigned int uid, const QScriptValue& includeAvatars) { + QReadLocker lock(&_lock); + if (_laserPointers.contains(uid)) { + QWriteLocker laserLock(_laserPointerLocks[uid].get()); + _laserPointers[uid]->setIncludeAvatars(includeAvatars); } } \ No newline at end of file diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h index 574a4d9e96..a550de694a 100644 --- a/interface/src/raypick/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -31,17 +31,26 @@ public: const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled); unsigned int createLaserPointer(const uint16_t filter, const float maxDistance, const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled); - void removeLaserPointer(const unsigned int uid) { _laserPointers.remove(uid); } + void removeLaserPointer(const unsigned int uid); void enableLaserPointer(const unsigned int uid); void disableLaserPointer(const unsigned int uid); void setRenderState(unsigned int uid, const QString& renderState); void editRenderState(unsigned int uid, const QString& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps); const RayPickResult getPrevRayPickResult(const unsigned int uid); + void setIgnoreEntities(unsigned int uid, const QScriptValue& ignoreEntities); + void setIncludeEntities(unsigned int uid, const QScriptValue& includeEntities); + void setIgnoreOverlays(unsigned int uid, const QScriptValue& ignoreOverlays); + void setIncludeOverlays(unsigned int uid, const QScriptValue& includeOverlays); + void setIgnoreAvatars(unsigned int uid, const QScriptValue& ignoreAvatars); + void setIncludeAvatars(unsigned int uid, const QScriptValue& includeAvatars); + void update(); private: QHash> _laserPointers; + QReadWriteLock _lock; + QHash> _laserPointerLocks; }; diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h index f91fa617ae..d4297c59ac 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -30,6 +30,13 @@ public slots: Q_INVOKABLE void setRenderState(unsigned int uid, const QString& renderState) { DependencyManager::get()->setRenderState(uid, renderState); } Q_INVOKABLE RayPickResult getPrevRayPickResult(unsigned int uid) { return DependencyManager::get()->getPrevRayPickResult(uid); } + Q_INVOKABLE void setIgnoreEntities(unsigned int uid, const QScriptValue& ignoreEntities) { DependencyManager::get()->setIgnoreEntities(uid, ignoreEntities); } + Q_INVOKABLE void setIncludeEntities(unsigned int uid, const QScriptValue& includeEntities) { DependencyManager::get()->setIncludeEntities(uid, includeEntities); } + Q_INVOKABLE void setIgnoreOverlays(unsigned int uid, const QScriptValue& ignoreOverlays) { DependencyManager::get()->setIgnoreOverlays(uid, ignoreOverlays); } + Q_INVOKABLE void setIncludeOverlays(unsigned int uid, const QScriptValue& includeOverlays) { DependencyManager::get()->setIncludeOverlays(uid, includeOverlays); } + Q_INVOKABLE void setIgnoreAvatars(unsigned int uid, const QScriptValue& ignoreAvatars) { DependencyManager::get()->setIgnoreAvatars(uid, ignoreAvatars); } + Q_INVOKABLE void setIncludeAvatars(unsigned int uid, const QScriptValue& includeAvatars) { DependencyManager::get()->setIncludeAvatars(uid, includeAvatars); } + private: const RenderState buildRenderState(const QVariantMap & propMap); diff --git a/interface/src/raypick/MouseRayPick.h b/interface/src/raypick/MouseRayPick.h index 473d1871e8..84d1c86e24 100644 --- a/interface/src/raypick/MouseRayPick.h +++ b/interface/src/raypick/MouseRayPick.h @@ -13,8 +13,6 @@ #include "RayPick.h" -#include - class MouseRayPick : public RayPick { public: diff --git a/interface/src/raypick/RayPick.h b/interface/src/raypick/RayPick.h index e149611210..ca9660729a 100644 --- a/interface/src/raypick/RayPick.h +++ b/interface/src/raypick/RayPick.h @@ -31,12 +31,31 @@ public: void setRayPickResult(const RayPickResult& rayPickResult) { _prevResult = rayPickResult; } + const QScriptValue& getIgnoreEntites() { return _ignoreEntities; } + const QScriptValue& getIncludeEntites() { return _includeEntities; } + const QScriptValue& getIgnoreOverlays() { return _ignoreOverlays; } + const QScriptValue& getIncludeOverlays() { return _includeOverlays; } + const QScriptValue& getIgnoreAvatars() { return _ignoreAvatars; } + const QScriptValue& getIncludeAvatars() { return _includeAvatars; } + void setIgnoreEntities(const QScriptValue& ignoreEntities) { _ignoreEntities = ignoreEntities; } + void setIncludeEntities(const QScriptValue& includeEntities) { _includeEntities = includeEntities; } + void setIgnoreOverlays(const QScriptValue& ignoreOverlays) { _ignoreOverlays = ignoreOverlays; } + void setIncludeOverlays(const QScriptValue& includeOverlays) { _includeOverlays = includeOverlays; } + void setIgnoreAvatars(const QScriptValue& ignoreAvatars) { _ignoreAvatars = ignoreAvatars; } + void setIncludeAvatars(const QScriptValue& includeAvatars) { _includeAvatars = includeAvatars; } + private: uint16_t _filter; float _maxDistance; bool _enabled; RayPickResult _prevResult; + QScriptValue _ignoreEntities; + QScriptValue _includeEntities; + QScriptValue _ignoreOverlays; + QScriptValue _includeOverlays; + QScriptValue _ignoreAvatars; + QScriptValue _includeAvatars; }; #endif // hifi_RayPick_h diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp index ff4fca3f50..b7952bfef3 100644 --- a/interface/src/raypick/RayPickManager.cpp +++ b/interface/src/raypick/RayPickManager.cpp @@ -63,70 +63,40 @@ void RayPickManager::update() { if (rayPick->getFilter() & RayPickMask::PICK_ENTITIES) { RayToEntityIntersectionResult entityRes; bool fromCache = true; - if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE && rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE) { - if (!checkAndCompareCachedResults(rayKey, results, res, RayPickMask::PICK_ENTITIES | RayPickMask::PICK_INCLUDE_INVISIBLE | RayPickMask::PICK_INCLUDE_NONCOLLIDABLE)) { - entityRes = DependencyManager::get()->findRayIntersection(ray, true, QScriptValue(), QScriptValue(), false, false); - fromCache = false; - } - } else if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE) { - if (!checkAndCompareCachedResults(rayKey, results, res, RayPickMask::PICK_ENTITIES | RayPickMask::PICK_INCLUDE_INVISIBLE)) { - entityRes = DependencyManager::get()->findRayIntersection(ray, true, QScriptValue(), QScriptValue(), false, true); - fromCache = false; - } - } else if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE) { - if (!checkAndCompareCachedResults(rayKey, results, res, RayPickMask::PICK_ENTITIES | RayPickMask::PICK_INCLUDE_NONCOLLIDABLE)) { - entityRes = DependencyManager::get()->findRayIntersection(ray, true, QScriptValue(), QScriptValue(), true, false); - fromCache = false; - } - } else { - if (!checkAndCompareCachedResults(rayKey, results, res, RayPickMask::PICK_ENTITIES)) { - entityRes = DependencyManager::get()->findRayIntersection(ray, true, QScriptValue(), QScriptValue(), true, true); - fromCache = false; - } + unsigned int invisible = rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE; + unsigned int noncollidable = rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE; + unsigned int entityMask = RayPickMask::PICK_ENTITIES | invisible | noncollidable; + if (!checkAndCompareCachedResults(rayKey, results, res, entityMask)) { + entityRes = DependencyManager::get()->findRayIntersection(ray, true, rayPick->getIncludeEntites(), rayPick->getIgnoreEntites(), !invisible, !noncollidable); + fromCache = false; } if (!fromCache) { - unsigned int mask = (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE) | (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE); cacheResult(entityRes.intersects, RayPickResult(IntersectionType::ENTITY, entityRes.entityID, entityRes.distance, entityRes.intersection, entityRes.surfaceNormal), - RayPickMask::PICK_ENTITIES | mask, res, rayKey, results); + entityMask, res, rayKey, results); } } if (rayPick->getFilter() & RayPickMask::PICK_OVERLAYS) { RayToOverlayIntersectionResult overlayRes; bool fromCache = true; - if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE && rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE) { - if (!checkAndCompareCachedResults(rayKey, results, res, RayPickMask::PICK_OVERLAYS | RayPickMask::PICK_INCLUDE_INVISIBLE | RayPickMask::PICK_INCLUDE_NONCOLLIDABLE)) { - overlayRes = qApp->getOverlays().findRayIntersection(ray, true, QScriptValue(), QScriptValue(), false, false); - fromCache = false; - } - } else if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE) { - if (!checkAndCompareCachedResults(rayKey, results, res, RayPickMask::PICK_OVERLAYS | RayPickMask::PICK_INCLUDE_INVISIBLE)) { - overlayRes = qApp->getOverlays().findRayIntersection(ray, true, QScriptValue(), QScriptValue(), false, true); - fromCache = false; - } - } else if (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE) { - if (!checkAndCompareCachedResults(rayKey, results, res, RayPickMask::PICK_OVERLAYS | RayPickMask::PICK_INCLUDE_NONCOLLIDABLE)) { - overlayRes = qApp->getOverlays().findRayIntersection(ray, true, QScriptValue(), QScriptValue(), true, false); - fromCache = false; - } - } else { - if (!checkAndCompareCachedResults(rayKey, results, res, RayPickMask::PICK_OVERLAYS)) { - overlayRes = qApp->getOverlays().findRayIntersection(ray, true, QScriptValue(), QScriptValue(), true, true); - fromCache = false; - } + unsigned int invisible = rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE; + unsigned int noncollidable = rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE; + unsigned int overlayMask = RayPickMask::PICK_OVERLAYS | invisible | noncollidable; + if (!checkAndCompareCachedResults(rayKey, results, res, overlayMask)) { + overlayRes = qApp->getOverlays().findRayIntersection(ray, true, rayPick->getIncludeOverlays(), rayPick->getIgnoreOverlays(), !invisible, !noncollidable); + fromCache = false; } if (!fromCache) { - unsigned int mask = (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE) | (rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE); cacheResult(overlayRes.intersects, RayPickResult(IntersectionType::OVERLAY, overlayRes.overlayID, overlayRes.distance, overlayRes.intersection, overlayRes.surfaceNormal), - RayPickMask::PICK_OVERLAYS | mask, res, rayKey, results); + overlayMask, res, rayKey, results); } } if (rayPick->getFilter() & RayPickMask::PICK_AVATARS) { if (!checkAndCompareCachedResults(rayKey, results, res, RayPickMask::PICK_AVATARS)) { - RayToAvatarIntersectionResult avatarRes = DependencyManager::get()->findRayIntersection(ray, QScriptValue(), QScriptValue()); + RayToAvatarIntersectionResult avatarRes = DependencyManager::get()->findRayIntersection(ray, rayPick->getIncludeAvatars(), rayPick->getIgnoreAvatars()); cacheResult(avatarRes.intersects, RayPickResult(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection), RayPickMask::PICK_AVATARS, res, rayKey, results); } } @@ -214,3 +184,51 @@ const RayPickResult RayPickManager::getPrevRayPickResult(const unsigned int uid) } return RayPickResult(); } + +void RayPickManager::setIgnoreEntities(unsigned int uid, const QScriptValue& ignoreEntities) { + QReadLocker containsLock(&_containsLock); + if (_rayPicks.contains(uid)) { + QWriteLocker lock(_rayPickLocks[uid].get()); + _rayPicks[uid]->setIgnoreEntities(ignoreEntities); + } +} + +void RayPickManager::setIncludeEntities(unsigned int uid, const QScriptValue& includeEntities) { + QReadLocker containsLock(&_containsLock); + if (_rayPicks.contains(uid)) { + QWriteLocker lock(_rayPickLocks[uid].get()); + _rayPicks[uid]->setIncludeEntities(includeEntities); + } +} + +void RayPickManager::setIgnoreOverlays(unsigned int uid, const QScriptValue& ignoreOverlays) { + QReadLocker containsLock(&_containsLock); + if (_rayPicks.contains(uid)) { + QWriteLocker lock(_rayPickLocks[uid].get()); + _rayPicks[uid]->setIgnoreOverlays(ignoreOverlays); + } +} + +void RayPickManager::setIncludeOverlays(unsigned int uid, const QScriptValue& includeOverlays) { + QReadLocker containsLock(&_containsLock); + if (_rayPicks.contains(uid)) { + QWriteLocker lock(_rayPickLocks[uid].get()); + _rayPicks[uid]->setIncludeOverlays(includeOverlays); + } +} + +void RayPickManager::setIgnoreAvatars(unsigned int uid, const QScriptValue& ignoreAvatars) { + QReadLocker containsLock(&_containsLock); + if (_rayPicks.contains(uid)) { + QWriteLocker lock(_rayPickLocks[uid].get()); + _rayPicks[uid]->setIgnoreAvatars(ignoreAvatars); + } +} + +void RayPickManager::setIncludeAvatars(unsigned int uid, const QScriptValue& includeAvatars) { + QReadLocker containsLock(&_containsLock); + if (_rayPicks.contains(uid)) { + QWriteLocker lock(_rayPickLocks[uid].get()); + _rayPicks[uid]->setIncludeAvatars(includeAvatars); + } +} \ No newline at end of file diff --git a/interface/src/raypick/RayPickManager.h b/interface/src/raypick/RayPickManager.h index 7ecb028d29..400098587e 100644 --- a/interface/src/raypick/RayPickManager.h +++ b/interface/src/raypick/RayPickManager.h @@ -65,6 +65,13 @@ public: const PickRay getPickRay(const unsigned int uid); const RayPickResult getPrevRayPickResult(const unsigned int uid); + void setIgnoreEntities(unsigned int uid, const QScriptValue& ignoreEntities); + void setIncludeEntities(unsigned int uid, const QScriptValue& includeEntities); + void setIgnoreOverlays(unsigned int uid, const QScriptValue& ignoreOverlays); + void setIncludeOverlays(unsigned int uid, const QScriptValue& includeOverlays); + void setIgnoreAvatars(unsigned int uid, const QScriptValue& ignoreAvatars); + void setIncludeAvatars(unsigned int uid, const QScriptValue& includeAvatars); + private: QHash> _rayPicks; QHash> _rayPickLocks; diff --git a/scripts/system/controllers/grab.js b/scripts/system/controllers/grab.js index ae1474f140..411d5f6e41 100644 --- a/scripts/system/controllers/grab.js +++ b/scripts/system/controllers/grab.js @@ -262,6 +262,7 @@ function Grabber() { filter: RayPick.PICK_OVERLAYS, enabled: true }); + LaserPointers.setIncludeOverlays(this.mouseRayOverlays, [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID]); this.mouseRayEntities = LaserPointers.createLaserPointer({ joint: "Mouse", filter: RayPick.PICK_ENTITIES, @@ -319,9 +320,7 @@ Grabber.prototype.pressEvent = function(event) { var overlayResult = LaserPointers.getPrevRayPickResult(this.mouseRayOverlays); if (overlayResult.type != RayPick.INTERSECTED_NONE) { - if (overlayResult.objectID == HMD.tabletID || overlayResult.objectID == HMD.tabletScreenID || overlayResult.objectID == HMD.homeButtonID) { - return; - } + return; } var pickResults = LaserPointers.getPrevRayPickResult(this.mouseRayEntities); From c7f0f03fcebdc30782d04559787004f5996f197c Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 20 Jul 2017 13:53:39 -0700 Subject: [PATCH 21/42] expanded RayPick JS API --- interface/src/raypick/LaserPointer.cpp | 43 +--------- interface/src/raypick/LaserPointer.h | 10 +-- interface/src/raypick/LaserPointerManager.cpp | 84 +++++++++---------- interface/src/raypick/LaserPointerManager.h | 15 ++-- .../LaserPointerScriptingInterface.cpp | 42 +--------- interface/src/raypick/RayPickManager.cpp | 61 +++++++++++++- interface/src/raypick/RayPickManager.h | 24 +++--- scripts/system/controllers/grab.js | 8 +- 8 files changed, 129 insertions(+), 158 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 057901bdb6..76ed632027 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -10,56 +10,17 @@ // #include "LaserPointer.h" -#include "JointRayPick.h" -#include "StaticRayPick.h" -#include "MouseRayPick.h" - #include "Application.h" #include "avatar/AvatarManager.h" -LaserPointer::LaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, - const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) : +LaserPointer::LaserPointer(const QVariantMap& rayProps, const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) : _renderingEnabled(enabled), _renderStates(renderStates), _faceAvatar(faceAvatar), _centerEndY(centerEndY), _lockEnd(lockEnd) { - _rayPickUID = DependencyManager::get()->addRayPick(std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled)); - - for (auto& state : _renderStates.keys()) { - if (!enabled || state != _currentRenderState) { - disableRenderState(state); - } - } -} - -LaserPointer::LaserPointer(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance, - const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) : - _renderingEnabled(enabled), - _renderStates(renderStates), - _faceAvatar(faceAvatar), - _centerEndY(centerEndY), - _lockEnd(lockEnd) -{ - _rayPickUID = DependencyManager::get()->addRayPick(std::make_shared(position, direction, filter, maxDistance, enabled)); - - for (auto& state : _renderStates.keys()) { - if (!enabled || state != _currentRenderState) { - disableRenderState(state); - } - } -} - -LaserPointer::LaserPointer(const uint16_t filter, const float maxDistance, const QHash& renderStates, const bool faceAvatar, const bool centerEndY, - const bool lockEnd, const bool enabled) : - _renderingEnabled(enabled), - _renderStates(renderStates), - _faceAvatar(faceAvatar), - _centerEndY(centerEndY), - _lockEnd(lockEnd) -{ - _rayPickUID = DependencyManager::get()->addRayPick(std::make_shared(filter, maxDistance, enabled)); + _rayPickUID = DependencyManager::get()->createRayPick(rayProps); for (auto& state : _renderStates.keys()) { if (!enabled || state != _currentRenderState) { diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index ec96dfd76f..909e61e00c 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -49,15 +49,11 @@ private: class LaserPointer { public: - LaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, - const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled); - LaserPointer(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance, - const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled); - LaserPointer(const uint16_t filter, const float maxDistance, const QHash& renderStates, const bool faceAvatar, - const bool centerEndY, const bool lockEnd, const bool enabled); + LaserPointer::LaserPointer(const QVariantMap& rayProps, const QHash& renderStates, const bool faceAvatar, const bool centerEndY, + const bool lockEnd, const bool enabled); ~LaserPointer(); - unsigned int getUID() { return _rayPickUID; } + unsigned int getRayUID() { return _rayPickUID; } void enable(); void disable(); const RayPickResult getPrevRayPickResult() { return DependencyManager::get()->getPrevRayPickResult(_rayPickUID); } diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp index 5235c7736a..d9f3023263 100644 --- a/interface/src/raypick/LaserPointerManager.cpp +++ b/interface/src/raypick/LaserPointerManager.cpp @@ -12,44 +12,24 @@ #include "LaserPointer.h" #include "RayPick.h" -unsigned int LaserPointerManager::createLaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, - const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) { - std::shared_ptr laserPointer = std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, renderStates, faceAvatar, centerEndY, lockEnd, enabled); - unsigned int uid = laserPointer->getUID(); - QWriteLocker lock(&_lock); - _laserPointers[uid] = laserPointer; - _laserPointerLocks[uid] = std::make_shared(); - return uid; -} - -unsigned int LaserPointerManager::createLaserPointer(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance, - const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) { - std::shared_ptr laserPointer = std::make_shared(position, direction, filter, maxDistance, renderStates, faceAvatar, centerEndY, lockEnd, enabled); - unsigned int uid = laserPointer->getUID(); - QWriteLocker lock(&_lock); - _laserPointers[uid] = laserPointer; - _laserPointerLocks[uid] = std::make_shared(); - return uid; -} - -unsigned int LaserPointerManager::createLaserPointer(const uint16_t filter, const float maxDistance, const QHash& renderStates, const bool faceAvatar, - const bool centerEndY, const bool lockEnd, const bool enabled) { - std::shared_ptr laserPointer = std::make_shared(filter, maxDistance, renderStates, faceAvatar, centerEndY, lockEnd, enabled); - unsigned int uid = laserPointer->getUID(); - QWriteLocker lock(&_lock); - _laserPointers[uid] = laserPointer; - _laserPointerLocks[uid] = std::make_shared(); - return uid; +unsigned int LaserPointerManager::createLaserPointer(const QVariantMap& rayProps, const QHash& renderStates, const bool faceAvatar, const bool centerEndY, + const bool lockEnd, const bool enabled) { + std::shared_ptr laserPointer = std::make_shared(rayProps, renderStates, faceAvatar, centerEndY, lockEnd, enabled); + if (laserPointer->getRayUID() != 0) { + QWriteLocker lock(&_addLock); + _laserPointersToAdd.enqueue(QPair>(_nextUID, laserPointer)); + return _nextUID++; + } + return 0; } void LaserPointerManager::removeLaserPointer(const unsigned int uid) { - QWriteLocker lock(&_lock); - _laserPointers.remove(uid); - _laserPointerLocks.remove(uid); + QWriteLocker lock(&_removeLock); + _laserPointersToRemove.enqueue(uid); } void LaserPointerManager::enableLaserPointer(const unsigned int uid) { - QReadLocker lock(&_lock); + QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { QWriteLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->enable(); @@ -57,7 +37,7 @@ void LaserPointerManager::enableLaserPointer(const unsigned int uid) { } void LaserPointerManager::disableLaserPointer(const unsigned int uid) { - QReadLocker lock(&_lock); + QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { QWriteLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->disable(); @@ -65,7 +45,7 @@ void LaserPointerManager::disableLaserPointer(const unsigned int uid) { } void LaserPointerManager::setRenderState(unsigned int uid, const QString & renderState) { - QReadLocker lock(&_lock); + QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { QWriteLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->setRenderState(renderState); @@ -73,7 +53,7 @@ void LaserPointerManager::setRenderState(unsigned int uid, const QString & rende } void LaserPointerManager::editRenderState(unsigned int uid, const QString& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) { - QReadLocker lock(&_lock); + QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { QWriteLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->editRenderState(state, startProps, pathProps, endProps); @@ -81,7 +61,7 @@ void LaserPointerManager::editRenderState(unsigned int uid, const QString& state } const RayPickResult LaserPointerManager::getPrevRayPickResult(const unsigned int uid) { - QReadLocker lock(&_lock); + QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { QReadLocker laserLock(_laserPointerLocks[uid].get()); return _laserPointers[uid]->getPrevRayPickResult(); @@ -90,16 +70,34 @@ const RayPickResult LaserPointerManager::getPrevRayPickResult(const unsigned int } void LaserPointerManager::update() { - QReadLocker lock(&_lock); for (unsigned int uid : _laserPointers.keys()) { // This only needs to be a read lock because update won't change any of the properties that can be modified from scripts QReadLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->update(); } + + QWriteLocker containsLock(&_containsLock); + { + QWriteLocker lock(&_addLock); + while (!_laserPointersToAdd.isEmpty()) { + QPair> laserPointerToAdd = _laserPointersToAdd.dequeue(); + _laserPointers[laserPointerToAdd.first] = laserPointerToAdd.second; + _laserPointerLocks[laserPointerToAdd.first] = std::make_shared(); + } + } + + { + QWriteLocker lock(&_removeLock); + while (!_laserPointersToRemove.isEmpty()) { + unsigned int uid = _laserPointersToRemove.dequeue(); + _laserPointers.remove(uid); + _laserPointerLocks.remove(uid); + } + } } void LaserPointerManager::setIgnoreEntities(unsigned int uid, const QScriptValue& ignoreEntities) { - QReadLocker lock(&_lock); + QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { QWriteLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->setIgnoreEntities(ignoreEntities); @@ -107,7 +105,7 @@ void LaserPointerManager::setIgnoreEntities(unsigned int uid, const QScriptValue } void LaserPointerManager::setIncludeEntities(unsigned int uid, const QScriptValue& includeEntities) { - QReadLocker lock(&_lock); + QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { QWriteLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->setIncludeEntities(includeEntities); @@ -115,7 +113,7 @@ void LaserPointerManager::setIncludeEntities(unsigned int uid, const QScriptValu } void LaserPointerManager::setIgnoreOverlays(unsigned int uid, const QScriptValue& ignoreOverlays) { - QReadLocker lock(&_lock); + QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { QWriteLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->setIgnoreOverlays(ignoreOverlays); @@ -123,7 +121,7 @@ void LaserPointerManager::setIgnoreOverlays(unsigned int uid, const QScriptValue } void LaserPointerManager::setIncludeOverlays(unsigned int uid, const QScriptValue& includeOverlays) { - QReadLocker lock(&_lock); + QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { QWriteLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->setIncludeOverlays(includeOverlays); @@ -131,7 +129,7 @@ void LaserPointerManager::setIncludeOverlays(unsigned int uid, const QScriptValu } void LaserPointerManager::setIgnoreAvatars(unsigned int uid, const QScriptValue& ignoreAvatars) { - QReadLocker lock(&_lock); + QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { QWriteLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->setIgnoreAvatars(ignoreAvatars); @@ -139,7 +137,7 @@ void LaserPointerManager::setIgnoreAvatars(unsigned int uid, const QScriptValue& } void LaserPointerManager::setIncludeAvatars(unsigned int uid, const QScriptValue& includeAvatars) { - QReadLocker lock(&_lock); + QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { QWriteLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->setIncludeAvatars(includeAvatars); diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h index a550de694a..ff63927be2 100644 --- a/interface/src/raypick/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -25,12 +25,8 @@ class LaserPointerManager : public Dependency { SINGLETON_DEPENDENCY public: - unsigned int createLaserPointer(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, - const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled); - unsigned int createLaserPointer(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance, - const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled); - unsigned int createLaserPointer(const uint16_t filter, const float maxDistance, const QHash& renderStates, const bool faceAvatar, - const bool centerEndY, const bool lockEnd, const bool enabled); + unsigned int createLaserPointer(const QVariantMap& rayProps, const QHash& renderStates, const bool faceAvatar, const bool centerEndY, + const bool lockEnd, const bool enabled); void removeLaserPointer(const unsigned int uid); void enableLaserPointer(const unsigned int uid); void disableLaserPointer(const unsigned int uid); @@ -49,8 +45,13 @@ public: private: QHash> _laserPointers; - QReadWriteLock _lock; QHash> _laserPointerLocks; + unsigned int _nextUID{ 1 }; // 0 is invalid + QReadWriteLock _addLock; + QQueue>> _laserPointersToAdd; + QReadWriteLock _removeLock; + QQueue _laserPointersToRemove; + QReadWriteLock _containsLock; }; diff --git a/interface/src/raypick/LaserPointerScriptingInterface.cpp b/interface/src/raypick/LaserPointerScriptingInterface.cpp index 1cc3a967c4..e1dc1f35c1 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.cpp +++ b/interface/src/raypick/LaserPointerScriptingInterface.cpp @@ -20,16 +20,6 @@ uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& properties) { QVariantMap propertyMap = properties.toMap(); - uint16_t filter = 0; - if (propertyMap["filter"].isValid()) { - filter = propertyMap["filter"].toUInt(); - } - - float maxDistance = 0.0f; - if (propertyMap["maxDistance"].isValid()) { - maxDistance = propertyMap["maxDistance"].toFloat(); - } - bool faceAvatar = false; if (propertyMap["faceAvatar"].isValid()) { faceAvatar = propertyMap["faceAvatar"].toBool(); @@ -64,37 +54,7 @@ uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& prop } } - if (propertyMap["joint"].isValid()) { - QString jointName = propertyMap["joint"].toString(); - - if (jointName != "Mouse") { - // x = upward, y = forward, z = lateral - glm::vec3 posOffset = Vectors::ZERO; - if (propertyMap["posOffset"].isValid()) { - posOffset = vec3FromVariant(propertyMap["posOffset"]); - } - - glm::vec3 dirOffset = Vectors::UP; - if (propertyMap["dirOffset"].isValid()) { - dirOffset = vec3FromVariant(propertyMap["dirOffset"]); - } - - return DependencyManager::get()->createLaserPointer(jointName, posOffset, dirOffset, filter, maxDistance, renderStates, faceAvatar, centerEndY, lockEnd, enabled); - } else { - return DependencyManager::get()->createLaserPointer(filter, maxDistance, renderStates, faceAvatar, centerEndY, lockEnd, enabled); - } - } else if (propertyMap["position"].isValid()) { - glm::vec3 position = vec3FromVariant(propertyMap["position"]); - - glm::vec3 direction = -Vectors::UP; - if (propertyMap["direction"].isValid()) { - direction = vec3FromVariant(propertyMap["direction"]); - } - - return DependencyManager::get()->createLaserPointer(position, direction, filter, maxDistance, renderStates, faceAvatar, centerEndY, lockEnd, enabled); - } - - return 0; + return DependencyManager::get()->createLaserPointer(propertyMap, renderStates, faceAvatar, centerEndY, lockEnd, enabled); } void LaserPointerScriptingInterface::editRenderState(unsigned int uid, const QString& renderState, const QVariant& properties) { diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp index b7952bfef3..1ccc27f76d 100644 --- a/interface/src/raypick/RayPickManager.cpp +++ b/interface/src/raypick/RayPickManager.cpp @@ -19,6 +19,10 @@ #include "scripting/HMDScriptingInterface.h" #include "DependencyManager.h" +#include "JointRayPick.h" +#include "StaticRayPick.h" +#include "MouseRayPick.h" + bool RayPickManager::checkAndCompareCachedResults(QPair& ray, RayPickCache& cache, RayPickResult& res, unsigned int mask) { if (cache.contains(ray) && cache[ray].contains(mask)) { if (cache[ray][mask].distance < res.distance) { @@ -137,10 +141,59 @@ void RayPickManager::update() { } } -unsigned int RayPickManager::addRayPick(std::shared_ptr rayPick) { - QWriteLocker lock(&_addLock); - _rayPicksToAdd.enqueue(QPair>(_nextUID, rayPick)); - return _nextUID++; +unsigned int RayPickManager::createRayPick(const QVariantMap& rayProps) { + bool enabled = false; + if (rayProps["enabled"].isValid()) { + enabled = rayProps["enabled"].toBool(); + } + + uint16_t filter = 0; + if (rayProps["filter"].isValid()) { + filter = rayProps["filter"].toUInt(); + } + + float maxDistance = 0.0f; + if (rayProps["maxDistance"].isValid()) { + maxDistance = rayProps["maxDistance"].toFloat(); + } + + if (rayProps["joint"].isValid()) { + QString jointName = rayProps["joint"].toString(); + + if (jointName != "Mouse") { + // x = upward, y = forward, z = lateral + glm::vec3 posOffset = Vectors::ZERO; + if (rayProps["posOffset"].isValid()) { + posOffset = vec3FromVariant(rayProps["posOffset"]); + } + + glm::vec3 dirOffset = Vectors::UP; + if (rayProps["dirOffset"].isValid()) { + dirOffset = vec3FromVariant(rayProps["dirOffset"]); + } + + QWriteLocker lock(&_addLock); + _rayPicksToAdd.enqueue(QPair>(_nextUID, std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled))); + return _nextUID++; + } else { + QWriteLocker lock(&_addLock); + _rayPicksToAdd.enqueue(QPair>(_nextUID, std::make_shared(filter, maxDistance, enabled))); + return _nextUID++; + } + } else if (rayProps["position"].isValid()) { + glm::vec3 position = vec3FromVariant(rayProps["position"]); + + glm::vec3 direction = -Vectors::UP; + if (rayProps["direction"].isValid()) { + direction = vec3FromVariant(rayProps["direction"]); + } + + QWriteLocker lock(&_addLock); + _rayPicksToAdd.enqueue(QPair>(_nextUID, std::make_shared(position, direction, filter, maxDistance, enabled))); + return _nextUID++; + } + + return 0; } void RayPickManager::removeRayPick(const unsigned int uid) { diff --git a/interface/src/raypick/RayPickManager.h b/interface/src/raypick/RayPickManager.h index 400098587e..47d982494f 100644 --- a/interface/src/raypick/RayPickManager.h +++ b/interface/src/raypick/RayPickManager.h @@ -58,19 +58,21 @@ class RayPickManager : public QObject, public Dependency { public: void update(); - unsigned int addRayPick(std::shared_ptr rayPick); - void removeRayPick(const unsigned int uid); - void enableRayPick(const unsigned int uid); - void disableRayPick(const unsigned int uid); const PickRay getPickRay(const unsigned int uid); - const RayPickResult getPrevRayPickResult(const unsigned int uid); - void setIgnoreEntities(unsigned int uid, const QScriptValue& ignoreEntities); - void setIncludeEntities(unsigned int uid, const QScriptValue& includeEntities); - void setIgnoreOverlays(unsigned int uid, const QScriptValue& ignoreOverlays); - void setIncludeOverlays(unsigned int uid, const QScriptValue& includeOverlays); - void setIgnoreAvatars(unsigned int uid, const QScriptValue& ignoreAvatars); - void setIncludeAvatars(unsigned int uid, const QScriptValue& includeAvatars); +public slots: + Q_INVOKABLE unsigned int createRayPick(const QVariantMap& rayProps); + Q_INVOKABLE void removeRayPick(const unsigned int uid); + Q_INVOKABLE void enableRayPick(const unsigned int uid); + Q_INVOKABLE void disableRayPick(const unsigned int uid); + Q_INVOKABLE const RayPickResult getPrevRayPickResult(const unsigned int uid); + + Q_INVOKABLE void setIgnoreEntities(unsigned int uid, const QScriptValue& ignoreEntities); + Q_INVOKABLE void setIncludeEntities(unsigned int uid, const QScriptValue& includeEntities); + Q_INVOKABLE void setIgnoreOverlays(unsigned int uid, const QScriptValue& ignoreOverlays); + Q_INVOKABLE void setIncludeOverlays(unsigned int uid, const QScriptValue& includeOverlays); + Q_INVOKABLE void setIgnoreAvatars(unsigned int uid, const QScriptValue& ignoreAvatars); + Q_INVOKABLE void setIncludeAvatars(unsigned int uid, const QScriptValue& includeAvatars); private: QHash> _rayPicks; diff --git a/scripts/system/controllers/grab.js b/scripts/system/controllers/grab.js index 411d5f6e41..a3473df7e3 100644 --- a/scripts/system/controllers/grab.js +++ b/scripts/system/controllers/grab.js @@ -257,12 +257,12 @@ function Grabber() { this.liftKey = false; // SHIFT this.rotateKey = false; // CONTROL - this.mouseRayOverlays = LaserPointers.createLaserPointer({ + this.mouseRayOverlays = RayPick.createRayPick({ joint: "Mouse", filter: RayPick.PICK_OVERLAYS, enabled: true }); - LaserPointers.setIncludeOverlays(this.mouseRayOverlays, [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID]); + RayPick.setIncludeOverlays(this.mouseRayOverlays, [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID]); this.mouseRayEntities = LaserPointers.createLaserPointer({ joint: "Mouse", filter: RayPick.PICK_ENTITIES, @@ -318,7 +318,7 @@ Grabber.prototype.pressEvent = function(event) { return; } - var overlayResult = LaserPointers.getPrevRayPickResult(this.mouseRayOverlays); + var overlayResult = RayPick.getPrevRayPickResult(this.mouseRayOverlays); if (overlayResult.type != RayPick.INTERSECTED_NONE) { return; } @@ -572,7 +572,7 @@ Grabber.prototype.keyPressEvent = function(event) { Grabber.prototype.cleanup = function() { LaserPointers.removeLaserPointer(this.mouseRayEntities); - LaserPointers.removeLaserPointer(this.mouseRayOverlays); + RayPick.removeRayPick(this.mouseRayOverlays); }; var grabber = new Grabber(); From 5de0970365c06bc06217c850825cb58b72421bd3 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 20 Jul 2017 14:17:52 -0700 Subject: [PATCH 22/42] put back ignoredEntities functionality in teleport --- scripts/system/controllers/teleport.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/scripts/system/controllers/teleport.js b/scripts/system/controllers/teleport.js index eaeb7767ac..fc22d21089 100644 --- a/scripts/system/controllers/teleport.js +++ b/scripts/system/controllers/teleport.js @@ -516,6 +516,15 @@ function cleanup() { } Script.scriptEnding.connect(cleanup); +var setIgnoredEntities = function () { + LaserPointers.setIgnoredEntities(teleporter.teleportRayRightVisible, ignoredEntities); + LaserPointers.setIgnoredEntities(teleporter.teleportRayRightInvisible, ignoredEntities); + LaserPointers.setIgnoredEntities(teleporter.teleportRayLeftVisible, ignoredEntities); + LaserPointers.setIgnoredEntities(teleporter.teleportRayLeftInvisible, ignoredEntities); + LaserPointers.setIgnoredEntities(teleporter.teleportRayHeadVisible, ignoredEntities); + LaserPointers.setIgnoredEntities(teleporter.teleportRayHeadInvisible, ignoredEntities); +} + var isDisabled = false; var handleTeleportMessages = function(channel, message, sender) { if (sender === MyAvatar.sessionUUID) { @@ -533,13 +542,13 @@ var handleTeleportMessages = function(channel, message, sender) { isDisabled = false; } } else if (channel === 'Hifi-Teleport-Ignore-Add' && !Uuid.isNull(message) && ignoredEntities.indexOf(message) === -1) { - // TODO: - // add ability to ignore entities to LaserPointers ignoredEntities.push(message); + setIgnoredEntities(); } else if (channel === 'Hifi-Teleport-Ignore-Remove' && !Uuid.isNull(message)) { var removeIndex = ignoredEntities.indexOf(message); if (removeIndex > -1) { ignoredEntities.splice(removeIndex, 1); + setIgnoredEntities(); } } } From ee02a0bff4ceda83644d3dc4026b7347178ddef0 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 24 Jul 2017 12:44:54 -0700 Subject: [PATCH 23/42] fix build error --- interface/src/raypick/LaserPointer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index 909e61e00c..359295fd6a 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -49,7 +49,7 @@ private: class LaserPointer { public: - LaserPointer::LaserPointer(const QVariantMap& rayProps, const QHash& renderStates, const bool faceAvatar, const bool centerEndY, + LaserPointer(const QVariantMap& rayProps, const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled); ~LaserPointer(); From 3c8b964cc9d10cd4e50c9672a0941118303dd497 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 24 Jul 2017 18:16:40 -0700 Subject: [PATCH 24/42] replace setHandLasers with drawHUDLayer overlay property --- interface/resources/shaders/hmd_ui.frag | 27 ++ .../shaders/{hmd_ui_glow.vert => hmd_ui.vert} | 9 +- interface/resources/shaders/hmd_ui_glow.frag | 86 ------- interface/src/Application.cpp | 16 +- .../src/scripting/HMDScriptingInterface.cpp | 60 ++--- .../src/scripting/HMDScriptingInterface.h | 12 +- interface/src/ui/overlays/Circle3DOverlay.cpp | 2 +- interface/src/ui/overlays/Cube3DOverlay.cpp | 2 +- interface/src/ui/overlays/Image3DOverlay.cpp | 2 +- interface/src/ui/overlays/Overlay.cpp | 7 + interface/src/ui/overlays/Overlay.h | 3 + interface/src/ui/overlays/Overlays.cpp | 45 +++- interface/src/ui/overlays/Overlays.h | 5 + interface/src/ui/overlays/Shape3DOverlay.cpp | 2 +- interface/src/ui/overlays/Sphere3DOverlay.cpp | 2 +- .../src/display-plugins/CompositorHelper.cpp | 5 +- .../src/display-plugins/CompositorHelper.h | 3 - .../display-plugins/OpenGLDisplayPlugin.cpp | 9 + .../hmd/DebugHmdDisplayPlugin.cpp | 9 - .../display-plugins/hmd/HmdDisplayPlugin.cpp | 230 +----------------- .../display-plugins/hmd/HmdDisplayPlugin.h | 40 --- libraries/gpu/src/gpu/Frame.h | 2 + libraries/plugins/src/plugins/DisplayPlugin.h | 18 -- .../oculus/src/OculusBaseDisplayPlugin.cpp | 2 - plugins/openvr/src/OpenVrDisplayPlugin.cpp | 3 - .../controllers/handControllerPointer.js | 169 ++++++++++--- 26 files changed, 275 insertions(+), 495 deletions(-) create mode 100644 interface/resources/shaders/hmd_ui.frag rename interface/resources/shaders/{hmd_ui_glow.vert => hmd_ui.vert} (76%) delete mode 100644 interface/resources/shaders/hmd_ui_glow.frag diff --git a/interface/resources/shaders/hmd_ui.frag b/interface/resources/shaders/hmd_ui.frag new file mode 100644 index 0000000000..af96169831 --- /dev/null +++ b/interface/resources/shaders/hmd_ui.frag @@ -0,0 +1,27 @@ +// +// Created by Bradley Austin Davis on 2016/07/11 +// Copyright 2013-2016 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 +// + +uniform sampler2D sampler; + +struct OverlayData { + mat4 mvp; + float alpha; +}; + +layout(std140) uniform overlayBuffer { + OverlayData overlay; +}; + +in vec2 vTexCoord; + +out vec4 FragColor; + +void main() { + FragColor = texture(sampler, vTexCoord); + FragColor.a *= overlay.alpha; +} \ No newline at end of file diff --git a/interface/resources/shaders/hmd_ui_glow.vert b/interface/resources/shaders/hmd_ui.vert similarity index 76% rename from interface/resources/shaders/hmd_ui_glow.vert rename to interface/resources/shaders/hmd_ui.vert index 71089d8608..41b9b3666f 100644 --- a/interface/resources/shaders/hmd_ui_glow.vert +++ b/interface/resources/shaders/hmd_ui.vert @@ -8,12 +8,7 @@ struct OverlayData { mat4 mvp; - vec4 glowPoints; - vec4 glowColors[2]; - vec4 resolutionRadiusAlpha; - - vec4 extraGlowColor; - vec2 extraGlowPoint; + float alpha; }; layout(std140) uniform overlayBuffer { @@ -25,11 +20,9 @@ mat4 mvp = overlay.mvp; layout(location = 0) in vec3 Position; layout(location = 3) in vec2 TexCoord; -out vec3 vPosition; out vec2 vTexCoord; void main() { gl_Position = mvp * vec4(Position, 1); vTexCoord = TexCoord; - vPosition = Position; } diff --git a/interface/resources/shaders/hmd_ui_glow.frag b/interface/resources/shaders/hmd_ui_glow.frag deleted file mode 100644 index 5dda76e89d..0000000000 --- a/interface/resources/shaders/hmd_ui_glow.frag +++ /dev/null @@ -1,86 +0,0 @@ -// -// Created by Bradley Austin Davis on 2016/07/11 -// Copyright 2013-2016 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 -// - -uniform sampler2D sampler; - -struct OverlayData { - mat4 mvp; - vec4 glowPoints; - vec4 glowColors[2]; - vec4 resolutionRadiusAlpha; - - vec4 extraGlowColor; - vec2 extraGlowPoint; -}; - -layout(std140) uniform overlayBuffer { - OverlayData overlay; -}; - -vec2 resolution = overlay.resolutionRadiusAlpha.xy; -float radius = overlay.resolutionRadiusAlpha.z; -float alpha = overlay.resolutionRadiusAlpha.w; -vec4 glowPoints = overlay.glowPoints; -vec4 glowColors[2] = overlay.glowColors; - -vec2 extraGlowPoint = overlay.extraGlowPoint; -vec4 extraGlowColor = overlay.extraGlowColor; - -in vec3 vPosition; -in vec2 vTexCoord; - -out vec4 FragColor; - -float easeInOutCubic(float f) { - const float d = 1.0; - const float b = 0.0; - const float c = 1.0; - float t = f; - if ((t /= d / 2.0) < 1.0) return c / 2.0 * t * t * t + b; - return c / 2.0 * ((t -= 2.0) * t * t + 2.0) + b; -} - -void main() { - FragColor = texture(sampler, vTexCoord); - - vec2 aspect = resolution; - aspect /= resolution.x; - - float glowIntensity = 0.0; - float dist1 = distance(vTexCoord * aspect, glowPoints.xy * aspect); - float dist2 = distance(vTexCoord * aspect, glowPoints.zw * aspect); - float dist3 = distance(vTexCoord * aspect, extraGlowPoint * aspect); - float distX = min(dist1, dist2); - float dist = min(distX, dist3); - vec3 glowColor = glowColors[0].rgb; - if (dist2 < dist1) { - glowColor = glowColors[1].rgb; - } - if (dist3 < dist2) { - glowColor = extraGlowColor.rgb; - } - - if (dist <= radius) { - glowIntensity = 1.0 - (dist / radius); - glowColor.rgb = pow(glowColor, vec3(1.0 - glowIntensity)); - glowIntensity = easeInOutCubic(glowIntensity); - glowIntensity = pow(glowIntensity, 0.5); - } - - if (alpha <= 0.0) { - if (glowIntensity <= 0.0) { - discard; - } - - FragColor = vec4(glowColor, glowIntensity); - return; - } - - FragColor.rgb = mix(FragColor.rgb, glowColor.rgb, glowIntensity); - FragColor.a *= alpha; -} \ No newline at end of file diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 69835caff0..7a42312f6c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2378,6 +2378,7 @@ void Application::paintGL() { finalFramebuffer = framebufferCache->getFramebuffer(); } + mat4 eyeProjections[2]; { PROFILE_RANGE(render, "/mainRender"); PerformanceTimer perfTimer("mainRender"); @@ -2399,7 +2400,6 @@ void Application::paintGL() { _myCamera.setProjection(displayPlugin->getCullingProjection(_myCamera.getProjection())); renderArgs._context->enableStereo(true); mat4 eyeOffsets[2]; - mat4 eyeProjections[2]; auto baseProjection = renderArgs.getViewFrustum().getProjection(); auto hmdInterface = DependencyManager::get(); float IPDScale = hmdInterface->getIPDScale(); @@ -2430,6 +2430,19 @@ void Application::paintGL() { displaySide(&renderArgs, _myCamera); } + gpu::Batch postCompositeBatch; + { + PROFILE_RANGE(render, "/postComposite"); + PerformanceTimer perfTimer("postComposite"); + renderArgs._batch = &postCompositeBatch; + renderArgs._batch->setViewportTransform(ivec4(0, 0, finalFramebufferSize.width(), finalFramebufferSize.height())); + renderArgs._batch->setViewTransform(renderArgs.getViewFrustum().getView()); + for_each_eye([&](Eye eye) { + renderArgs._batch->setProjectionTransform(eyeProjections[eye]); + _overlays.render3DHUDOverlays(&renderArgs); + }); + } + auto frame = _gpuContext->endFrame(); frame->frameIndex = _frameCount; frame->framebuffer = finalFramebuffer; @@ -2437,6 +2450,7 @@ void Application::paintGL() { DependencyManager::get()->releaseFramebuffer(framebuffer); }; frame->overlay = _applicationOverlay.getOverlayTexture(); + frame->postCompositeBatch = postCompositeBatch; // deliver final scene rendering commands to the display plugin { PROFILE_RANGE(render, "/pluginOutput"); diff --git a/interface/src/scripting/HMDScriptingInterface.cpp b/interface/src/scripting/HMDScriptingInterface.cpp index 35f2e2aa86..af3c7c3d67 100644 --- a/interface/src/scripting/HMDScriptingInterface.cpp +++ b/interface/src/scripting/HMDScriptingInterface.cpp @@ -82,6 +82,22 @@ bool HMDScriptingInterface::shouldShowHandControllers() const { return _showHandControllersCount > 0; } +void HMDScriptingInterface::activateHMDHandMouse() { + QWriteLocker lock(&_hmdHandMouseLock); + auto offscreenUi = DependencyManager::get(); + offscreenUi->getDesktop()->setProperty("hmdHandMouseActive", true); + _hmdHandMouseCount++; +} + +void HMDScriptingInterface::deactivateHMDHandMouse() { + QWriteLocker lock(&_hmdHandMouseLock); + _hmdHandMouseCount = std::max(--_hmdHandMouseCount, 0); + if (_hmdHandMouseCount == 0) { + auto offscreenUi = DependencyManager::get(); + offscreenUi->getDesktop()->setProperty("hmdHandMouseActive", false); + } +} + void HMDScriptingInterface::closeTablet() { _showTablet = false; } @@ -153,50 +169,6 @@ QString HMDScriptingInterface::preferredAudioOutput() const { return qApp->getActiveDisplayPlugin()->getPreferredAudioOutDevice(); } -bool HMDScriptingInterface::setHandLasers(int hands, bool enabled, const glm::vec4& color, const glm::vec3& direction) { - if (QThread::currentThread() != thread()) { - bool result; - BLOCKING_INVOKE_METHOD(this, "setHandLasers", Q_RETURN_ARG(bool, result), - Q_ARG(int, hands), Q_ARG(bool, enabled), Q_ARG(glm::vec4, color), Q_ARG(glm::vec3, direction)); - return result; - } - - auto offscreenUi = DependencyManager::get(); - offscreenUi->getDesktop()->setProperty("hmdHandMouseActive", enabled); - return qApp->getActiveDisplayPlugin()->setHandLaser(hands, - enabled ? DisplayPlugin::HandLaserMode::Overlay : DisplayPlugin::HandLaserMode::None, - color, direction); -} - -bool HMDScriptingInterface::setExtraLaser(const glm::vec3& worldStart, bool enabled, const glm::vec4& color, const glm::vec3& direction) { - if (QThread::currentThread() != thread()) { - bool result; - BLOCKING_INVOKE_METHOD(this, "setExtraLaser", Q_RETURN_ARG(bool, result), - Q_ARG(glm::vec3, worldStart), Q_ARG(bool, enabled), Q_ARG(glm::vec4, color), Q_ARG(glm::vec3, direction)); - return result; - } - - auto offscreenUi = DependencyManager::get(); - offscreenUi->getDesktop()->setProperty("hmdHandMouseActive", enabled); - - auto myAvatar = DependencyManager::get()->getMyAvatar(); - auto sensorToWorld = myAvatar->getSensorToWorldMatrix(); - auto worldToSensor = glm::inverse(sensorToWorld); - auto sensorStart = ::transformPoint(worldToSensor, worldStart); - auto sensorDirection = ::transformVectorFast(worldToSensor, direction); - - return qApp->getActiveDisplayPlugin()->setExtraLaser(enabled ? DisplayPlugin::HandLaserMode::Overlay : DisplayPlugin::HandLaserMode::None, - color, sensorStart, sensorDirection); -} - -void HMDScriptingInterface::disableExtraLaser() { - setExtraLaser(vec3(0), false, vec4(0), vec3(0)); -} - -void HMDScriptingInterface::disableHandLasers(int hands) { - setHandLasers(hands, false, vec4(0), vec3(0)); -} - bool HMDScriptingInterface::suppressKeyboard() { return qApp->getActiveDisplayPlugin()->suppressKeyboard(); } diff --git a/interface/src/scripting/HMDScriptingInterface.h b/interface/src/scripting/HMDScriptingInterface.h index 3ed7db0232..2eefe6ea22 100644 --- a/interface/src/scripting/HMDScriptingInterface.h +++ b/interface/src/scripting/HMDScriptingInterface.h @@ -22,6 +22,7 @@ class QScriptEngine; #include #include +#include class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Dependency { Q_OBJECT @@ -51,12 +52,8 @@ public: Q_INVOKABLE void requestHideHandControllers(); Q_INVOKABLE bool shouldShowHandControllers() const; - Q_INVOKABLE bool setHandLasers(int hands, bool enabled, const glm::vec4& color, const glm::vec3& direction); - Q_INVOKABLE void disableHandLasers(int hands); - - Q_INVOKABLE bool setExtraLaser(const glm::vec3& worldStart, bool enabled, const glm::vec4& color, const glm::vec3& direction); - Q_INVOKABLE void disableExtraLaser(); - + Q_INVOKABLE void activateHMDHandMouse(); + Q_INVOKABLE void deactivateHMDHandMouse(); /// Suppress the activation of any on-screen keyboard so that a script operation will /// not be interrupted by a keyboard popup @@ -119,6 +116,9 @@ private: bool getHUDLookAtPosition3D(glm::vec3& result) const; glm::mat4 getWorldHMDMatrix() const; std::atomic _showHandControllersCount { 0 }; + + QReadWriteLock _hmdHandMouseLock; + int _hmdHandMouseCount; }; #endif // hifi_HMDScriptingInterface_h diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp index 827417a912..52a3d7a929 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -267,7 +267,7 @@ const render::ShapeKey Circle3DOverlay::getShapeKey() { if (getAlpha() != 1.0f) { builder.withTranslucent(); } - if (!getIsSolid()) { + if (!getIsSolid() || shouldDrawHUDLayer()) { builder.withUnlit().withDepthBias(); } return builder.build(); diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index a353545245..31cbe5e822 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -120,7 +120,7 @@ const render::ShapeKey Cube3DOverlay::getShapeKey() { if (getAlpha() != 1.0f) { builder.withTranslucent(); } - if (!getIsSolid()) { + if (!getIsSolid() || shouldDrawHUDLayer()) { builder.withUnlit().withDepthBias(); } return builder.build(); diff --git a/interface/src/ui/overlays/Image3DOverlay.cpp b/interface/src/ui/overlays/Image3DOverlay.cpp index 7dfee2c491..82417db83a 100644 --- a/interface/src/ui/overlays/Image3DOverlay.cpp +++ b/interface/src/ui/overlays/Image3DOverlay.cpp @@ -123,7 +123,7 @@ void Image3DOverlay::render(RenderArgs* args) { const render::ShapeKey Image3DOverlay::getShapeKey() { auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias(); - if (_emissive) { + if (_emissive || shouldDrawHUDLayer()) { builder.withUnlit(); } if (getAlpha() != 1.0f) { diff --git a/interface/src/ui/overlays/Overlay.cpp b/interface/src/ui/overlays/Overlay.cpp index b650da3522..868cdf110b 100644 --- a/interface/src/ui/overlays/Overlay.cpp +++ b/interface/src/ui/overlays/Overlay.cpp @@ -29,6 +29,7 @@ Overlay::Overlay() : _alphaPulse(0.0f), _colorPulse(0.0f), _color(DEFAULT_OVERLAY_COLOR), + _drawHUDLayer(false), _visible(true), _anchor(NO_ANCHOR) { @@ -47,6 +48,7 @@ Overlay::Overlay(const Overlay* overlay) : _alphaPulse(overlay->_alphaPulse), _colorPulse(overlay->_colorPulse), _color(overlay->_color), + _drawHUDLayer(overlay->_drawHUDLayer), _visible(overlay->_visible), _anchor(overlay->_anchor) { @@ -86,6 +88,11 @@ void Overlay::setProperties(const QVariantMap& properties) { setColorPulse(properties["colorPulse"].toFloat()); } + if (properties["drawHUDLayer"].isValid()) { + bool drawHUDLayer = properties["drawHUDLayer"].toBool(); + setDrawHUDLayer(drawHUDLayer); + } + if (properties["visible"].isValid()) { bool visible = properties["visible"].toBool(); setVisible(visible); diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index 494c287676..0bb0d39d7a 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -58,6 +58,7 @@ public: virtual bool is3D() const = 0; bool isLoaded() { return _isLoaded; } bool getVisible() const { return _visible; } + bool shouldDrawHUDLayer() const { return _drawHUDLayer; } xColor getColor(); float getAlpha(); Anchor getAnchor() const { return _anchor; } @@ -72,6 +73,7 @@ public: // setters void setVisible(bool visible) { _visible = visible; } + void setDrawHUDLayer(bool drawHUDLayer) { _drawHUDLayer = drawHUDLayer; } void setColor(const xColor& color) { _color = color; } void setAlpha(float alpha) { _alpha = alpha; } void setAnchor(Anchor anchor) { _anchor = anchor; } @@ -114,6 +116,7 @@ protected: xColor _color; bool _visible; // should the overlay be drawn at all + bool _drawHUDLayer; // should the overlay be drawn on the HUD layer Anchor _anchor; unsigned int _stackOrder { 0 }; diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 72682fcb8c..067bfac0cb 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -37,20 +37,29 @@ #include "Web3DOverlay.h" #include +#include "render/ShapePipeline.h" + Q_LOGGING_CATEGORY(trace_render_overlays, "trace.render.overlays") +extern void initOverlay3DPipelines(render::ShapePlumber& plumber); + void Overlays::cleanupAllOverlays() { QMap overlaysHUD; + QMap overlays3DHUD; QMap overlaysWorld; { QMutexLocker locker(&_mutex); overlaysHUD.swap(_overlaysHUD); + overlays3DHUD.swap(_overlays3DHUD); overlaysWorld.swap(_overlaysWorld); } foreach(Overlay::Pointer overlay, overlaysHUD) { _overlaysToDelete.push_back(overlay); } + foreach(Overlay::Pointer overlay, overlays3DHUD) { + _overlaysToDelete.push_back(overlay); + } foreach(Overlay::Pointer overlay, overlaysWorld) { _overlaysToDelete.push_back(overlay); } @@ -64,6 +73,8 @@ void Overlays::init() { #if OVERLAY_PANELS _scriptEngine = new QScriptEngine(); #endif + _shapePlumber = std::make_shared(); + initOverlay3DPipelines(*_shapePlumber); } void Overlays::update(float deltatime) { @@ -72,6 +83,9 @@ void Overlays::update(float deltatime) { foreach(const auto& thisOverlay, _overlaysHUD) { thisOverlay->update(deltatime); } + foreach(const auto& thisOverlay, _overlays3DHUD) { + thisOverlay->update(deltatime); + } foreach(const auto& thisOverlay, _overlaysWorld) { thisOverlay->update(deltatime); } @@ -128,6 +142,23 @@ void Overlays::renderHUD(RenderArgs* renderArgs) { } } +void Overlays::render3DHUDOverlays(RenderArgs* renderArgs) { + PROFILE_RANGE(render_overlays, __FUNCTION__); + gpu::Batch& batch = *renderArgs->_batch; + + auto textureCache = DependencyManager::get(); + + QMutexLocker lock(&_mutex); + foreach(Overlay::Pointer thisOverlay, _overlays3DHUD) { + // Reset necessary batch pipeline settings between overlays + batch.setResourceTexture(0, textureCache->getWhiteTexture()); // FIXME - do we really need to do this?? + batch.setModelTransform(Transform()); + + renderArgs->_shapePipeline = _shapePlumber->pickPipeline(renderArgs, thisOverlay->getShapeKey()); + thisOverlay->render(renderArgs); + } +} + void Overlays::disable() { _enabled = false; } @@ -142,8 +173,9 @@ Overlay::Pointer Overlays::getOverlay(OverlayID id) const { QMutexLocker locker(&_mutex); if (_overlaysHUD.contains(id)) { return _overlaysHUD[id]; - } - if (_overlaysWorld.contains(id)) { + } else if (_overlays3DHUD.contains(id)) { + return _overlays3DHUD[id]; + } else if (_overlaysWorld.contains(id)) { return _overlaysWorld[id]; } return nullptr; @@ -200,7 +232,7 @@ OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) { OverlayID thisID = OverlayID(QUuid::createUuid()); overlay->setOverlayID(thisID); overlay->setStackOrder(_stackOrder++); - if (overlay->is3D()) { + if (overlay->is3D() && !overlay->shouldDrawHUDLayer()) { { QMutexLocker locker(&_mutex); _overlaysWorld[thisID] = overlay; @@ -210,6 +242,9 @@ OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) { render::Transaction transaction; overlay->addToScene(overlay, scene, transaction); scene->enqueueTransaction(transaction); + } else if (overlay->is3D() && overlay->shouldDrawHUDLayer()) { + QMutexLocker locker(&_mutex); + _overlays3DHUD[thisID] = overlay; } else { QMutexLocker locker(&_mutex); _overlaysHUD[thisID] = overlay; @@ -294,6 +329,8 @@ void Overlays::deleteOverlay(OverlayID id) { QMutexLocker locker(&_mutex); if (_overlaysHUD.contains(id)) { overlayToDelete = _overlaysHUD.take(id); + } else if (_overlays3DHUD.contains(id)) { + overlayToDelete = _overlays3DHUD.take(id); } else if (_overlaysWorld.contains(id)) { overlayToDelete = _overlaysWorld.take(id); } else { @@ -702,7 +739,7 @@ bool Overlays::isAddedOverlay(OverlayID id) { } QMutexLocker locker(&_mutex); - return _overlaysHUD.contains(id) || _overlaysWorld.contains(id); + return _overlaysHUD.contains(id) || _overlays3DHUD.contains(id) || _overlaysWorld.contains(id); } void Overlays::sendMousePressOnOverlay(OverlayID overlayID, const PointerEvent& event) { diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 100f853a96..9efc003669 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -90,6 +90,7 @@ public: void init(); void update(float deltatime); void renderHUD(RenderArgs* renderArgs); + void render3DHUDOverlays(RenderArgs* renderArgs); void disable(); void enable(); @@ -325,7 +326,11 @@ private: mutable QMutex _mutex; QMap _overlaysHUD; + QMap _overlays3DHUD; QMap _overlaysWorld; + + render::ShapePlumberPointer _shapePlumber; + #if OVERLAY_PANELS QMap _panels; #endif diff --git a/interface/src/ui/overlays/Shape3DOverlay.cpp b/interface/src/ui/overlays/Shape3DOverlay.cpp index a6fcacc769..7126f7bde4 100644 --- a/interface/src/ui/overlays/Shape3DOverlay.cpp +++ b/interface/src/ui/overlays/Shape3DOverlay.cpp @@ -65,7 +65,7 @@ const render::ShapeKey Shape3DOverlay::getShapeKey() { if (getAlpha() != 1.0f) { builder.withTranslucent(); } - if (!getIsSolid()) { + if (!getIsSolid() || shouldDrawHUDLayer()) { builder.withUnlit().withDepthBias(); } return builder.build(); diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index 5bbf41eb94..ee3f9b9784 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -62,7 +62,7 @@ const render::ShapeKey Sphere3DOverlay::getShapeKey() { if (getAlpha() != 1.0f) { builder.withTranslucent(); } - if (!getIsSolid()) { + if (!getIsSolid() || shouldDrawHUDLayer()) { builder.withUnlit().withDepthBias(); } return builder.build(); diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp index 29b8aee08b..4dc8d3378c 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp @@ -349,10 +349,9 @@ bool CompositorHelper::calculateRayUICollisionPoint(const glm::vec3& position, c auto relativePosition = vec3(relativePosition4) / relativePosition4.w; auto relativeDirection = glm::inverse(glm::quat_cast(UITransform)) * direction; - float uiRadius = _hmdUIRadius; // * myAvatar->getUniformScale(); // FIXME - how do we want to handle avatar scale - + const float UI_RADIUS = 1.0f; // * myAvatar->getUniformScale(); // FIXME - how do we want to handle avatar scale float instersectionDistance; - if (raySphereIntersect(relativeDirection, relativePosition, uiRadius, &instersectionDistance)){ + if (raySphereIntersect(relativeDirection, relativePosition, UI_RADIUS, &instersectionDistance)){ result = position + glm::normalize(direction) * instersectionDistance; return true; } diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.h b/libraries/display-plugins/src/display-plugins/CompositorHelper.h index 5be2d68cf9..e6a32dcfb9 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.h +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.h @@ -111,8 +111,6 @@ public: void setDisplayPlugin(const DisplayPluginPointer& displayPlugin) { _currentDisplayPlugin = displayPlugin; } void setFrameInfo(uint32_t frame, const glm::mat4& camera) { _currentCamera = camera; } - float getHmdUiRadius() const { return _hmdUIRadius; } - signals: void allowMouseCaptureChanged(); void alphaChanged(); @@ -142,7 +140,6 @@ private: float _textureAspectRatio { VIRTUAL_UI_ASPECT_RATIO }; float _alpha { 1.0f }; - float _hmdUIRadius { 1.0f }; int _previousBorderWidth { -1 }; int _previousBorderHeight { -1 }; diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index e1259fc5fc..1c361ed1ca 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -641,6 +641,15 @@ void OpenGLDisplayPlugin::compositeLayers() { compositePointer(); } + { + PROFILE_RANGE_EX(render_detail, "compositeHUDOverlays", 0xff0077ff, (uint64_t)presentCount()) + render([&](gpu::Batch& batch) { + batch.enableStereo(false); + batch.setFramebuffer(_compositeFramebuffer); + }); + _gpuContext->executeBatch(_currentFrame->postCompositeBatch); + } + { PROFILE_RANGE_EX(render_detail, "compositeExtra", 0xff0077ff, (uint64_t)presentCount()) compositeExtra(); diff --git a/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.cpp index fd45398236..1e0e7e6c1f 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.cpp @@ -35,16 +35,7 @@ bool DebugHmdDisplayPlugin::beginFrameRender(uint32_t frameIndex) { //_currentRenderFrameInfo.presentPose = _currentRenderFrameInfo.renderPose; withNonPresentThreadLock([&] { - _uiModelTransform = DependencyManager::get()->getModelTransform(); _frameInfos[frameIndex] = _currentRenderFrameInfo; - - _handPoses[0] = glm::translate(mat4(), vec3(0.3f * cosf(secTimestampNow() * 3.0f), -0.3f * sinf(secTimestampNow() * 5.0f), 0.0f)); - _handLasers[0].color = vec4(1, 0, 0, 1); - _handLasers[0].mode = HandLaserMode::Overlay; - - _handPoses[1] = glm::translate(mat4(), vec3(0.3f * sinf(secTimestampNow() * 3.0f), -0.3f * cosf(secTimestampNow() * 5.0f), 0.0f)); - _handLasers[1].color = vec4(0, 1, 1, 1); - _handLasers[1].mode = HandLaserMode::Overlay; }); return Parent::beginFrameRender(frameIndex); } diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index b183850e7f..fe109e7bc9 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -32,9 +32,6 @@ #include "../Logging.h" #include "../CompositorHelper.h" -#include <../render-utils/shaders/render-utils/glowLine_vert.h> -#include <../render-utils/shaders/render-utils/glowLine_frag.h> - static const QString MONO_PREVIEW = "Mono Preview"; static const QString DISABLE_PREVIEW = "Disable Preview"; @@ -123,26 +120,6 @@ static const int32_t LINE_DATA_SLOT = 1; void HmdDisplayPlugin::customizeContext() { Parent::customizeContext(); _overlayRenderer.build(); - - { - auto state = std::make_shared(); - auto VS = gpu::Shader::createVertex(std::string(glowLine_vert)); - auto PS = gpu::Shader::createPixel(std::string(glowLine_frag)); - auto program = gpu::Shader::createProgram(VS, PS); - state->setCullMode(gpu::State::CULL_NONE); - state->setDepthTest(true, false, gpu::LESS_EQUAL); - state->setBlendFunction(true, - gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, - gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - - gpu::Shader::BindingSet bindings; - bindings.insert({ "lineData", LINE_DATA_SLOT });; - gpu::Shader::makeProgram(*program, bindings); - _glowLinePipeline = gpu::Pipeline::create(program, state); - _handLaserUniforms = std::array{ { std::make_shared(), std::make_shared() } }; - _extraLaserUniforms = std::make_shared(); - }; - } void HmdDisplayPlugin::uncustomizeContext() { @@ -157,10 +134,6 @@ void HmdDisplayPlugin::uncustomizeContext() { }); _overlayRenderer = OverlayRenderer(); _previewTexture.reset(); - _handLaserUniforms[0].reset(); - _handLaserUniforms[1].reset(); - _extraLaserUniforms.reset(); - _glowLinePipeline.reset(); Parent::uncustomizeContext(); } @@ -383,132 +356,13 @@ void HmdDisplayPlugin::updateFrameData() { getGLBackend()->setCameraCorrection(correction); } - withPresentThreadLock([&] { - _presentHandLasers = _handLasers; - _presentHandPoses = _handPoses; - _presentUiModelTransform = _uiModelTransform; - - _presentExtraLaser = _extraLaser; - _presentExtraLaserStart = _extraLaserStart; - }); - auto compositorHelper = DependencyManager::get(); glm::mat4 modelMat = compositorHelper->getModelTransform().getMatrix(); - static const float OUT_OF_BOUNDS = -1; - std::array handGlowPoints { { vec2(OUT_OF_BOUNDS), vec2(OUT_OF_BOUNDS) } }; - vec2 extraGlowPoint(OUT_OF_BOUNDS); - - float uiRadius = compositorHelper->getHmdUiRadius(); - - // compute the glow point interesections - for (size_t i = 0; i < NUMBER_OF_HANDS; ++i) { - if (_presentHandPoses[i] == IDENTITY_MATRIX) { - continue; - } - const auto& handLaser = _presentHandLasers[i]; - if (!handLaser.valid()) { - continue; - } - - const vec3& laserDirection = handLaser.direction; - mat4 model = _presentHandPoses[i]; - vec3 castStart = vec3(model[3]); - vec3 castDirection = glm::quat_cast(model) * laserDirection; - - // this offset needs to match GRAB_POINT_SPHERE_OFFSET in scripts/system/libraries/controllers.js:19 - static const vec3 GRAB_POINT_SPHERE_OFFSET(0.04f, 0.13f, 0.039f); // x = upward, y = forward, z = lateral - - // swizzle grab point so that (x = upward, y = lateral, z = forward) - vec3 grabPointOffset = glm::vec3(GRAB_POINT_SPHERE_OFFSET.x, GRAB_POINT_SPHERE_OFFSET.z, -GRAB_POINT_SPHERE_OFFSET.y); - if (i == 0) { - grabPointOffset.x *= -1.0f; // this changes between left and right hands - } - castStart += glm::quat_cast(model) * grabPointOffset; - - // Find the intersection of the laser with he UI and use it to scale the model matrix - float distance; - if (!glm::intersectRaySphere(castStart, castDirection, - _presentUiModelTransform.getTranslation(), uiRadius * uiRadius, distance)) { - continue; - } - - _presentHandLaserPoints[i].first = castStart; - _presentHandLaserPoints[i].second = _presentHandLaserPoints[i].first + (castDirection * distance); - - vec3 intersectionPosition = castStart + (castDirection * distance) - _presentUiModelTransform.getTranslation(); - intersectionPosition = glm::inverse(_presentUiModelTransform.getRotation()) * intersectionPosition; - - // Take the interesection normal and convert it to a texture coordinate - vec2 yawPitch; - { - vec2 xdir = glm::normalize(vec2(intersectionPosition.x, -intersectionPosition.z)); - yawPitch.x = glm::atan(xdir.x, xdir.y); - yawPitch.y = (acosf(intersectionPosition.y) * -1.0f) + (float)M_PI_2; - } - vec2 halfFov = CompositorHelper::VIRTUAL_UI_TARGET_FOV / 2.0f; - - // Are we out of range - if (glm::any(glm::greaterThan(glm::abs(yawPitch), halfFov))) { - continue; - } - - yawPitch /= CompositorHelper::VIRTUAL_UI_TARGET_FOV; - yawPitch += 0.5f; - handGlowPoints[i] = yawPitch; - } - - // compute the glow point interesections - if (_presentExtraLaser.valid()) { - const vec3& laserDirection = _presentExtraLaser.direction; - vec3 castStart = _presentExtraLaserStart; - vec3 castDirection = laserDirection; - - // Find the intersection of the laser with he UI and use it to scale the model matrix - float distance; - if (glm::intersectRaySphere(castStart, castDirection, - _presentUiModelTransform.getTranslation(), uiRadius * uiRadius, distance)) { - - - _presentExtraLaserPoints.first = castStart; - _presentExtraLaserPoints.second = _presentExtraLaserPoints.first + (castDirection * distance); - - vec3 intersectionPosition = castStart + (castDirection * distance) - _presentUiModelTransform.getTranslation(); - intersectionPosition = glm::inverse(_presentUiModelTransform.getRotation()) * intersectionPosition; - - // Take the interesection normal and convert it to a texture coordinate - vec2 yawPitch; - { - vec2 xdir = glm::normalize(vec2(intersectionPosition.x, -intersectionPosition.z)); - yawPitch.x = glm::atan(xdir.x, xdir.y); - yawPitch.y = (acosf(intersectionPosition.y) * -1.0f) + (float)M_PI_2; - } - vec2 halfFov = CompositorHelper::VIRTUAL_UI_TARGET_FOV / 2.0f; - - // Are we out of range - if (!glm::any(glm::greaterThan(glm::abs(yawPitch), halfFov))) { - yawPitch /= CompositorHelper::VIRTUAL_UI_TARGET_FOV; - yawPitch += 0.5f; - extraGlowPoint = yawPitch; - } - } - } - for_each_eye([&](Eye eye) { auto modelView = glm::inverse(_currentPresentFrameInfo.presentPose * getEyeToHeadTransform(eye)) * modelMat; _overlayRenderer.mvps[eye] = _eyeProjections[eye] * modelView; }); - - // Setup the uniforms - { - auto& uniforms = _overlayRenderer.uniforms; - uniforms.alpha = _compositeOverlayAlpha; - uniforms.glowPoints = vec4(handGlowPoints[0], handGlowPoints[1]); - uniforms.glowColors[0] = _presentHandLasers[0].color; - uniforms.glowColors[1] = _presentHandLasers[1].color; - uniforms.extraGlowPoint = extraGlowPoint; - uniforms.extraGlowColor = _presentExtraLaser.color; - } } void HmdDisplayPlugin::OverlayRenderer::build() { @@ -573,8 +427,8 @@ void HmdDisplayPlugin::OverlayRenderer::build() { } void HmdDisplayPlugin::OverlayRenderer::updatePipeline() { - static const QString vsFile = PathUtils::resourcesPath() + "/shaders/hmd_ui_glow.vert"; - static const QString fsFile = PathUtils::resourcesPath() + "/shaders/hmd_ui_glow.frag"; + static const QString vsFile = PathUtils::resourcesPath() + "/shaders/hmd_ui.vert"; + static const QString fsFile = PathUtils::resourcesPath() + "/shaders/hmd_ui.frag"; #if LIVE_SHADER_RELOAD static qint64 vsBuiltAge = 0; @@ -598,7 +452,7 @@ void HmdDisplayPlugin::OverlayRenderer::updatePipeline() { this->uniformsLocation = program->getUniformBuffers().findLocation("overlayBuffer"); gpu::StatePointer state = gpu::StatePointer(new gpu::State()); - state->setDepthTest(gpu::State::DepthTest(false)); + state->setDepthTest(gpu::State::DepthTest(true)); state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); @@ -665,84 +519,6 @@ void HmdDisplayPlugin::compositeOverlay() { _overlayRenderer.render(*this); } -bool HmdDisplayPlugin::setHandLaser(uint32_t hands, HandLaserMode mode, const vec4& color, const vec3& direction) { - HandLaserInfo info; - info.mode = mode; - info.color = color; - info.direction = direction; - withNonPresentThreadLock([&] { - if (hands & Hand::LeftHand) { - _handLasers[0] = info; - } - if (hands & Hand::RightHand) { - _handLasers[1] = info; - } - }); - // FIXME defer to a child class plugin to determine if hand lasers are actually - // available based on the presence or absence of hand controllers - return true; -} - -bool HmdDisplayPlugin::setExtraLaser(HandLaserMode mode, const vec4& color, const glm::vec3& sensorSpaceStart, const vec3& sensorSpaceDirection) { - HandLaserInfo info; - info.mode = mode; - info.color = color; - info.direction = sensorSpaceDirection; - withNonPresentThreadLock([&] { - _extraLaser = info; - _extraLaserStart = sensorSpaceStart; - }); - - // FIXME defer to a child class plugin to determine if hand lasers are actually - // available based on the presence or absence of hand controllers - return true; -} - - -void HmdDisplayPlugin::compositeExtra() { - // If neither hand laser is activated, exit - if (!_presentHandLasers[0].valid() && !_presentHandLasers[1].valid() && !_presentExtraLaser.valid()) { - return; - } - - if (_presentHandPoses[0] == IDENTITY_MATRIX && _presentHandPoses[1] == IDENTITY_MATRIX && !_presentExtraLaser.valid()) { - return; - } - - render([&](gpu::Batch& batch) { - batch.setFramebuffer(_compositeFramebuffer); - batch.setModelTransform(Transform()); - batch.setViewportTransform(ivec4(uvec2(0), _renderTargetSize)); - batch.setViewTransform(_currentPresentFrameInfo.presentPose, false); - // Compile the shaders - batch.setPipeline(_glowLinePipeline); - - - bilateral::for_each_side([&](bilateral::Side side){ - auto index = bilateral::index(side); - if (_presentHandPoses[index] == IDENTITY_MATRIX) { - return; - } - const auto& laser = _presentHandLasers[index]; - if (laser.valid()) { - const auto& points = _presentHandLaserPoints[index]; - _handLaserUniforms[index]->resize(sizeof(HandLaserData)); - _handLaserUniforms[index]->setSubData(0, HandLaserData { vec4(points.first, 1.0f), vec4(points.second, 1.0f), _handLasers[index].color }); - batch.setUniformBuffer(LINE_DATA_SLOT, _handLaserUniforms[index]); - batch.draw(gpu::TRIANGLE_STRIP, 4, 0); - } - }); - - if (_presentExtraLaser.valid()) { - const auto& points = _presentExtraLaserPoints; - _extraLaserUniforms->resize(sizeof(HandLaserData)); - _extraLaserUniforms->setSubData(0, HandLaserData { vec4(points.first, 1.0f), vec4(points.second, 1.0f), _presentExtraLaser.color }); - batch.setUniformBuffer(LINE_DATA_SLOT, _extraLaserUniforms); - batch.draw(gpu::TRIANGLE_STRIP, 4, 0); - } - }); -} - HmdDisplayPlugin::~HmdDisplayPlugin() { } diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h index 055328ee21..0827d04922 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h @@ -37,9 +37,6 @@ public: virtual glm::mat4 getHeadPose() const override; - bool setHandLaser(uint32_t hands, HandLaserMode mode, const vec4& color, const vec3& direction) override; - bool setExtraLaser(HandLaserMode mode, const vec4& color, const glm::vec3& sensorSpaceStart, const vec3& sensorSpaceDirection) override; - bool wantVsync() const override { return false; } @@ -63,33 +60,6 @@ protected: void customizeContext() override; void uncustomizeContext() override; void updateFrameData() override; - void compositeExtra() override; - - struct HandLaserInfo { - HandLaserMode mode { HandLaserMode::None }; - vec4 color { 1.0f }; - vec3 direction { 0, 0, -1 }; - - // Is this hand laser info suitable for drawing? - bool valid() const { - return (mode != HandLaserMode::None && color.a > 0.0f && direction != vec3()); - } - }; - - Transform _uiModelTransform; - std::array _handLasers; - std::array _handPoses; - - Transform _presentUiModelTransform; - std::array _presentHandLasers; - std::array _presentHandPoses; - std::array, 2> _presentHandLaserPoints; - - HandLaserInfo _extraLaser; - HandLaserInfo _presentExtraLaser; - vec3 _extraLaserStart; - vec3 _presentExtraLaserStart; - std::pair _presentExtraLaserPoints; std::array _eyeOffsets; std::array _eyeProjections; @@ -120,9 +90,6 @@ private: bool _disablePreviewItemAdded { false }; bool _monoPreview { true }; bool _clearPreviewFlag { false }; - std::array _handLaserUniforms; - gpu::BufferPointer _extraLaserUniforms; - gpu::PipelinePointer _glowLinePipeline; gpu::TexturePointer _previewTexture; glm::vec2 _lastWindowSize; @@ -140,14 +107,7 @@ private: struct Uniforms { mat4 mvp; - vec4 glowPoints { -1 }; - vec4 glowColors[2]; - vec2 resolution { CompositorHelper::VIRTUAL_SCREEN_SIZE }; - float radius { 0.005f }; float alpha { 1.0f }; - - vec4 extraGlowColor; - vec2 extraGlowPoint { -1 }; } uniforms; struct Vertex { diff --git a/libraries/gpu/src/gpu/Frame.h b/libraries/gpu/src/gpu/Frame.h index 3c6fed9393..bfebe85753 100644 --- a/libraries/gpu/src/gpu/Frame.h +++ b/libraries/gpu/src/gpu/Frame.h @@ -32,6 +32,8 @@ namespace gpu { Mat4 pose; /// The collection of batches which make up the frame Batches batches; + /// Single batch containing overlays to be drawn in the composite framebuffer + Batch postCompositeBatch; /// The main thread updates to buffers that are applicable for this frame. BufferUpdates bufferUpdates; /// The destination framebuffer in which the results will be placed diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index 481a2609fc..398e586ef1 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -107,24 +107,6 @@ public: RightHand = 0x02, }; - enum class HandLaserMode { - None, // Render no hand lasers - Overlay, // Render hand lasers only if they intersect with the UI layer, and stop at the UI layer - }; - - virtual bool setHandLaser( - uint32_t hands, // Bits from the Hand enum - HandLaserMode mode, // Mode in which to render - const vec4& color = vec4(1), // The color of the rendered laser - const vec3& direction = vec3(0, 0, -1) // The direction in which to render the hand lasers - ) { - return false; - } - - virtual bool setExtraLaser(HandLaserMode mode, const vec4& color, const glm::vec3& sensorSpaceStart, const vec3& sensorSpaceDirection) { - return false; - } - virtual bool suppressKeyboard() { return false; } virtual void unsuppressKeyboard() {}; virtual bool isKeyboardVisible() { return false; } diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp index 93f4787f0f..426c162628 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp @@ -51,8 +51,6 @@ bool OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) { }); withNonPresentThreadLock([&] { - _uiModelTransform = DependencyManager::get()->getModelTransform(); - _handPoses = handPoses; _frameInfos[frameIndex] = _currentRenderFrameInfo; }); return Parent::beginFrameRender(frameIndex); diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index 7a73c91c7d..394125a734 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -594,9 +594,6 @@ bool OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) { } withNonPresentThreadLock([&] { - _uiModelTransform = DependencyManager::get()->getModelTransform(); - // Make controller poses available to the presentation thread - _handPoses = handPoses; _frameInfos[frameIndex] = _currentRenderFrameInfo; }); return Parent::beginFrameRender(frameIndex); diff --git a/scripts/system/controllers/handControllerPointer.js b/scripts/system/controllers/handControllerPointer.js index eb94428100..f169204206 100644 --- a/scripts/system/controllers/handControllerPointer.js +++ b/scripts/system/controllers/handControllerPointer.js @@ -150,15 +150,92 @@ var setReticlePosition = function (point2d) { Reticle.setPosition(point2d); }; -// Generalizations of utilities that work with system and overlay elements. -function findRayIntersection(pickRay) { - // Check 3D overlays and entities. Argument is an object with origin and direction. - var result = Overlays.findRayIntersection(pickRay); - if (!result.intersects) { - result = Entities.findRayIntersection(pickRay, true); - } - return result; +// VISUAL AID ----------- +// Same properties as handControllerGrab search sphere +var LASER_ALPHA = 0.5; +var LASER_SEARCH_COLOR = {red: 10, green: 10, blue: 255}; +var LASER_TRIGGER_COLOR = {red: 250, green: 10, blue: 10}; +var END_DIAMETER = 0.05; +var systemLaserOn = false; + +var triggerPath = { + type: "line3d", + color: LASER_SEARCH_COLOR, + ignoreRayIntersection: true, + visible: true, + alpha: LASER_ALPHA, + solid: true, + glow: 1.0, + drawHUDLayer: true } +var triggerEnd = { + type: "sphere", + dimensions: {x: END_DIAMETER, y: END_DIAMETER, z: END_DIAMETER}, + color: LASER_SEARCH_COLOR, + ignoreRayIntersection: true, + visible: true, + alpha: LASER_ALPHA, + solid: true, + drawHUDLayer: true +} + +var searchPath = { + type: "line3d", + color: LASER_TRIGGER_COLOR, + ignoreRayIntersection: true, + visible: true, + alpha: LASER_ALPHA, + solid: true, + glow: 1.0, + drawHUDLayer: true +} +var searchEnd = { + type: "sphere", + dimensions: {x: END_DIAMETER, y: END_DIAMETER, z: END_DIAMETER}, + color: LASER_TRIGGER_COLOR, + ignoreRayIntersection: true, + visible: true, + alpha: LASER_ALPHA, + solid: true, + drawHUDLayer: true +} + +var hudRayStates = [{name: "trigger", path: triggerPath, end: triggerEnd}, + {name: "search", path: searchPath, end: searchEnd}]; +// this offset needs to match the one in libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp:378 +var GRAB_POINT_SPHERE_OFFSET_RIGHT = { x: 0.04, y: 0.13, z: 0.039 }; +var GRAB_POINT_SPHERE_OFFSET_LEFT = { x: -0.04, y: 0.13, z: 0.039 }; +var hudRayRight = LaserPointers.createLaserPointer({ + joint: "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND", + filter: RayPick.PICK_HUD, + posOffset: GRAB_POINT_SPHERE_OFFSET_RIGHT, + renderStates: hudRayStates, + enabled: true +}); +var hudRayLeft = LaserPointers.createLaserPointer({ + joint: "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", + filter: RayPick.PICK_HUD, + posOffset: GRAB_POINT_SPHERE_OFFSET_LEFT, + renderStates: hudRayStates, + enabled: true +}); + +// NOTE: keep this offset in sync with scripts/system/librarires/controllers.js:57 +var VERTICAL_HEAD_LASER_OFFSET = 0.1; +var hudRayHead = LaserPointers.createLaserPointer({ + joint: "Avatar", + filter: RayPick.PICK_HUD, + posOffset: {x: 0, y: VERTICAL_HEAD_LASER_OFFSET, z: 0}, + renderStates: hudRayStates, + enabled: true +}); + +var mouseRayPick = RayPick.createRayPick({ + joint: "Mouse", + filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, + enabled: true +}); + function isPointingAtOverlay(optionalHudPosition2d) { return Reticle.pointingAtSystemOverlay || Overlays.getOverlayAtPoint(optionalHudPosition2d || Reticle.position); } @@ -166,10 +243,21 @@ function isPointingAtOverlay(optionalHudPosition2d) { // Generalized HUD utilities, with or without HMD: // This "var" is for documentation. Do not change the value! var PLANAR_PERPENDICULAR_HUD_DISTANCE = 1; -function calculateRayUICollisionPoint(position, direction) { +function calculateRayUICollisionPoint(position, direction, isHands) { // Answer the 3D intersection of the HUD by the given ray, or falsey if no intersection. if (HMD.active) { - return HMD.calculateRayUICollisionPoint(position, direction); + var laserPointer; + if (isHands) { + laserPointer = activeHand == Controller.Standard.RightHand ? hudRayRight : hudRayLeft; + } else { + laserPointer = hudRayHead; + } + var result = LaserPointers.getPrevRayPickResult(laserPointer); + if (result.type != RayPick.INTERSECTED_NONE) { + return result.intersection; + } else { + return null; + } } // interect HUD plane, 1m in front of camera, using formula: // scale = hudNormal dot (hudPoint - position) / hudNormal dot direction @@ -215,7 +303,7 @@ function activeHudPoint2dGamePad() { var headPosition = MyAvatar.getHeadPosition(); var headDirection = Quat.getUp(Quat.multiply(MyAvatar.headOrientation, Quat.angleAxis(-90, { x: 1, y: 0, z: 0 }))); - var hudPoint3d = calculateRayUICollisionPoint(headPosition, headDirection); + var hudPoint3d = calculateRayUICollisionPoint(headPosition, headDirection, false); if (!hudPoint3d) { if (Menu.isOptionChecked("Overlays")) { // With our hud resetting strategy, hudPoint3d should be valid here @@ -241,7 +329,7 @@ function activeHudPoint2d(activeHand) { // if controller is valid, update reticl var controllerPosition = controllerPose.position; var controllerDirection = Quat.getUp(controllerPose.rotation); - var hudPoint3d = calculateRayUICollisionPoint(controllerPosition, controllerDirection); + var hudPoint3d = calculateRayUICollisionPoint(controllerPosition, controllerDirection, true); if (!hudPoint3d) { if (Menu.isOptionChecked("Overlays")) { // With our hud resetting strategy, hudPoint3d should be valid here print('Controller is parallel to HUD'); // so let us know that our assumptions are wrong. @@ -355,7 +443,7 @@ function onMouseMove() { if (isPointingAtOverlay()) { Reticle.depth = hudReticleDistance(); } else { - var result = findRayIntersection(Camera.computePickRay(Reticle.position.x, Reticle.position.y)); + var result = RayPick.getPrevRayPickResult(mouseRayPick); Reticle.depth = result.intersects ? result.distance : APPARENT_MAXIMUM_DEPTH; } } @@ -473,14 +561,6 @@ clickMapping.from(rightTrigger.partial).to(makeToggleAction(Controller.Standard. clickMapping.from(leftTrigger.partial).to(makeToggleAction(Controller.Standard.LeftHand)); clickMapping.enable(); -// VISUAL AID ----------- -// Same properties as handControllerGrab search sphere -var LASER_ALPHA = 0.5; -var LASER_SEARCH_COLOR_XYZW = {x: 10 / 255, y: 10 / 255, z: 255 / 255, w: LASER_ALPHA}; -var LASER_TRIGGER_COLOR_XYZW = {x: 250 / 255, y: 10 / 255, z: 10 / 255, w: LASER_ALPHA}; -var SYSTEM_LASER_DIRECTION = {x: 0, y: 0, z: -1}; -var systemLaserOn = false; - var HIFI_POINTER_DISABLE_MESSAGE_CHANNEL = "Hifi-Pointer-Disable"; var isPointerEnabled = true; @@ -488,23 +568,34 @@ function clearSystemLaser() { if (!systemLaserOn) { return; } - HMD.disableHandLasers(BOTH_HUD_LASERS); - HMD.disableExtraLaser(); + HMD.deactivateHMDHandMouse(); + LaserPointers.setRenderState(hudRayRight, ""); + LaserPointers.setRenderState(hudRayLeft, ""); + LaserPointers.setRenderState(hudRayHead, ""); systemLaserOn = false; weMovedReticle = true; } function setColoredLaser() { // answer trigger state if lasers supported, else falsey. - var color = (activeTrigger.state === 'full') ? LASER_TRIGGER_COLOR_XYZW : LASER_SEARCH_COLOR_XYZW; + var mode = (activeTrigger.state === 'full') ? 'trigger' : 'search'; - if (!HMD.isHandControllerAvailable()) { - // NOTE: keep this offset in sync with scripts/system/librarires/controllers.js:57 - var VERTICAL_HEAD_LASER_OFFSET = 0.1; - var position = Vec3.sum(HMD.position, Vec3.multiplyQbyV(HMD.orientation, {x: 0, y: VERTICAL_HEAD_LASER_OFFSET, z: 0})); - var orientation = Quat.multiply(HMD.orientation, Quat.angleAxis(-90, { x: 1, y: 0, z: 0 })); - return HMD.setExtraLaser(position, true, color, Quat.getUp(orientation)); + if (!systemLaserOn) { + HMD.activateHMDHandMouse(); } - return HMD.setHandLasers(activeHudLaser, true, color, SYSTEM_LASER_DIRECTION) && activeTrigger.state; + var pose = Controller.getPoseValue(activeHand); + if (!pose.valid) { + LaserPointers.setRenderState(hudRayRight, ""); + LaserPointers.setRenderState(hudRayLeft, ""); + LaserPointers.setRenderState(hudRayHead, mode); + return true; + } + + var right = activeHand == Controller.Standard.RightHand; + LaserPointers.setRenderState(hudRayRight, right ? mode : ""); + LaserPointers.setRenderState(hudRayLeft, right ? "" : mode); + LaserPointers.setRenderState(hudRayHead, ""); + + return activeTrigger.state; } // MAIN OPERATIONS ----------- @@ -551,11 +642,13 @@ function update() { if (HMD.active) { Reticle.depth = hudReticleDistance(); - if (!HMD.isHandControllerAvailable()) { - var color = (activeTrigger.state === 'full') ? LASER_TRIGGER_COLOR_XYZW : LASER_SEARCH_COLOR_XYZW; - var position = MyAvatar.getHeadPosition(); - var direction = Quat.getUp(Quat.multiply(MyAvatar.headOrientation, Quat.angleAxis(-90, { x: 1, y: 0, z: 0 }))); - HMD.setExtraLaser(position, true, color, direction); + var pose = Controller.getPoseValue(activeHand); + if (!pose.valid) { + var mode = (activeTrigger.state === 'full') ? 'trigger' : 'search'; + if (!systemLaserOn) { + HMD.activateHMDHandMouse(); + } + LaserPointers.setRenderState(hudRayHead, mode); } } @@ -604,6 +697,10 @@ Script.scriptEnding.connect(function () { Script.clearInterval(settingsChecker); Script.update.disconnect(update); OffscreenFlags.navigationFocusDisabled = false; + LaserPointers.removeLaserPointer(hudRayRight); + LaserPointers.removeLaserPointer(hudRayLeft); + LaserPointers.removeLaserPointer(hudRayHead); + HMD.deactivateHMDHandMouse(); }); }()); // END LOCAL_SCOPE From 3149c3e16c0671a8428390b28e3614f3ca170c90 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 25 Jul 2017 10:16:50 -0700 Subject: [PATCH 25/42] warnings --- interface/src/scripting/HMDScriptingInterface.cpp | 2 +- interface/src/ui/overlays/Overlay.cpp | 4 ++-- .../src/display-plugins/hmd/HmdDisplayPlugin.cpp | 9 --------- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/interface/src/scripting/HMDScriptingInterface.cpp b/interface/src/scripting/HMDScriptingInterface.cpp index af3c7c3d67..93c3a7652e 100644 --- a/interface/src/scripting/HMDScriptingInterface.cpp +++ b/interface/src/scripting/HMDScriptingInterface.cpp @@ -91,7 +91,7 @@ void HMDScriptingInterface::activateHMDHandMouse() { void HMDScriptingInterface::deactivateHMDHandMouse() { QWriteLocker lock(&_hmdHandMouseLock); - _hmdHandMouseCount = std::max(--_hmdHandMouseCount, 0); + _hmdHandMouseCount = std::max(_hmdHandMouseCount - 1, 0); if (_hmdHandMouseCount == 0) { auto offscreenUi = DependencyManager::get(); offscreenUi->getDesktop()->setProperty("hmdHandMouseActive", false); diff --git a/interface/src/ui/overlays/Overlay.cpp b/interface/src/ui/overlays/Overlay.cpp index 868cdf110b..3afe7d76ca 100644 --- a/interface/src/ui/overlays/Overlay.cpp +++ b/interface/src/ui/overlays/Overlay.cpp @@ -29,8 +29,8 @@ Overlay::Overlay() : _alphaPulse(0.0f), _colorPulse(0.0f), _color(DEFAULT_OVERLAY_COLOR), - _drawHUDLayer(false), _visible(true), + _drawHUDLayer(false), _anchor(NO_ANCHOR) { } @@ -48,8 +48,8 @@ Overlay::Overlay(const Overlay* overlay) : _alphaPulse(overlay->_alphaPulse), _colorPulse(overlay->_colorPulse), _color(overlay->_color), - _drawHUDLayer(overlay->_drawHUDLayer), _visible(overlay->_visible), + _drawHUDLayer(overlay->_drawHUDLayer), _anchor(overlay->_anchor) { } diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index fe109e7bc9..ab53316010 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -42,17 +42,10 @@ static const bool DEFAULT_MONO_VIEW = true; static const bool DEFAULT_DISABLE_PREVIEW = false; #endif static const glm::mat4 IDENTITY_MATRIX; -static const size_t NUMBER_OF_HANDS = 2; //#define LIVE_SHADER_RELOAD 1 extern glm::vec3 getPoint(float yaw, float pitch); -struct HandLaserData { - vec4 p1; - vec4 p2; - vec4 color; -}; - static QString readFile(const QString& filename) { QFile file(filename); file.open(QFile::Text | QFile::ReadOnly); @@ -115,8 +108,6 @@ void HmdDisplayPlugin::internalDeactivate() { Parent::internalDeactivate(); } -static const int32_t LINE_DATA_SLOT = 1; - void HmdDisplayPlugin::customizeContext() { Parent::customizeContext(); _overlayRenderer.build(); From 011795054652898eee287d85d10b9e98b9b1daf9 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 25 Jul 2017 12:57:52 -0700 Subject: [PATCH 26/42] can edit drawHUDLayer property --- interface/src/ui/overlays/Overlay.cpp | 8 +++++++ interface/src/ui/overlays/Overlay.h | 2 +- interface/src/ui/overlays/Overlays.cpp | 22 +++++++++++++++++++ interface/src/ui/overlays/Overlays.h | 2 ++ .../display-plugins/OpenGLDisplayPlugin.cpp | 3 ++- 5 files changed, 35 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/overlays/Overlay.cpp b/interface/src/ui/overlays/Overlay.cpp index 3afe7d76ca..541c251371 100644 --- a/interface/src/ui/overlays/Overlay.cpp +++ b/interface/src/ui/overlays/Overlay.cpp @@ -13,6 +13,8 @@ #include #include +#include "Application.h" + static const xColor DEFAULT_OVERLAY_COLOR = { 255, 255, 255 }; static const float DEFAULT_ALPHA = 0.7f; @@ -168,6 +170,12 @@ float Overlay::getAlpha() { return (_alphaPulse >= 0.0f) ? _alpha * pulseLevel : _alpha * (1.0f - pulseLevel); } +void Overlay::setDrawHUDLayer(bool drawHUDLayer) { + if (drawHUDLayer != _drawHUDLayer) { + qApp->getOverlays().setOverlayDrawHUDLayer(getOverlayID(), drawHUDLayer); + _drawHUDLayer = drawHUDLayer; + } +} // pulse travels from min to max, then max to min in one period. float Overlay::updatePulse() { diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index 0bb0d39d7a..a9774eea06 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -73,7 +73,7 @@ public: // setters void setVisible(bool visible) { _visible = visible; } - void setDrawHUDLayer(bool drawHUDLayer) { _drawHUDLayer = drawHUDLayer; } + void setDrawHUDLayer(bool drawHUDLayer); void setColor(const xColor& color) { _color = color; } void setAlpha(float alpha) { _alpha = alpha; } void setAnchor(Anchor anchor) { _anchor = anchor; } diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 067bfac0cb..5d6029f521 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -253,6 +253,28 @@ OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) { return thisID; } +void Overlays::setOverlayDrawHUDLayer(const OverlayID& id, const bool drawHUDLayer) { + QMutexLocker locker(&_mutex); + if (drawHUDLayer && _overlaysWorld.contains(id)) { + std::shared_ptr overlay = _overlaysWorld.take(id); + render::ScenePointer scene = qApp->getMain3DScene(); + render::Transaction transaction; + auto itemID = overlay->getRenderItemID(); + if (render::Item::isValidID(itemID)) { + overlay->removeFromScene(overlay, scene, transaction); + scene->enqueueTransaction(transaction); + } + _overlays3DHUD[id] = overlay; + } else if (!drawHUDLayer && _overlays3DHUD.contains(id)) { + std::shared_ptr overlay = _overlays3DHUD.take(id); + render::ScenePointer scene = qApp->getMain3DScene(); + render::Transaction transaction; + overlay->addToScene(overlay, scene, transaction); + scene->enqueueTransaction(transaction); + _overlaysWorld[id] = overlay; + } +} + OverlayID Overlays::cloneOverlay(OverlayID id) { if (QThread::currentThread() != thread()) { OverlayID result; diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 9efc003669..8aa15d7f14 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -103,6 +103,8 @@ public: OverlayID addOverlay(Overlay* overlay) { return addOverlay(Overlay::Pointer(overlay)); } OverlayID addOverlay(const Overlay::Pointer& overlay); + void setOverlayDrawHUDLayer(const OverlayID& id, const bool drawHUDLayer); + bool mousePressEvent(QMouseEvent* event); bool mouseDoublePressEvent(QMouseEvent* event); bool mouseReleaseEvent(QMouseEvent* event); diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 1c361ed1ca..7333c7012c 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -641,7 +641,8 @@ void OpenGLDisplayPlugin::compositeLayers() { compositePointer(); } - { + // Only render HUD layer 3D overlays in HMD mode + if (isHmd()) { PROFILE_RANGE_EX(render_detail, "compositeHUDOverlays", 0xff0077ff, (uint64_t)presentCount()) render([&](gpu::Batch& batch) { batch.enableStereo(false); From 658acd91f2fdb30be4b134869294c3094f9d58f3 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 25 Jul 2017 14:17:39 -0700 Subject: [PATCH 27/42] experimenting with drawHUDLayer depth testing --- interface/resources/shaders/hmd_ui.frag | 3 +++ interface/src/ui/overlays/Overlays.cpp | 4 +-- .../display-plugins/OpenGLDisplayPlugin.cpp | 26 ++++++++++++++----- .../display-plugins/hmd/HmdDisplayPlugin.cpp | 2 +- .../render-utils/src/RenderDeferredTask.cpp | 2 +- .../render-utils/src/RenderPipelines.cpp | 10 ++++--- 6 files changed, 33 insertions(+), 14 deletions(-) diff --git a/interface/resources/shaders/hmd_ui.frag b/interface/resources/shaders/hmd_ui.frag index af96169831..5341ab575d 100644 --- a/interface/resources/shaders/hmd_ui.frag +++ b/interface/resources/shaders/hmd_ui.frag @@ -24,4 +24,7 @@ out vec4 FragColor; void main() { FragColor = texture(sampler, vTexCoord); FragColor.a *= overlay.alpha; + if (FragColor.a <= 0.0) { + discard; + } } \ No newline at end of file diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 5d6029f521..197ea907da 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -41,7 +41,7 @@ Q_LOGGING_CATEGORY(trace_render_overlays, "trace.render.overlays") -extern void initOverlay3DPipelines(render::ShapePlumber& plumber); +extern void initOverlay3DPipelines(render::ShapePlumber& plumber, bool depthTest = false); void Overlays::cleanupAllOverlays() { QMap overlaysHUD; @@ -74,7 +74,7 @@ void Overlays::init() { _scriptEngine = new QScriptEngine(); #endif _shapePlumber = std::make_shared(); - initOverlay3DPipelines(*_shapePlumber); + initOverlay3DPipelines(*_shapePlumber, true); } void Overlays::update(float deltatime) { diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 7333c7012c..db7c0e4f65 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -626,6 +626,11 @@ void OpenGLDisplayPlugin::compositeLayers() { compositeScene(); } + // Clear the depth framebuffer after drawing the scene so that the HUD elements can depth test against each other + render([&](gpu::Batch& batch) { + batch.setFramebuffer(_compositeFramebuffer); + batch.clearDepthFramebuffer(UINT32_MAX); + }); #ifdef HIFI_ENABLE_NSIGHT_DEBUG if (false) // do not compositeoverlay if running nsight debug @@ -635,12 +640,6 @@ void OpenGLDisplayPlugin::compositeLayers() { compositeOverlay(); } - auto compositorHelper = DependencyManager::get(); - if (compositorHelper->getReticleVisible()) { - PROFILE_RANGE_EX(render_detail, "compositePointer", 0xff0077ff, (uint64_t)presentCount()) - compositePointer(); - } - // Only render HUD layer 3D overlays in HMD mode if (isHmd()) { PROFILE_RANGE_EX(render_detail, "compositeHUDOverlays", 0xff0077ff, (uint64_t)presentCount()) @@ -655,6 +654,18 @@ void OpenGLDisplayPlugin::compositeLayers() { PROFILE_RANGE_EX(render_detail, "compositeExtra", 0xff0077ff, (uint64_t)presentCount()) compositeExtra(); } + + // Clear the depth buffer again and draw the pointer last so it's on top of everything + render([&](gpu::Batch& batch) { + batch.setFramebuffer(_compositeFramebuffer); + batch.clearDepthFramebuffer(UINT32_MAX); + }); + + auto compositorHelper = DependencyManager::get(); + if (compositorHelper->getReticleVisible()) { + PROFILE_RANGE_EX(render_detail, "compositePointer", 0xff0077ff, (uint64_t)presentCount()) + compositePointer(); + } } void OpenGLDisplayPlugin::internalPresent() { @@ -861,7 +872,8 @@ OpenGLDisplayPlugin::~OpenGLDisplayPlugin() { void OpenGLDisplayPlugin::updateCompositeFramebuffer() { auto renderSize = getRecommendedRenderSize(); if (!_compositeFramebuffer || _compositeFramebuffer->getSize() != renderSize) { - _compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", gpu::Element::COLOR_RGBA_32, renderSize.x, renderSize.y)); + auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); + _compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", gpu::Element::COLOR_RGBA_32, depthFormat, renderSize.x, renderSize.y)); } } diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index ab53316010..aef5c73fa3 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -443,7 +443,7 @@ void HmdDisplayPlugin::OverlayRenderer::updatePipeline() { this->uniformsLocation = program->getUniformBuffers().findLocation("overlayBuffer"); gpu::StatePointer state = gpu::StatePointer(new gpu::State()); - state->setDepthTest(gpu::State::DepthTest(true)); + state->setDepthTest(gpu::State::DepthTest(true, true, gpu::LESS_EQUAL)); state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 20c999019b..94fd1627d6 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -44,7 +44,7 @@ using namespace render; -extern void initOverlay3DPipelines(render::ShapePlumber& plumber); +extern void initOverlay3DPipelines(render::ShapePlumber& plumber, bool depthTest = false); extern void initDeferredPipelines(render::ShapePlumber& plumber); void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 6c3a58b7e5..18146ca651 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -69,7 +69,7 @@ using namespace render; using namespace std::placeholders; -void initOverlay3DPipelines(ShapePlumber& plumber); +void initOverlay3DPipelines(ShapePlumber& plumber, bool depthTest = false); void initDeferredPipelines(ShapePlumber& plumber); void initForwardPipelines(ShapePlumber& plumber); @@ -79,7 +79,7 @@ void addPlumberPipeline(ShapePlumber& plumber, void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* args); void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* args); -void initOverlay3DPipelines(ShapePlumber& plumber) { +void initOverlay3DPipelines(ShapePlumber& plumber, bool depthTest) { auto vertex = gpu::Shader::createVertex(std::string(overlay3D_vert)); auto vertexModel = gpu::Shader::createVertex(std::string(model_vert)); auto pixel = gpu::Shader::createPixel(std::string(overlay3D_frag)); @@ -106,7 +106,11 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { bool isOpaque = (i & 4); auto state = std::make_shared(); - state->setDepthTest(false); + if (depthTest) { + state->setDepthTest(true, true, gpu::LESS_EQUAL); + } else { + state->setDepthTest(false); + } state->setCullMode(isCulled ? gpu::State::CULL_BACK : gpu::State::CULL_NONE); if (isBiased) { state->setDepthBias(1.0f); From 3a8ad8b6318e629826d341df05a52da5f217dc0a Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 25 Jul 2017 15:11:44 -0700 Subject: [PATCH 28/42] switch to QUuids --- interface/src/raypick/LaserPointer.h | 4 +- interface/src/raypick/LaserPointerManager.cpp | 39 +++++++++-------- interface/src/raypick/LaserPointerManager.h | 35 ++++++++------- .../LaserPointerScriptingInterface.cpp | 4 +- .../raypick/LaserPointerScriptingInterface.h | 26 +++++------ interface/src/raypick/RayPickManager.cpp | 43 ++++++++++--------- interface/src/raypick/RayPickManager.h | 33 +++++++------- 7 files changed, 93 insertions(+), 91 deletions(-) diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index 359295fd6a..b1b8be23e4 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -53,7 +53,7 @@ public: const bool lockEnd, const bool enabled); ~LaserPointer(); - unsigned int getRayUID() { return _rayPickUID; } + QUuid getRayUID() { return _rayPickUID; } void enable(); void disable(); const RayPickResult getPrevRayPickResult() { return DependencyManager::get()->getPrevRayPickResult(_rayPickUID); } @@ -78,7 +78,7 @@ private: bool _centerEndY; bool _lockEnd; - unsigned int _rayPickUID; + QUuid _rayPickUID; OverlayID updateRenderStateOverlay(const OverlayID& id, const QVariant& props); void disableRenderState(const QString& renderState); diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp index d9f3023263..2b4d7d096b 100644 --- a/interface/src/raypick/LaserPointerManager.cpp +++ b/interface/src/raypick/LaserPointerManager.cpp @@ -12,23 +12,24 @@ #include "LaserPointer.h" #include "RayPick.h" -unsigned int LaserPointerManager::createLaserPointer(const QVariantMap& rayProps, const QHash& renderStates, const bool faceAvatar, const bool centerEndY, +QUuid LaserPointerManager::createLaserPointer(const QVariantMap& rayProps, const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) { std::shared_ptr laserPointer = std::make_shared(rayProps, renderStates, faceAvatar, centerEndY, lockEnd, enabled); if (laserPointer->getRayUID() != 0) { QWriteLocker lock(&_addLock); - _laserPointersToAdd.enqueue(QPair>(_nextUID, laserPointer)); - return _nextUID++; + QUuid id = QUuid::createUuid(); + _laserPointersToAdd.enqueue(QPair>(id, laserPointer)); + return id; } - return 0; + return QUuid(); } -void LaserPointerManager::removeLaserPointer(const unsigned int uid) { +void LaserPointerManager::removeLaserPointer(const QUuid uid) { QWriteLocker lock(&_removeLock); _laserPointersToRemove.enqueue(uid); } -void LaserPointerManager::enableLaserPointer(const unsigned int uid) { +void LaserPointerManager::enableLaserPointer(const QUuid uid) { QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { QWriteLocker laserLock(_laserPointerLocks[uid].get()); @@ -36,7 +37,7 @@ void LaserPointerManager::enableLaserPointer(const unsigned int uid) { } } -void LaserPointerManager::disableLaserPointer(const unsigned int uid) { +void LaserPointerManager::disableLaserPointer(const QUuid uid) { QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { QWriteLocker laserLock(_laserPointerLocks[uid].get()); @@ -44,7 +45,7 @@ void LaserPointerManager::disableLaserPointer(const unsigned int uid) { } } -void LaserPointerManager::setRenderState(unsigned int uid, const QString & renderState) { +void LaserPointerManager::setRenderState(QUuid uid, const QString & renderState) { QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { QWriteLocker laserLock(_laserPointerLocks[uid].get()); @@ -52,7 +53,7 @@ void LaserPointerManager::setRenderState(unsigned int uid, const QString & rende } } -void LaserPointerManager::editRenderState(unsigned int uid, const QString& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) { +void LaserPointerManager::editRenderState(QUuid uid, const QString& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) { QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { QWriteLocker laserLock(_laserPointerLocks[uid].get()); @@ -60,7 +61,7 @@ void LaserPointerManager::editRenderState(unsigned int uid, const QString& state } } -const RayPickResult LaserPointerManager::getPrevRayPickResult(const unsigned int uid) { +const RayPickResult LaserPointerManager::getPrevRayPickResult(const QUuid uid) { QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { QReadLocker laserLock(_laserPointerLocks[uid].get()); @@ -70,7 +71,7 @@ const RayPickResult LaserPointerManager::getPrevRayPickResult(const unsigned int } void LaserPointerManager::update() { - for (unsigned int uid : _laserPointers.keys()) { + for (QUuid uid : _laserPointers.keys()) { // This only needs to be a read lock because update won't change any of the properties that can be modified from scripts QReadLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->update(); @@ -80,7 +81,7 @@ void LaserPointerManager::update() { { QWriteLocker lock(&_addLock); while (!_laserPointersToAdd.isEmpty()) { - QPair> laserPointerToAdd = _laserPointersToAdd.dequeue(); + QPair> laserPointerToAdd = _laserPointersToAdd.dequeue(); _laserPointers[laserPointerToAdd.first] = laserPointerToAdd.second; _laserPointerLocks[laserPointerToAdd.first] = std::make_shared(); } @@ -89,14 +90,14 @@ void LaserPointerManager::update() { { QWriteLocker lock(&_removeLock); while (!_laserPointersToRemove.isEmpty()) { - unsigned int uid = _laserPointersToRemove.dequeue(); + QUuid uid = _laserPointersToRemove.dequeue(); _laserPointers.remove(uid); _laserPointerLocks.remove(uid); } } } -void LaserPointerManager::setIgnoreEntities(unsigned int uid, const QScriptValue& ignoreEntities) { +void LaserPointerManager::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) { QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { QWriteLocker laserLock(_laserPointerLocks[uid].get()); @@ -104,7 +105,7 @@ void LaserPointerManager::setIgnoreEntities(unsigned int uid, const QScriptValue } } -void LaserPointerManager::setIncludeEntities(unsigned int uid, const QScriptValue& includeEntities) { +void LaserPointerManager::setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) { QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { QWriteLocker laserLock(_laserPointerLocks[uid].get()); @@ -112,7 +113,7 @@ void LaserPointerManager::setIncludeEntities(unsigned int uid, const QScriptValu } } -void LaserPointerManager::setIgnoreOverlays(unsigned int uid, const QScriptValue& ignoreOverlays) { +void LaserPointerManager::setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) { QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { QWriteLocker laserLock(_laserPointerLocks[uid].get()); @@ -120,7 +121,7 @@ void LaserPointerManager::setIgnoreOverlays(unsigned int uid, const QScriptValue } } -void LaserPointerManager::setIncludeOverlays(unsigned int uid, const QScriptValue& includeOverlays) { +void LaserPointerManager::setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays) { QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { QWriteLocker laserLock(_laserPointerLocks[uid].get()); @@ -128,7 +129,7 @@ void LaserPointerManager::setIncludeOverlays(unsigned int uid, const QScriptValu } } -void LaserPointerManager::setIgnoreAvatars(unsigned int uid, const QScriptValue& ignoreAvatars) { +void LaserPointerManager::setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) { QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { QWriteLocker laserLock(_laserPointerLocks[uid].get()); @@ -136,7 +137,7 @@ void LaserPointerManager::setIgnoreAvatars(unsigned int uid, const QScriptValue& } } -void LaserPointerManager::setIncludeAvatars(unsigned int uid, const QScriptValue& includeAvatars) { +void LaserPointerManager::setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) { QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { QWriteLocker laserLock(_laserPointerLocks[uid].get()); diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h index ff63927be2..b239fc1514 100644 --- a/interface/src/raypick/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -25,32 +25,31 @@ class LaserPointerManager : public Dependency { SINGLETON_DEPENDENCY public: - unsigned int createLaserPointer(const QVariantMap& rayProps, const QHash& renderStates, const bool faceAvatar, const bool centerEndY, + QUuid createLaserPointer(const QVariantMap& rayProps, const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled); - void removeLaserPointer(const unsigned int uid); - void enableLaserPointer(const unsigned int uid); - void disableLaserPointer(const unsigned int uid); - void setRenderState(unsigned int uid, const QString& renderState); - void editRenderState(unsigned int uid, const QString& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps); - const RayPickResult getPrevRayPickResult(const unsigned int uid); + void removeLaserPointer(const QUuid uid); + void enableLaserPointer(const QUuid uid); + void disableLaserPointer(const QUuid uid); + void setRenderState(QUuid uid, const QString& renderState); + void editRenderState(QUuid uid, const QString& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps); + const RayPickResult getPrevRayPickResult(const QUuid uid); - void setIgnoreEntities(unsigned int uid, const QScriptValue& ignoreEntities); - void setIncludeEntities(unsigned int uid, const QScriptValue& includeEntities); - void setIgnoreOverlays(unsigned int uid, const QScriptValue& ignoreOverlays); - void setIncludeOverlays(unsigned int uid, const QScriptValue& includeOverlays); - void setIgnoreAvatars(unsigned int uid, const QScriptValue& ignoreAvatars); - void setIncludeAvatars(unsigned int uid, const QScriptValue& includeAvatars); + void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities); + void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities); + void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays); + void setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays); + void setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars); + void setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars); void update(); private: - QHash> _laserPointers; - QHash> _laserPointerLocks; - unsigned int _nextUID{ 1 }; // 0 is invalid + QHash> _laserPointers; + QHash> _laserPointerLocks; QReadWriteLock _addLock; - QQueue>> _laserPointersToAdd; + QQueue>> _laserPointersToAdd; QReadWriteLock _removeLock; - QQueue _laserPointersToRemove; + QQueue _laserPointersToRemove; QReadWriteLock _containsLock; }; diff --git a/interface/src/raypick/LaserPointerScriptingInterface.cpp b/interface/src/raypick/LaserPointerScriptingInterface.cpp index e1dc1f35c1..7cae7ccdc4 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.cpp +++ b/interface/src/raypick/LaserPointerScriptingInterface.cpp @@ -17,7 +17,7 @@ #include "Application.h" -uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& properties) { +QUuid LaserPointerScriptingInterface::createLaserPointer(const QVariant& properties) { QVariantMap propertyMap = properties.toMap(); bool faceAvatar = false; @@ -57,7 +57,7 @@ uint32_t LaserPointerScriptingInterface::createLaserPointer(const QVariant& prop return DependencyManager::get()->createLaserPointer(propertyMap, renderStates, faceAvatar, centerEndY, lockEnd, enabled); } -void LaserPointerScriptingInterface::editRenderState(unsigned int uid, const QString& renderState, const QVariant& properties) { +void LaserPointerScriptingInterface::editRenderState(QUuid uid, const QString& renderState, const QVariant& properties) { QVariantMap propMap = properties.toMap(); QVariant startProps; diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h index d4297c59ac..a6b61446a7 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -22,20 +22,20 @@ class LaserPointerScriptingInterface : public QObject, public Dependency { SINGLETON_DEPENDENCY public slots: - Q_INVOKABLE unsigned int createLaserPointer(const QVariant& properties); - Q_INVOKABLE void enableLaserPointer(unsigned int uid) { DependencyManager::get()->enableLaserPointer(uid); } - Q_INVOKABLE void disableLaserPointer(unsigned int uid) { DependencyManager::get()->disableLaserPointer(uid); } - Q_INVOKABLE void removeLaserPointer(unsigned int uid) { DependencyManager::get()->removeLaserPointer(uid); } - Q_INVOKABLE void editRenderState(unsigned int uid, const QString& renderState, const QVariant& properties); - Q_INVOKABLE void setRenderState(unsigned int uid, const QString& renderState) { DependencyManager::get()->setRenderState(uid, renderState); } - Q_INVOKABLE RayPickResult getPrevRayPickResult(unsigned int uid) { return DependencyManager::get()->getPrevRayPickResult(uid); } + Q_INVOKABLE QUuid createLaserPointer(const QVariant& properties); + Q_INVOKABLE void enableLaserPointer(QUuid uid) { DependencyManager::get()->enableLaserPointer(uid); } + Q_INVOKABLE void disableLaserPointer(QUuid uid) { DependencyManager::get()->disableLaserPointer(uid); } + Q_INVOKABLE void removeLaserPointer(QUuid uid) { DependencyManager::get()->removeLaserPointer(uid); } + Q_INVOKABLE void editRenderState(QUuid uid, const QString& renderState, const QVariant& properties); + Q_INVOKABLE void setRenderState(QUuid uid, const QString& renderState) { DependencyManager::get()->setRenderState(uid, renderState); } + Q_INVOKABLE RayPickResult getPrevRayPickResult(QUuid uid) { return DependencyManager::get()->getPrevRayPickResult(uid); } - Q_INVOKABLE void setIgnoreEntities(unsigned int uid, const QScriptValue& ignoreEntities) { DependencyManager::get()->setIgnoreEntities(uid, ignoreEntities); } - Q_INVOKABLE void setIncludeEntities(unsigned int uid, const QScriptValue& includeEntities) { DependencyManager::get()->setIncludeEntities(uid, includeEntities); } - Q_INVOKABLE void setIgnoreOverlays(unsigned int uid, const QScriptValue& ignoreOverlays) { DependencyManager::get()->setIgnoreOverlays(uid, ignoreOverlays); } - Q_INVOKABLE void setIncludeOverlays(unsigned int uid, const QScriptValue& includeOverlays) { DependencyManager::get()->setIncludeOverlays(uid, includeOverlays); } - Q_INVOKABLE void setIgnoreAvatars(unsigned int uid, const QScriptValue& ignoreAvatars) { DependencyManager::get()->setIgnoreAvatars(uid, ignoreAvatars); } - Q_INVOKABLE void setIncludeAvatars(unsigned int uid, const QScriptValue& includeAvatars) { DependencyManager::get()->setIncludeAvatars(uid, includeAvatars); } + Q_INVOKABLE void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) { DependencyManager::get()->setIgnoreEntities(uid, ignoreEntities); } + Q_INVOKABLE void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) { DependencyManager::get()->setIncludeEntities(uid, includeEntities); } + Q_INVOKABLE void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) { DependencyManager::get()->setIgnoreOverlays(uid, ignoreOverlays); } + Q_INVOKABLE void setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays) { DependencyManager::get()->setIncludeOverlays(uid, includeOverlays); } + Q_INVOKABLE void setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) { DependencyManager::get()->setIgnoreAvatars(uid, ignoreAvatars); } + Q_INVOKABLE void setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) { DependencyManager::get()->setIncludeAvatars(uid, includeAvatars); } private: const RenderState buildRenderState(const QVariantMap & propMap); diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp index 1ccc27f76d..0814466e4b 100644 --- a/interface/src/raypick/RayPickManager.cpp +++ b/interface/src/raypick/RayPickManager.cpp @@ -125,7 +125,7 @@ void RayPickManager::update() { { QWriteLocker lock(&_addLock); while (!_rayPicksToAdd.isEmpty()) { - QPair> rayPickToAdd = _rayPicksToAdd.dequeue(); + QPair> rayPickToAdd = _rayPicksToAdd.dequeue(); _rayPicks[rayPickToAdd.first] = rayPickToAdd.second; _rayPickLocks[rayPickToAdd.first] = std::make_shared(); } @@ -134,14 +134,14 @@ void RayPickManager::update() { { QWriteLocker lock(&_removeLock); while (!_rayPicksToRemove.isEmpty()) { - unsigned int uid = _rayPicksToRemove.dequeue(); + QUuid uid = _rayPicksToRemove.dequeue(); _rayPicks.remove(uid); _rayPickLocks.remove(uid); } } } -unsigned int RayPickManager::createRayPick(const QVariantMap& rayProps) { +QUuid RayPickManager::createRayPick(const QVariantMap& rayProps) { bool enabled = false; if (rayProps["enabled"].isValid()) { enabled = rayProps["enabled"].toBool(); @@ -173,12 +173,14 @@ unsigned int RayPickManager::createRayPick(const QVariantMap& rayProps) { } QWriteLocker lock(&_addLock); - _rayPicksToAdd.enqueue(QPair>(_nextUID, std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled))); - return _nextUID++; + QUuid id = QUuid::createUuid(); + _rayPicksToAdd.enqueue(QPair>(id, std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled))); + return id; } else { QWriteLocker lock(&_addLock); - _rayPicksToAdd.enqueue(QPair>(_nextUID, std::make_shared(filter, maxDistance, enabled))); - return _nextUID++; + QUuid id = QUuid::createUuid(); + _rayPicksToAdd.enqueue(QPair>(id, std::make_shared(filter, maxDistance, enabled))); + return id; } } else if (rayProps["position"].isValid()) { glm::vec3 position = vec3FromVariant(rayProps["position"]); @@ -189,19 +191,20 @@ unsigned int RayPickManager::createRayPick(const QVariantMap& rayProps) { } QWriteLocker lock(&_addLock); - _rayPicksToAdd.enqueue(QPair>(_nextUID, std::make_shared(position, direction, filter, maxDistance, enabled))); - return _nextUID++; + QUuid id = QUuid::createUuid(); + _rayPicksToAdd.enqueue(QPair>(id, std::make_shared(position, direction, filter, maxDistance, enabled))); + return id; } return 0; } -void RayPickManager::removeRayPick(const unsigned int uid) { +void RayPickManager::removeRayPick(const QUuid uid) { QWriteLocker lock(&_removeLock); _rayPicksToRemove.enqueue(uid); } -void RayPickManager::enableRayPick(const unsigned int uid) { +void RayPickManager::enableRayPick(const QUuid uid) { QReadLocker containsLock(&_containsLock); if (_rayPicks.contains(uid)) { QWriteLocker rayPickLock(_rayPickLocks[uid].get()); @@ -209,7 +212,7 @@ void RayPickManager::enableRayPick(const unsigned int uid) { } } -void RayPickManager::disableRayPick(const unsigned int uid) { +void RayPickManager::disableRayPick(const QUuid uid) { QReadLocker containsLock(&_containsLock); if (_rayPicks.contains(uid)) { QWriteLocker rayPickLock(_rayPickLocks[uid].get()); @@ -217,7 +220,7 @@ void RayPickManager::disableRayPick(const unsigned int uid) { } } -const PickRay RayPickManager::getPickRay(const unsigned int uid) { +const PickRay RayPickManager::getPickRay(const QUuid uid) { QReadLocker containsLock(&_containsLock); if (_rayPicks.contains(uid)) { bool valid; @@ -229,7 +232,7 @@ const PickRay RayPickManager::getPickRay(const unsigned int uid) { return PickRay(); } -const RayPickResult RayPickManager::getPrevRayPickResult(const unsigned int uid) { +const RayPickResult RayPickManager::getPrevRayPickResult(const QUuid uid) { QReadLocker containsLock(&_containsLock); if (_rayPicks.contains(uid)) { QReadLocker lock(_rayPickLocks[uid].get()); @@ -238,7 +241,7 @@ const RayPickResult RayPickManager::getPrevRayPickResult(const unsigned int uid) return RayPickResult(); } -void RayPickManager::setIgnoreEntities(unsigned int uid, const QScriptValue& ignoreEntities) { +void RayPickManager::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) { QReadLocker containsLock(&_containsLock); if (_rayPicks.contains(uid)) { QWriteLocker lock(_rayPickLocks[uid].get()); @@ -246,7 +249,7 @@ void RayPickManager::setIgnoreEntities(unsigned int uid, const QScriptValue& ign } } -void RayPickManager::setIncludeEntities(unsigned int uid, const QScriptValue& includeEntities) { +void RayPickManager::setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) { QReadLocker containsLock(&_containsLock); if (_rayPicks.contains(uid)) { QWriteLocker lock(_rayPickLocks[uid].get()); @@ -254,7 +257,7 @@ void RayPickManager::setIncludeEntities(unsigned int uid, const QScriptValue& in } } -void RayPickManager::setIgnoreOverlays(unsigned int uid, const QScriptValue& ignoreOverlays) { +void RayPickManager::setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) { QReadLocker containsLock(&_containsLock); if (_rayPicks.contains(uid)) { QWriteLocker lock(_rayPickLocks[uid].get()); @@ -262,7 +265,7 @@ void RayPickManager::setIgnoreOverlays(unsigned int uid, const QScriptValue& ign } } -void RayPickManager::setIncludeOverlays(unsigned int uid, const QScriptValue& includeOverlays) { +void RayPickManager::setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays) { QReadLocker containsLock(&_containsLock); if (_rayPicks.contains(uid)) { QWriteLocker lock(_rayPickLocks[uid].get()); @@ -270,7 +273,7 @@ void RayPickManager::setIncludeOverlays(unsigned int uid, const QScriptValue& in } } -void RayPickManager::setIgnoreAvatars(unsigned int uid, const QScriptValue& ignoreAvatars) { +void RayPickManager::setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) { QReadLocker containsLock(&_containsLock); if (_rayPicks.contains(uid)) { QWriteLocker lock(_rayPickLocks[uid].get()); @@ -278,7 +281,7 @@ void RayPickManager::setIgnoreAvatars(unsigned int uid, const QScriptValue& igno } } -void RayPickManager::setIncludeAvatars(unsigned int uid, const QScriptValue& includeAvatars) { +void RayPickManager::setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) { QReadLocker containsLock(&_containsLock); if (_rayPicks.contains(uid)) { QWriteLocker lock(_rayPickLocks[uid].get()); diff --git a/interface/src/raypick/RayPickManager.h b/interface/src/raypick/RayPickManager.h index 47d982494f..27428ab43c 100644 --- a/interface/src/raypick/RayPickManager.h +++ b/interface/src/raypick/RayPickManager.h @@ -58,30 +58,29 @@ class RayPickManager : public QObject, public Dependency { public: void update(); - const PickRay getPickRay(const unsigned int uid); + const PickRay getPickRay(const QUuid uid); public slots: - Q_INVOKABLE unsigned int createRayPick(const QVariantMap& rayProps); - Q_INVOKABLE void removeRayPick(const unsigned int uid); - Q_INVOKABLE void enableRayPick(const unsigned int uid); - Q_INVOKABLE void disableRayPick(const unsigned int uid); - Q_INVOKABLE const RayPickResult getPrevRayPickResult(const unsigned int uid); + Q_INVOKABLE QUuid createRayPick(const QVariantMap& rayProps); + Q_INVOKABLE void removeRayPick(const QUuid uid); + Q_INVOKABLE void enableRayPick(const QUuid uid); + Q_INVOKABLE void disableRayPick(const QUuid uid); + Q_INVOKABLE const RayPickResult getPrevRayPickResult(const QUuid uid); - Q_INVOKABLE void setIgnoreEntities(unsigned int uid, const QScriptValue& ignoreEntities); - Q_INVOKABLE void setIncludeEntities(unsigned int uid, const QScriptValue& includeEntities); - Q_INVOKABLE void setIgnoreOverlays(unsigned int uid, const QScriptValue& ignoreOverlays); - Q_INVOKABLE void setIncludeOverlays(unsigned int uid, const QScriptValue& includeOverlays); - Q_INVOKABLE void setIgnoreAvatars(unsigned int uid, const QScriptValue& ignoreAvatars); - Q_INVOKABLE void setIncludeAvatars(unsigned int uid, const QScriptValue& includeAvatars); + Q_INVOKABLE void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities); + Q_INVOKABLE void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities); + Q_INVOKABLE void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays); + Q_INVOKABLE void setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays); + Q_INVOKABLE void setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars); + Q_INVOKABLE void setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars); private: - QHash> _rayPicks; - QHash> _rayPickLocks; - unsigned int _nextUID { 1 }; // 0 is invalid + QHash> _rayPicks; + QHash> _rayPickLocks; QReadWriteLock _addLock; - QQueue>> _rayPicksToAdd; + QQueue>> _rayPicksToAdd; QReadWriteLock _removeLock; - QQueue _rayPicksToRemove; + QQueue _rayPicksToRemove; QReadWriteLock _containsLock; typedef QHash, QHash> RayPickCache; From 6e78238f588684da0ffe3a7f1a32d86bbec35bb1 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 25 Jul 2017 15:48:41 -0700 Subject: [PATCH 29/42] warning --- .../src/display-plugins/OpenGLDisplayPlugin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index db7c0e4f65..9b3fe10c55 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -629,7 +629,7 @@ void OpenGLDisplayPlugin::compositeLayers() { // Clear the depth framebuffer after drawing the scene so that the HUD elements can depth test against each other render([&](gpu::Batch& batch) { batch.setFramebuffer(_compositeFramebuffer); - batch.clearDepthFramebuffer(UINT32_MAX); + batch.clearDepthFramebuffer((float) UINT32_MAX); }); #ifdef HIFI_ENABLE_NSIGHT_DEBUG @@ -658,7 +658,7 @@ void OpenGLDisplayPlugin::compositeLayers() { // Clear the depth buffer again and draw the pointer last so it's on top of everything render([&](gpu::Batch& batch) { batch.setFramebuffer(_compositeFramebuffer); - batch.clearDepthFramebuffer(UINT32_MAX); + batch.clearDepthFramebuffer((float) UINT32_MAX); }); auto compositorHelper = DependencyManager::get(); From 5e4a83dad97c1898054245c796c7f6b0b5258385 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 26 Jul 2017 17:58:39 -0700 Subject: [PATCH 30/42] defaultRenderStates, handControllerGrab.js, fix teleport.js a little --- interface/src/raypick/LaserPointer.cpp | 163 ++++--- interface/src/raypick/LaserPointer.h | 20 +- interface/src/raypick/LaserPointerManager.cpp | 6 +- interface/src/raypick/LaserPointerManager.h | 4 +- .../LaserPointerScriptingInterface.cpp | 17 +- .../system/controllers/handControllerGrab.js | 443 +++++++----------- scripts/system/controllers/teleport.js | 33 +- 7 files changed, 322 insertions(+), 364 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 76ed632027..23adf5b532 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -13,18 +13,25 @@ #include "Application.h" #include "avatar/AvatarManager.h" -LaserPointer::LaserPointer(const QVariantMap& rayProps, const QHash& renderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) : +LaserPointer::LaserPointer(const QVariantMap& rayProps, const QHash& renderStates, QHash>& defaultRenderStates, + const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) : _renderingEnabled(enabled), _renderStates(renderStates), + _defaultRenderStates(defaultRenderStates), _faceAvatar(faceAvatar), _centerEndY(centerEndY), _lockEnd(lockEnd) { _rayPickUID = DependencyManager::get()->createRayPick(rayProps); - for (auto& state : _renderStates.keys()) { + for (QString& state : _renderStates.keys()) { if (!enabled || state != _currentRenderState) { - disableRenderState(state); + disableRenderState(_renderStates[state]); + } + } + for (QString& state : _defaultRenderStates.keys()) { + if (!enabled || state != _currentRenderState) { + disableRenderState(_defaultRenderStates[state].second); } } } @@ -42,6 +49,17 @@ LaserPointer::~LaserPointer() { qApp->getOverlays().deleteOverlay(renderState.getEndID()); } } + for (QPair& renderState : _defaultRenderStates) { + if (!renderState.second.getStartID().isNull()) { + qApp->getOverlays().deleteOverlay(renderState.second.getStartID()); + } + if (!renderState.second.getPathID().isNull()) { + qApp->getOverlays().deleteOverlay(renderState.second.getPathID()); + } + if (!renderState.second.getEndID().isNull()) { + qApp->getOverlays().deleteOverlay(renderState.second.getEndID()); + } + } } void LaserPointer::enable() { @@ -52,14 +70,24 @@ void LaserPointer::enable() { void LaserPointer::disable() { DependencyManager::get()->disableRayPick(_rayPickUID); _renderingEnabled = false; - if (!_currentRenderState.isEmpty() && _renderStates.contains(_currentRenderState)) { - disableRenderState(_currentRenderState); + if (!_currentRenderState.isEmpty()) { + if (_renderStates.contains(_currentRenderState)) { + disableRenderState(_renderStates[_currentRenderState]); + } + if (_defaultRenderStates.contains(_currentRenderState)) { + disableRenderState(_defaultRenderStates[_currentRenderState].second); + } } } void LaserPointer::setRenderState(const QString& state) { - if (!_currentRenderState.isEmpty() && _renderStates.contains(_currentRenderState)) { - disableRenderState(_currentRenderState); + if (!_currentRenderState.isEmpty()) { + if (_renderStates.contains(_currentRenderState)) { + disableRenderState(_renderStates[_currentRenderState]); + } + if (_defaultRenderStates.contains(_currentRenderState)) { + disableRenderState(_defaultRenderStates[_currentRenderState].second); + } } _currentRenderState = state; } @@ -85,77 +113,90 @@ OverlayID LaserPointer::updateRenderStateOverlay(const OverlayID& id, const QVar return OverlayID(); } -void LaserPointer::disableRenderState(const QString& renderState) { - if (!_renderStates[renderState].getStartID().isNull()) { +void LaserPointer::updateRenderState(const RenderState& renderState, const IntersectionType type, const float distance, const QUuid& objectID, const bool defaultState) { + PickRay pickRay = DependencyManager::get()->getPickRay(_rayPickUID); + if (!renderState.getStartID().isNull()) { + QVariantMap startProps; + startProps.insert("position", vec3toVariant(pickRay.origin)); + startProps.insert("visible", true); + startProps.insert("ignoreRayIntersection", renderState.doesStartIgnoreRays()); + qApp->getOverlays().editOverlay(renderState.getStartID(), startProps); + } + glm::vec3 endVec; + if (defaultState || !_lockEnd || type == IntersectionType::HUD) { + endVec = pickRay.origin + pickRay.direction * distance; + } + else { + if (type == IntersectionType::ENTITY) { + endVec = DependencyManager::get()->getEntityTransform(objectID)[3]; + } + else if (type == IntersectionType::OVERLAY) { + endVec = vec3FromVariant(qApp->getOverlays().getProperty(objectID, "position").value); + } + else if (type == IntersectionType::AVATAR) { + endVec = DependencyManager::get()->getAvatar(objectID)->getPosition(); + } + } + QVariant end = vec3toVariant(endVec); + if (!renderState.getPathID().isNull()) { + QVariantMap pathProps; + pathProps.insert("start", vec3toVariant(pickRay.origin)); + pathProps.insert("end", end); + pathProps.insert("visible", true); + pathProps.insert("ignoreRayIntersection", renderState.doesPathIgnoreRays()); + qApp->getOverlays().editOverlay(renderState.getPathID(), pathProps); + } + if (!renderState.getEndID().isNull()) { + QVariantMap endProps; + if (_centerEndY) { + endProps.insert("position", end); + } + else { + glm::vec3 dim = vec3FromVariant(qApp->getOverlays().getProperty(renderState.getEndID(), "dimensions").value); + endProps.insert("position", vec3toVariant(endVec + glm::vec3(0, 0.5f * dim.y, 0))); + } + if (_faceAvatar) { + glm::quat rotation = glm::inverse(glm::quat_cast(glm::lookAt(endVec, DependencyManager::get()->getMyAvatar()->getPosition(), Vectors::UP))); + endProps.insert("rotation", quatToVariant(glm::quat(glm::radians(glm::vec3(0, glm::degrees(safeEulerAngles(rotation)).y, 0))))); + } + endProps.insert("visible", true); + endProps.insert("ignoreRayIntersection", renderState.doesEndIgnoreRays()); + qApp->getOverlays().editOverlay(renderState.getEndID(), endProps); + } +} + +void LaserPointer::disableRenderState(const RenderState& renderState) { + if (!renderState.getStartID().isNull()) { QVariantMap startProps; startProps.insert("visible", false); startProps.insert("ignoreRayIntersection", true); - qApp->getOverlays().editOverlay(_renderStates[renderState].getStartID(), startProps); + qApp->getOverlays().editOverlay(renderState.getStartID(), startProps); } - if (!_renderStates[renderState].getPathID().isNull()) { + if (!renderState.getPathID().isNull()) { QVariantMap pathProps; pathProps.insert("visible", false); pathProps.insert("ignoreRayIntersection", true); - qApp->getOverlays().editOverlay(_renderStates[renderState].getPathID(), pathProps); + qApp->getOverlays().editOverlay(renderState.getPathID(), pathProps); } - if (!_renderStates[renderState].getEndID().isNull()) { + if (!renderState.getEndID().isNull()) { QVariantMap endProps; endProps.insert("visible", false); endProps.insert("ignoreRayIntersection", true); - qApp->getOverlays().editOverlay(_renderStates[renderState].getEndID(), endProps); + qApp->getOverlays().editOverlay(renderState.getEndID(), endProps); } } void LaserPointer::update() { RayPickResult prevRayPickResult = DependencyManager::get()->getPrevRayPickResult(_rayPickUID); if (_renderingEnabled && !_currentRenderState.isEmpty() && _renderStates.contains(_currentRenderState) && prevRayPickResult.type != IntersectionType::NONE) { - PickRay pickRay = DependencyManager::get()->getPickRay(_rayPickUID); - if (!_renderStates[_currentRenderState].getStartID().isNull()) { - QVariantMap startProps; - startProps.insert("position", vec3toVariant(pickRay.origin)); - startProps.insert("visible", true); - startProps.insert("ignoreRayIntersection", _renderStates[_currentRenderState].doesStartIgnoreRays()); - qApp->getOverlays().editOverlay(_renderStates[_currentRenderState].getStartID(), startProps); - } - glm::vec3 endVec; - if (!_lockEnd || prevRayPickResult.type == IntersectionType::HUD) { - endVec = pickRay.origin + pickRay.direction * prevRayPickResult.distance; - } else { - if (prevRayPickResult.type == IntersectionType::ENTITY) { - endVec = DependencyManager::get()->getEntityTransform(prevRayPickResult.objectID)[3]; - } else if (prevRayPickResult.type == IntersectionType::OVERLAY) { - endVec = vec3FromVariant(qApp->getOverlays().getProperty(prevRayPickResult.objectID, "position").value); - } else if (prevRayPickResult.type == IntersectionType::AVATAR) { - endVec = DependencyManager::get()->getAvatar(prevRayPickResult.objectID)->getPosition(); - } - } - QVariant end = vec3toVariant(endVec); - if (!_renderStates[_currentRenderState].getPathID().isNull()) { - QVariantMap pathProps; - pathProps.insert("start", vec3toVariant(pickRay.origin)); - pathProps.insert("end", end); - pathProps.insert("visible", true); - pathProps.insert("ignoreRayIntersection", _renderStates[_currentRenderState].doesPathIgnoreRays()); - qApp->getOverlays().editOverlay(_renderStates[_currentRenderState].getPathID(), pathProps); - } - if (!_renderStates[_currentRenderState].getEndID().isNull()) { - QVariantMap endProps; - if (_centerEndY) { - endProps.insert("position", end); - } else { - glm::vec3 dim = vec3FromVariant(qApp->getOverlays().getProperty(_renderStates[_currentRenderState].getEndID(), "dimensions").value); - endProps.insert("position", vec3toVariant(endVec + glm::vec3(0, 0.5f * dim.y, 0))); - } - if (_faceAvatar) { - glm::quat rotation = glm::inverse(glm::quat_cast(glm::lookAt(endVec, DependencyManager::get()->getMyAvatar()->getPosition(), Vectors::UP))); - endProps.insert("rotation", quatToVariant(glm::quat(glm::radians(glm::vec3(0, glm::degrees(safeEulerAngles(rotation)).y, 0))))); - } - endProps.insert("visible", true); - endProps.insert("ignoreRayIntersection", _renderStates[_currentRenderState].doesEndIgnoreRays()); - qApp->getOverlays().editOverlay(_renderStates[_currentRenderState].getEndID(), endProps); - } - } else { - disableRenderState(_currentRenderState); + updateRenderState(_renderStates[_currentRenderState], prevRayPickResult.type, prevRayPickResult.distance, prevRayPickResult.objectID, false); + disableRenderState(_defaultRenderStates[_currentRenderState].second); + } else if (_renderingEnabled && !_currentRenderState.isEmpty() && _defaultRenderStates.contains(_currentRenderState)) { + disableRenderState(_renderStates[_currentRenderState]); + updateRenderState(_defaultRenderStates[_currentRenderState].second, IntersectionType::NONE, _defaultRenderStates[_currentRenderState].first, QUuid(), true); + } else if (!_currentRenderState.isEmpty()) { + disableRenderState(_renderStates[_currentRenderState]); + disableRenderState(_defaultRenderStates[_currentRenderState].second); } } diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index b1b8be23e4..34d9ee50df 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -26,15 +26,15 @@ public: RenderState() {} RenderState(const OverlayID& startID, const OverlayID& pathID, const OverlayID& endID); - const OverlayID& getStartID() { return _startID; } - const OverlayID& getPathID() { return _pathID; } - const OverlayID& getEndID() { return _endID; } + const OverlayID& getStartID() const { return _startID; } + const OverlayID& getPathID() const { return _pathID; } + const OverlayID& getEndID() const { return _endID; } void setStartID(const OverlayID& startID) { _startID = startID; } void setPathID(const OverlayID& pathID) { _pathID = pathID; } void setEndID(const OverlayID& endID) { _endID = endID; } - const bool& doesStartIgnoreRays() { return _startIgnoreRays; } - const bool& doesPathIgnoreRays() { return _pathIgnoreRays; } - const bool& doesEndIgnoreRays() { return _endIgnoreRays; } + const bool& doesStartIgnoreRays() const { return _startIgnoreRays; } + const bool& doesPathIgnoreRays() const { return _pathIgnoreRays; } + const bool& doesEndIgnoreRays() const { return _endIgnoreRays; } private: OverlayID _startID; @@ -49,8 +49,8 @@ private: class LaserPointer { public: - LaserPointer(const QVariantMap& rayProps, const QHash& renderStates, const bool faceAvatar, const bool centerEndY, - const bool lockEnd, const bool enabled); + LaserPointer(const QVariantMap& rayProps, const QHash& renderStates, QHash>& defaultRenderStates, + const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled); ~LaserPointer(); QUuid getRayUID() { return _rayPickUID; } @@ -74,6 +74,7 @@ private: bool _renderingEnabled; QString _currentRenderState { "" }; QHash _renderStates; + QHash> _defaultRenderStates; bool _faceAvatar; bool _centerEndY; bool _lockEnd; @@ -81,7 +82,8 @@ private: QUuid _rayPickUID; OverlayID updateRenderStateOverlay(const OverlayID& id, const QVariant& props); - void disableRenderState(const QString& renderState); + void updateRenderState(const RenderState& renderState, const IntersectionType type, const float distance, const QUuid& objectID, const bool defaultState); + void disableRenderState(const RenderState& renderState); }; #endif // hifi_LaserPointer_h diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp index 2b4d7d096b..b05f56fa53 100644 --- a/interface/src/raypick/LaserPointerManager.cpp +++ b/interface/src/raypick/LaserPointerManager.cpp @@ -12,9 +12,9 @@ #include "LaserPointer.h" #include "RayPick.h" -QUuid LaserPointerManager::createLaserPointer(const QVariantMap& rayProps, const QHash& renderStates, const bool faceAvatar, const bool centerEndY, - const bool lockEnd, const bool enabled) { - std::shared_ptr laserPointer = std::make_shared(rayProps, renderStates, faceAvatar, centerEndY, lockEnd, enabled); +QUuid LaserPointerManager::createLaserPointer(const QVariantMap& rayProps, const QHash& renderStates, QHash>& defaultRenderStates, + const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) { + std::shared_ptr laserPointer = std::make_shared(rayProps, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, enabled); if (laserPointer->getRayUID() != 0) { QWriteLocker lock(&_addLock); QUuid id = QUuid::createUuid(); diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h index b239fc1514..db035b197f 100644 --- a/interface/src/raypick/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -25,8 +25,8 @@ class LaserPointerManager : public Dependency { SINGLETON_DEPENDENCY public: - QUuid createLaserPointer(const QVariantMap& rayProps, const QHash& renderStates, const bool faceAvatar, const bool centerEndY, - const bool lockEnd, const bool enabled); + QUuid createLaserPointer(const QVariantMap& rayProps, const QHash& renderStates, QHash>& defaultRenderStates, + const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled); void removeLaserPointer(const QUuid uid); void enableLaserPointer(const QUuid uid); void disableLaserPointer(const QUuid uid); diff --git a/interface/src/raypick/LaserPointerScriptingInterface.cpp b/interface/src/raypick/LaserPointerScriptingInterface.cpp index 7cae7ccdc4..9bda37f26f 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.cpp +++ b/interface/src/raypick/LaserPointerScriptingInterface.cpp @@ -54,7 +54,22 @@ QUuid LaserPointerScriptingInterface::createLaserPointer(const QVariant& propert } } - return DependencyManager::get()->createLaserPointer(propertyMap, renderStates, faceAvatar, centerEndY, lockEnd, enabled); + QHash> defaultRenderStates; + if (propertyMap["defaultRenderStates"].isValid()) { + QList renderStateVariants = propertyMap["defaultRenderStates"].toList(); + for (QVariant& renderStateVariant : renderStateVariants) { + if (renderStateVariant.isValid()) { + QVariantMap renderStateMap = renderStateVariant.toMap(); + if (renderStateMap["name"].isValid() && renderStateMap["distance"].isValid()) { + QString name = renderStateMap["name"].toString(); + float distance = renderStateMap["distance"].toFloat(); + defaultRenderStates[name] = QPair(distance, buildRenderState(renderStateMap)); + } + } + } + } + + return DependencyManager::get()->createLaserPointer(propertyMap, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, enabled); } void LaserPointerScriptingInterface::editRenderState(QUuid uid, const QString& renderState, const QVariant& properties) { diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index 04921fe14d..96d2b0d3fa 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -64,8 +64,6 @@ var HAPTIC_STYLUS_DURATION = 20.0; var HAPTIC_LASER_UI_STRENGTH = 1.0; var HAPTIC_LASER_UI_DURATION = 20.0; -var HAND_HEAD_MIX_RATIO = 0.0; // 0 = only use hands for search/move. 1 = only use head for search/move. - var PICK_WITH_HAND_RAY = true; var EQUIP_SPHERE_SCALE_FACTOR = 0.65; @@ -157,7 +155,6 @@ var INCHES_TO_METERS = 1.0 / 39.3701; // these control how long an abandoned pointer line or action will hang around var ACTION_TTL = 15; // seconds var ACTION_TTL_REFRESH = 5; -var PICKS_PER_SECOND_PER_HAND = 60; var MSECS_PER_SEC = 1000.0; var GRABBABLE_PROPERTIES = [ "position", @@ -448,15 +445,6 @@ function entityHasActions(entityID) { return Entities.getActionIDs(entityID).length > 0; } -function findRayIntersection(pickRay, precise, include, exclude) { - var entities = Entities.findRayIntersection(pickRay, precise, include, exclude, true); - var overlays = Overlays.findRayIntersection(pickRay, precise, [], [HMD.tabletID]); - if (!overlays.intersects || (entities.intersects && (entities.distance <= overlays.distance))) { - return entities; - } - return overlays; -} - function entityIsGrabbedByOther(entityID) { // by convention, a distance grab sets the tag of its action to be grab-*owner-session-id*. var actionIDs = Entities.getActionIDs(entityID); @@ -1043,6 +1031,74 @@ function getControllerJointIndex(hand) { // global EquipHotspotBuddy instance var equipHotspotBuddy = new EquipHotspotBuddy(); +var halfPath = { + type: "line3d", + color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE, + visible: true, + alpha: 1, + solid: true, + glow: 1.0, + lineWidth: 5, + ignoreRayIntersection: true, // always ignore this + drawInFront: true, // Even when burried inside of something, show it. + parentID: AVATAR_SELF_ID +} +var halfEnd = { + type: "sphere", + solid: true, + color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE, + alpha: 0.9, + ignoreRayIntersection: true, + drawInFront: true, // Even when burried inside of something, show it. + visible: true +} +var fullPath = { + type: "line3d", + color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE, + visible: true, + alpha: 1, + solid: true, + glow: 1.0, + lineWidth: 5, + ignoreRayIntersection: true, // always ignore this + drawInFront: true, // Even when burried inside of something, show it. + parentID: AVATAR_SELF_ID +} +var fullEnd = { + type: "sphere", + solid: true, + color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE, + alpha: 0.9, + ignoreRayIntersection: true, + drawInFront: true, // Even when burried inside of something, show it. + visible: true +} +var holdPath = { + type: "line3d", + color: COLORS_GRAB_DISTANCE_HOLD, + visible: true, + alpha: 1, + solid: true, + glow: 1.0, + lineWidth: 5, + ignoreRayIntersection: true, // always ignore this + drawInFront: true, // Even when burried inside of something, show it. + parentID: AVATAR_SELF_ID +} + +var renderStates = [{name: "half", path: halfPath, end: halfEnd}, + {name: "full", path: fullPath, end: fullEnd}, + {name: "hold", path: holdPath}]; +var headRenderStates = [{name: "half", end: halfEnd}, + {name: "full", end: fullEnd}, + {name: "hold", path: holdPath}]; + +// how far from camera to search intersection? +var DEFAULT_SEARCH_SPHERE_DISTANCE = 1000; +var defaultRenderStates = [{name: "half", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: halfPath}, + {name: "full", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: fullPath}, + {name: "hold", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: holdPath}]; + function MyController(hand) { this.hand = hand; this.autoUnequipCounter = 0; @@ -1091,7 +1147,6 @@ function MyController(hand) { this.grabbedThingID = null; // on this entity. this.grabbedOverlay = null; this.state = STATE_OFF; - this.pointer = null; // entity-id of line object this.triggerValue = 0; // rolling average of trigger value this.triggerClicked = false; @@ -1100,18 +1155,33 @@ function MyController(hand) { this.rawThumbValue = 0; // for visualizations - this.overlayLine = null; - this.searchSphere = null; - this.otherGrabbingLine = null; + this.halfEnd = halfEnd; + this.fullEnd = fullEnd; + this.laserPointer = LaserPointers.createLaserPointer({ + joint: (hand == RIGHT_HAND) ? "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", + filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, + maxDistance: PICK_MAX_DISTANCE, + posOffset: getGrabPointSphereOffset(this.handToController()), + renderStates: renderStates, + faceAvatar: true, + defaultRenderStates: defaultRenderStates + }); + this.headLaserPointer = LaserPointers.createLaserPointer({ + joint: "Avatar", + filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, + maxDistance: PICK_MAX_DISTANCE, + renderStates: headRenderStates, + faceAvatar: true, + defaultRenderStates: defaultRenderStates + }); + LaserPointers.setIgnoreOverlays(this.laserPointer, [HMD.tabletID]); + LaserPointers.setIgnoreOverlays(this.headLaserPointer, [HMD.tabletID]); this.otherGrabbingUUID = null; this.waitForTriggerRelease = false; - // how far from camera to search intersection? - var DEFAULT_SEARCH_SPHERE_DISTANCE = 1000; this.intersectionDistance = 0.0; - this.searchSphereDistance = DEFAULT_SEARCH_SPHERE_DISTANCE; this.ignoreIK = false; this.offsetPosition = Vec3.ZERO; @@ -1292,41 +1362,6 @@ function MyController(hand) { } }; - this.searchSphereOn = function(location, size, color) { - - var rotation = Quat.lookAt(location, Camera.getPosition(), Vec3.UP); - var brightColor = colorPow(color, 0.06); - if (this.searchSphere === null) { - var sphereProperties = { - name: "searchSphere", - position: location, - rotation: rotation, - outerRadius: size * 1.2, - innerColor: brightColor, - outerColor: color, - innerAlpha: 0.9, - outerAlpha: 0.0, - solid: true, - ignoreRayIntersection: true, - drawInFront: true, // Even when burried inside of something, show it. - visible: true - }; - this.searchSphere = Overlays.addOverlay("circle3d", sphereProperties); - } else { - Overlays.editOverlay(this.searchSphere, { - position: location, - rotation: rotation, - innerColor: brightColor, - outerColor: color, - innerAlpha: 1.0, - outerAlpha: 0.0, - outerRadius: size * 1.2, - visible: true, - ignoreRayIntersection: true - }); - } - }; - this.showStylus = function() { if (this.stylus) { return; @@ -1362,97 +1397,32 @@ function MyController(hand) { this.stylus = null; }; - this.overlayLineOn = function(closePoint, farPoint, color, farParentID) { - if (this.overlayLine === null) { - var lineProperties = { - name: "line", - glow: 1.0, - lineWidth: 5, - start: closePoint, - end: farPoint, - color: color, - ignoreRayIntersection: true, // always ignore this - drawInFront: true, // Even when burried inside of something, show it. - visible: true, - alpha: 1, - parentID: AVATAR_SELF_ID, - parentJointIndex: MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? - "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : - "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND"), - endParentID: farParentID - }; - this.overlayLine = Overlays.addOverlay("line3d", lineProperties); - - } else { - if (farParentID && farParentID != NULL_UUID) { - Overlays.editOverlay(this.overlayLine, { - color: color, - endParentID: farParentID - }); - } else { - Overlays.editOverlay(this.overlayLine, { - length: Vec3.distance(farPoint, closePoint), - color: color, - endParentID: farParentID - }); - } - } - }; - - this.searchIndicatorOn = function(distantPickRay) { - var handPosition = distantPickRay.origin; + this.updateLaserPointer = function() { var SEARCH_SPHERE_SIZE = 0.011; - var SEARCH_SPHERE_FOLLOW_RATE = 0.50; - - if (this.intersectionDistance > 0) { - // If we hit something with our pick ray, move the search sphere toward that distance - this.searchSphereDistance = this.searchSphereDistance * SEARCH_SPHERE_FOLLOW_RATE + - this.intersectionDistance * (1.0 - SEARCH_SPHERE_FOLLOW_RATE); + var radius = 1.2 * SEARCH_SPHERE_SIZE * this.intersectionDistance; + var dim = {x: radius, y: radius, z: radius}; + var mode = "hold"; + if (this.state !== STATE_DISTANCE_HOLDING && this.state !== STATE_DISTANCE_ROTATING) { + mode = (this.triggerSmoothedGrab() || this.secondarySqueezed()) ? "full" : "half"; } - var searchSphereLocation = Vec3.sum(distantPickRay.origin, - Vec3.multiply(distantPickRay.direction, this.searchSphereDistance)); - this.searchSphereOn(searchSphereLocation, SEARCH_SPHERE_SIZE * this.searchSphereDistance, - (this.triggerSmoothedGrab() || this.secondarySqueezed()) ? - COLORS_GRAB_SEARCHING_FULL_SQUEEZE : - COLORS_GRAB_SEARCHING_HALF_SQUEEZE); - if (PICK_WITH_HAND_RAY) { - this.overlayLineOn(handPosition, searchSphereLocation, - (this.triggerSmoothedGrab() || this.secondarySqueezed()) ? - COLORS_GRAB_SEARCHING_FULL_SQUEEZE : - COLORS_GRAB_SEARCHING_HALF_SQUEEZE); + var laserPointerID = PICK_WITH_HAND_RAY ? this.laserPointer : this.headLaserPointer; + if (mode === "full") { + var fullEndToEdit = PICK_WITH_HAND_RAY ? this.fullEnd : fullEnd; + fullEndToEdit.dimensions = dim; + LaserPointers.editRenderState(laserPointerID, mode, {path: fullPath, end: fullEndToEdit}); + } else if (mode === "half") { + var halfEndToEdit = PICK_WITH_HAND_RAY ? this.halfEnd : halfEnd; + halfEndToEdit.dimensions = dim; + LaserPointers.editRenderState(laserPointerID, mode, {path: halfPath, end: halfEndToEdit}); } + LaserPointers.enableLaserPointer(laserPointerID); + LaserPointers.setRenderState(laserPointerID, mode); }; - // Turns off indicators used for searching. Overlay line and sphere. - this.searchIndicatorOff = function() { - this.searchSphereOff(); - if (PICK_WITH_HAND_RAY) { - this.overlayLineOff(); - } - }; - - this.otherGrabbingLineOn = function(avatarPosition, entityPosition, color) { - if (this.otherGrabbingLine === null) { - var lineProperties = { - lineWidth: 5, - start: avatarPosition, - end: entityPosition, - color: color, - glow: 1.0, - ignoreRayIntersection: true, - drawInFront: true, - visible: true, - alpha: 1 - }; - this.otherGrabbingLine = Overlays.addOverlay("line3d", lineProperties); - } else { - Overlays.editOverlay(this.otherGrabbingLine, { - start: avatarPosition, - end: entityPosition, - color: color - }); - } + this.laserPointerOff = function() { + var laserPointerID = PICK_WITH_HAND_RAY ? this.laserPointer : this.headLaserPointer; + LaserPointers.disableLaserPointer(laserPointerID); }; this.evalLightWorldTransform = function(modelPos, modelRot) { @@ -1475,42 +1445,9 @@ function MyController(hand) { }; }; - this.lineOff = function() { - if (this.pointer !== null) { - Entities.deleteEntity(this.pointer); - } - this.pointer = null; - }; - - this.overlayLineOff = function() { - if (this.overlayLine !== null) { - Overlays.deleteOverlay(this.overlayLine); - } - this.overlayLine = null; - }; - - this.searchSphereOff = function() { - if (this.searchSphere !== null) { - Overlays.deleteOverlay(this.searchSphere); - this.searchSphere = null; - this.searchSphereDistance = DEFAULT_SEARCH_SPHERE_DISTANCE; - this.intersectionDistance = 0.0; - } - }; - - this.otherGrabbingLineOff = function() { - if (this.otherGrabbingLine !== null) { - Overlays.deleteOverlay(this.otherGrabbingLine); - } - this.otherGrabbingLine = null; - }; - this.turnOffVisualizations = function() { - this.overlayLineOff(); this.grabPointSphereOff(); - this.lineOff(); - this.searchSphereOff(); - this.otherGrabbingLineOff(); + this.laserPointerOff(); restore2DMode(); }; @@ -1803,9 +1740,9 @@ function MyController(hand) { // Always showing lasers while in edit mode and hands/stylus is not active. var rayPickInfo = this.calcRayPickInfo(this.hand); this.intersectionDistance = (rayPickInfo.entityID || rayPickInfo.overlayID) ? rayPickInfo.distance : 0; - this.searchIndicatorOn(rayPickInfo.searchRay); + this.updateLaserPointer(); } else { - this.searchIndicatorOff(); + this.laserPointerOff(); } }; @@ -1846,27 +1783,18 @@ function MyController(hand) { // Performs ray pick test from the hand controller into the world // @param {number} which hand to use, RIGHT_HAND or LEFT_HAND - // @param {object} if set, use this as as the pick ray, expects origin, direction, and length fields. // @returns {object} returns object with two keys entityID and distance // - this.calcRayPickInfo = function(hand, pickRayOverride) { + this.calcRayPickInfo = function(hand) { + var controllerLocation = getControllerWorldLocation(this.handToController(), true); + var worldHandPosition = controllerLocation.position; + var worldHandRotation = controllerLocation.orientation; - var pickRay; - if (pickRayOverride) { - pickRay = pickRayOverride; - } else { - var controllerLocation = getControllerWorldLocation(this.handToController(), true); - var worldHandPosition = controllerLocation.position; - var worldHandRotation = controllerLocation.orientation; - - pickRay = { - origin: PICK_WITH_HAND_RAY ? worldHandPosition : Camera.position, - direction: PICK_WITH_HAND_RAY ? Quat.getUp(worldHandRotation) : Vec3.mix(Quat.getUp(worldHandRotation), - Quat.getFront(Camera.orientation), - HAND_HEAD_MIX_RATIO), - length: PICK_MAX_DISTANCE - }; - } + var pickRay = { + origin: PICK_WITH_HAND_RAY ? worldHandPosition : MyAvatar.getHeadPosition(), + direction: PICK_WITH_HAND_RAY ? Quat.getUp(worldHandRotation) : Quat.getFront(Camera.orientation), + length: PICK_MAX_DISTANCE + }; var result = { entityID: null, @@ -1875,28 +1803,17 @@ function MyController(hand) { distance: PICK_MAX_DISTANCE }; - var now = Date.now(); - if (now - this.lastPickTime < MSECS_PER_SEC / PICKS_PER_SECOND_PER_HAND) { - return result; - } - this.lastPickTime = now; + var laserPointerID = PICK_WITH_HAND_RAY ? this.laserPointer : this.headLaserPointer; + var intersection = LaserPointers.getPrevRayPickResult(laserPointerID); - var intersection; - if (USE_BLACKLIST === true && blacklist.length !== 0) { - intersection = findRayIntersection(pickRay, true, [], blacklist, true); - } else { - intersection = findRayIntersection(pickRay, true, [], [], true); - } - - if (intersection.intersects) { + if (intersection.type != RayPick.INTERSECTED_NONE) { return { - entityID: intersection.entityID, - overlayID: intersection.overlayID, + entityID: intersection.type == RayPick.INTERSECTED_ENTITY ? intersection.objectID : null, + overlayID: intersection.type == RayPick.INTERSECTED_OVERLAY ? intersection.objectID : null, searchRay: pickRay, - distance: Vec3.distance(pickRay.origin, intersection.intersection), + distance: intersection.distance, intersection: intersection.intersection, - normal: intersection.surfaceNormal, - properties: intersection.properties + normal: intersection.surfaceNormal }; } else { return result; @@ -2168,7 +2085,6 @@ function MyController(hand) { var rayPickInfo = this.calcRayPickInfo(this.hand); if (rayPickInfo.entityID || rayPickInfo.overlayID) { this.intersectionDistance = rayPickInfo.distance; - this.searchSphereDistance = this.intersectionDistance; } }; @@ -2293,7 +2209,7 @@ function MyController(hand) { } if (isInEditMode()) { - this.searchIndicatorOn(rayPickInfo.searchRay); + this.updateLaserPointer(); if (this.triggerSmoothedGrab()) { if (!this.editTriggered){ if (rayPickInfo.entityID) { @@ -2326,7 +2242,7 @@ function MyController(hand) { } else { // potentialFarTriggerEntity = entity; } - this.otherGrabbingLineOff(); + this.laserPointerOff(); } else if (this.entityIsDistanceGrabbable(rayPickInfo.entityID, handPosition)) { if (this.triggerSmoothedGrab() && !isEditing() && farGrabEnabled && farSearching) { this.grabbedThingID = entity; @@ -2341,26 +2257,18 @@ function MyController(hand) { } else { // potentialFarGrabEntity = entity; } - this.otherGrabbingLineOff(); + this.laserPointerOff(); } else if (this.otherGrabbingUUID !== null) { if (this.triggerSmoothedGrab() && !isEditing() && farGrabEnabled && farSearching) { - var avatar = AvatarList.getAvatar(this.otherGrabbingUUID); - var IN_FRONT_OF_AVATAR = { x: 0, y: 0.2, z: 0.4 }; // Up from hips and in front of avatar. - var startPosition = Vec3.sum(avatar.position, Vec3.multiplyQbyV(avatar.rotation, IN_FRONT_OF_AVATAR)); - var rayHitProps = entityPropertiesCache.getProps(rayPickInfo.entityID); - var finishPisition = Vec3.sum(rayHitProps.position, // Entity's centroid. - Vec3.multiplyQbyV(rayHitProps.rotation, - Vec3.multiplyVbyV(rayHitProps.dimensions, - Vec3.subtract(DEFAULT_REGISTRATION_POINT, rayHitProps.registrationPoint)))); - this.otherGrabbingLineOn(startPosition, finishPisition, COLORS_GRAB_DISTANCE_HOLD); + this.updateLaserPointer(); } else { - this.otherGrabbingLineOff(); + this.laserPointerOff(); } } else { - this.otherGrabbingLineOff(); + this.laserPointerOff(); } } else { - this.otherGrabbingLineOff(); + this.laserPointerOff(); } this.updateEquipHaptics(potentialEquipHotspot, handPosition); @@ -2372,7 +2280,7 @@ function MyController(hand) { } if (farGrabEnabled && farSearching) { - this.searchIndicatorOn(rayPickInfo.searchRay); + this.updateLaserPointer(); } Reticle.setVisible(false); }; @@ -2702,7 +2610,7 @@ function MyController(hand) { y: 0.0, z: objDistance }); - var change = Vec3.multiply(Vec3.subtract(before, after), HAND_HEAD_MIX_RATIO); + var change = Vec3.subtract(before, after) * (PICK_WITH_HAND_RAY ? 0.0 : 1.0); this.currentCameraOrientation = Camera.orientation; this.currentObjectPosition = Vec3.sum(this.currentObjectPosition, change); } @@ -2711,11 +2619,7 @@ function MyController(hand) { this.maybeScale(grabbedProperties); // visualizations - var rayPickInfo = this.calcRayPickInfo(this.hand); - this.overlayLineOn(rayPickInfo.searchRay.origin, - Vec3.subtract(grabbedProperties.position, this.offsetPosition), - COLORS_GRAB_DISTANCE_HOLD, - this.grabbedThingID); + this.updateLaserPointer(); var distanceToObject = Vec3.length(Vec3.subtract(MyAvatar.position, this.currentObjectPosition)); @@ -2822,9 +2726,7 @@ function MyController(hand) { this.getOtherHandController().offsetPosition = Vec3.multiplyQbyV(controllerRotationDelta, this.getOtherHandController().offsetPosition); - var rayPickInfo = this.calcRayPickInfo(this.hand); - this.overlayLineOn(rayPickInfo.searchRay.origin, Vec3.subtract(grabbedProperties.position, this.offsetPosition), - COLORS_GRAB_DISTANCE_HOLD, this.grabbedThingID); + this.updateLaserPointer(); this.previousWorldControllerRotation = worldControllerRotation; }; @@ -2908,10 +2810,7 @@ function MyController(hand) { this.nearGrabbingEnter = function() { this.grabPointSphereOff(); - this.lineOff(); - this.overlayLineOff(); - this.searchSphereOff(); - this.otherGrabbingLineOff(); + this.laserPointerOff(); this.dropGestureReset(); this.clearEquipHaptics(); @@ -3415,28 +3314,18 @@ function MyController(hand) { return; } - var pickRay = { - origin: getControllerWorldLocation(this.handToController(), false).position, - direction: Quat.getUp(getControllerWorldLocation(this.handToController(), false).orientation) - }; - - var now = Date.now(); - if (now - this.lastPickTime > MSECS_PER_SEC / PICKS_PER_SECOND_PER_HAND) { - var intersection = findRayIntersection(pickRay, true, [], [], true); - if (intersection.accurate || intersection.overlayID) { - this.lastPickTime = now; - if (intersection.entityID != this.grabbedThingID) { - this.callEntityMethodOnGrabbed("stopFarTrigger"); - this.grabbedThingID = null; - this.setState(STATE_OFF, "laser moved off of entity"); - return; - } - if (intersection.intersects) { - this.intersectionDistance = Vec3.distance(pickRay.origin, intersection.intersection); - } - if (farGrabEnabled) { - this.searchIndicatorOn(pickRay); - } + var laserPointerID = PICK_WITH_HAND_RAY ? this.laserPointer : this.headLaserPointer; + var intersection = LaserPointers.getPrevRayPickResult(laserPointerID); + if (intersection.type != RayPick.INTERSECTED_NONE) { + if (intersection.objectID != this.grabbedThingID) { + this.callEntityMethodOnGrabbed("stopFarTrigger"); + this.grabbedThingID = null; + this.setState(STATE_OFF, "laser moved off of entity"); + return; + } + this.intersectionDistance = intersection.distance; + if (farGrabEnabled) { + this.updateLaserPointer(); } } @@ -3444,14 +3333,7 @@ function MyController(hand) { }; this.offEnter = function() { - // Reuse the existing search distance if lasers were active since - // they will be shown in OFF state while in edit mode. - var existingSearchDistance = this.searchSphereDistance; this.release(); - - if (isInEditMode()) { - this.searchSphereDistance = existingSearchDistance; - } }; this.entityLaserTouchingEnter = function() { @@ -3558,7 +3440,7 @@ function MyController(hand) { this.intersectionDistance = intersectInfo.distance; if (this.state == STATE_ENTITY_LASER_TOUCHING) { - this.searchIndicatorOn(intersectInfo.searchRay); + this.updateLaserPointer(); } Reticle.setVisible(false); } else { @@ -3686,7 +3568,7 @@ function MyController(hand) { this.intersectionDistance = intersectInfo.distance; if (this.state == STATE_OVERLAY_LASER_TOUCHING) { - this.searchIndicatorOn(intersectInfo.searchRay); + this.updateLaserPointer(); } Reticle.setVisible(false); } else { @@ -3829,7 +3711,8 @@ function MyController(hand) { this.release(); this.grabPointSphereOff(); this.hideStylus(); - this.overlayLineOff(); + LaserPointers.removeLaserPointer(this.laserPointer); + LaserPointers.removeLaserPointer(this.headLaserPointer); }; this.thisHandIsParent = function(props) { @@ -3880,8 +3763,7 @@ function MyController(hand) { children = children.concat(Entities.getChildrenIDsOfJoint(AVATAR_SELF_ID, controllerCRJointIndex)); children.forEach(function(childID) { - if (childID !== _this.stylus && - childID !== _this.overlayLine) { + if (childID !== _this.stylus) { // we appear to be holding something and this script isn't in a state that would be holding something. // unhook it. if we previously took note of this entity's parent, put it back where it was. This // works around some problems that happen when more than one hand or avatar is passing something around. @@ -3995,6 +3877,15 @@ Messages.subscribe('Hifi-Hand-RayPick-Blacklist'); Messages.subscribe('Hifi-Object-Manipulation'); Messages.subscribe('Hifi-Hand-Drop'); +var setBlacklist = function() { + if (USE_BLACKLIST) { + LaserPointers.setIgnoreEntities(leftController.laserPointer, blacklist); + LaserPointers.setIgnoreEntities(leftController.headLaserPointer, blacklist); + LaserPointers.setIgnoreEntities(rightController.laserPointer, blacklist); + LaserPointers.setIgnoreEntities(rightController.headLaserPointer, blacklist); + } +} + var handleHandMessages = function(channel, message, sender) { var data; if (sender === MyAvatar.sessionUUID) { @@ -4069,10 +3960,12 @@ var handleHandMessages = function(channel, message, sender) { if (action === 'add' && index === -1) { blacklist.push(id); + setBlacklist(); } if (action === 'remove') { if (index > -1) { blacklist.splice(index, 1); + setBlacklist(); } } diff --git a/scripts/system/controllers/teleport.js b/scripts/system/controllers/teleport.js index fc22d21089..f09cd07184 100644 --- a/scripts/system/controllers/teleport.js +++ b/scripts/system/controllers/teleport.js @@ -105,6 +105,9 @@ var teleportRenderStates = [{name: "cancel", path: cancelPath, end: cancelEnd}, {name: "teleport", path: teleportPath, end: teleportEnd}, {name: "seat", path: seatPath, end: seatEnd}]; +var DEFAULT_DISTANCE = 50; +var teleportDefaultRenderStates = [{name: "cancel", distance: DEFAULT_DISTANCE, path: cancelPath}]; + function ThumbPad(hand) { this.hand = hand; var _thisPad = this; @@ -157,7 +160,8 @@ function Teleporter() { filter: RayPick.PICK_ENTITIES, faceAvatar: true, centerEndY: false, - renderStates: teleportRenderStates + renderStates: teleportRenderStates, + defaultRenderStates: teleportDefaultRenderStates }); this.teleportRayLeftInvisible = LaserPointers.createLaserPointer({ joint: "LeftHand", @@ -171,7 +175,8 @@ function Teleporter() { filter: RayPick.PICK_ENTITIES, faceAvatar: true, centerEndY: false, - renderStates: teleportRenderStates + renderStates: teleportRenderStates, + defaultRenderStates: teleportDefaultRenderStates }); this.teleportRayRightInvisible = LaserPointers.createLaserPointer({ joint: "RightHand", @@ -186,7 +191,8 @@ function Teleporter() { filter: RayPick.PICK_ENTITIES, faceAvatar: true, centerEndY: false, - renderStates: teleportRenderStates + renderStates: teleportRenderStates, + defaultRenderStates: teleportDefaultRenderStates }); this.teleportRayHeadInvisible = LaserPointers.createLaserPointer({ joint: "Avatar", @@ -331,7 +337,8 @@ function Teleporter() { } if (teleportLocationType === TARGET.NONE) { - this.setTeleportState(mode, "", ""); + // Use the cancel default state + this.setTeleportState(mode, "cancel", ""); } else if (teleportLocationType === TARGET.INVALID || teleportLocationType === TARGET.INVISIBLE) { this.setTeleportState(mode, "", "cancel"); } else if (teleportLocationType === TARGET.SURFACE) { @@ -516,13 +523,13 @@ function cleanup() { } Script.scriptEnding.connect(cleanup); -var setIgnoredEntities = function () { - LaserPointers.setIgnoredEntities(teleporter.teleportRayRightVisible, ignoredEntities); - LaserPointers.setIgnoredEntities(teleporter.teleportRayRightInvisible, ignoredEntities); - LaserPointers.setIgnoredEntities(teleporter.teleportRayLeftVisible, ignoredEntities); - LaserPointers.setIgnoredEntities(teleporter.teleportRayLeftInvisible, ignoredEntities); - LaserPointers.setIgnoredEntities(teleporter.teleportRayHeadVisible, ignoredEntities); - LaserPointers.setIgnoredEntities(teleporter.teleportRayHeadInvisible, ignoredEntities); +var setIgnoreEntities = function() { + LaserPointers.setIgnoreEntities(teleporter.teleportRayRightVisible, ignoredEntities); + LaserPointers.setIgnoreEntities(teleporter.teleportRayRightInvisible, ignoredEntities); + LaserPointers.setIgnoreEntities(teleporter.teleportRayLeftVisible, ignoredEntities); + LaserPointers.setIgnoreEntities(teleporter.teleportRayLeftInvisible, ignoredEntities); + LaserPointers.setIgnoreEntities(teleporter.teleportRayHeadVisible, ignoredEntities); + LaserPointers.setIgnoreEntities(teleporter.teleportRayHeadInvisible, ignoredEntities); } var isDisabled = false; @@ -543,12 +550,12 @@ var handleTeleportMessages = function(channel, message, sender) { } } else if (channel === 'Hifi-Teleport-Ignore-Add' && !Uuid.isNull(message) && ignoredEntities.indexOf(message) === -1) { ignoredEntities.push(message); - setIgnoredEntities(); + setIgnoreEntities(); } else if (channel === 'Hifi-Teleport-Ignore-Remove' && !Uuid.isNull(message)) { var removeIndex = ignoredEntities.indexOf(message); if (removeIndex > -1) { ignoredEntities.splice(removeIndex, 1); - setIgnoredEntities(); + setIgnoreEntities(); } } } From e3288a9004af5ce42d4538490ffd9fb7390426e8 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 27 Jul 2017 11:17:30 -0700 Subject: [PATCH 31/42] fix flicker, scissor warning, and handControllerGrab sphere size --- interface/src/raypick/LaserPointer.cpp | 14 +++++--------- .../src/display-plugins/OpenGLDisplayPlugin.cpp | 2 ++ scripts/system/controllers/handControllerGrab.js | 3 ++- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 23adf5b532..ce25df340d 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -81,7 +81,7 @@ void LaserPointer::disable() { } void LaserPointer::setRenderState(const QString& state) { - if (!_currentRenderState.isEmpty()) { + if (!_currentRenderState.isEmpty() && state != _currentRenderState) { if (_renderStates.contains(_currentRenderState)) { disableRenderState(_renderStates[_currentRenderState]); } @@ -125,15 +125,12 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter glm::vec3 endVec; if (defaultState || !_lockEnd || type == IntersectionType::HUD) { endVec = pickRay.origin + pickRay.direction * distance; - } - else { + } else { if (type == IntersectionType::ENTITY) { endVec = DependencyManager::get()->getEntityTransform(objectID)[3]; - } - else if (type == IntersectionType::OVERLAY) { + } else if (type == IntersectionType::OVERLAY) { endVec = vec3FromVariant(qApp->getOverlays().getProperty(objectID, "position").value); - } - else if (type == IntersectionType::AVATAR) { + } else if (type == IntersectionType::AVATAR) { endVec = DependencyManager::get()->getAvatar(objectID)->getPosition(); } } @@ -150,8 +147,7 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter QVariantMap endProps; if (_centerEndY) { endProps.insert("position", end); - } - else { + } else { glm::vec3 dim = vec3FromVariant(qApp->getOverlays().getProperty(renderState.getEndID(), "dimensions").value); endProps.insert("position", vec3toVariant(endVec + glm::vec3(0, 0.5f * dim.y, 0))); } diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 9b3fe10c55..4e8940fe59 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -628,6 +628,7 @@ void OpenGLDisplayPlugin::compositeLayers() { // Clear the depth framebuffer after drawing the scene so that the HUD elements can depth test against each other render([&](gpu::Batch& batch) { + batch.enableStereo(false); batch.setFramebuffer(_compositeFramebuffer); batch.clearDepthFramebuffer((float) UINT32_MAX); }); @@ -657,6 +658,7 @@ void OpenGLDisplayPlugin::compositeLayers() { // Clear the depth buffer again and draw the pointer last so it's on top of everything render([&](gpu::Batch& batch) { + batch.enableStereo(false); batch.setFramebuffer(_compositeFramebuffer); batch.clearDepthFramebuffer((float) UINT32_MAX); }); diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index 79b00a3cae..7d76c2989f 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -1410,7 +1410,8 @@ function MyController(hand) { this.updateLaserPointer = function() { var SEARCH_SPHERE_SIZE = 0.011; - var radius = 1.2 * SEARCH_SPHERE_SIZE * this.intersectionDistance; + var MIN_SPHERE_SIZE = 0.0005; + var radius = Math.max(1.2 * SEARCH_SPHERE_SIZE * this.intersectionDistance, MIN_SPHERE_SIZE); var dim = {x: radius, y: radius, z: radius}; var mode = "hold"; if (this.state !== STATE_DISTANCE_HOLDING && this.state !== STATE_DISTANCE_ROTATING) { From 8b1c24e636f38793ee7dca1442e55ee4f458a940 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 4 Aug 2017 18:26:11 -0700 Subject: [PATCH 32/42] added setLockEndUUID, update handControllerGrab and grab --- interface/src/raypick/LaserPointer.cpp | 35 +++++++++++++++---- interface/src/raypick/LaserPointer.h | 3 ++ interface/src/raypick/LaserPointerManager.cpp | 10 +++++- interface/src/raypick/LaserPointerManager.h | 2 ++ .../raypick/LaserPointerScriptingInterface.h | 2 ++ scripts/system/controllers/grab.js | 2 +- .../system/controllers/handControllerGrab.js | 5 +++ 7 files changed, 50 insertions(+), 9 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index ce25df340d..342d7b37de 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -123,15 +123,36 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter qApp->getOverlays().editOverlay(renderState.getStartID(), startProps); } glm::vec3 endVec; - if (defaultState || !_lockEnd || type == IntersectionType::HUD) { + if (((defaultState || !_lockEnd) && _objectLockEnd.first.isNull()) || type == IntersectionType::HUD) { endVec = pickRay.origin + pickRay.direction * distance; } else { - if (type == IntersectionType::ENTITY) { - endVec = DependencyManager::get()->getEntityTransform(objectID)[3]; - } else if (type == IntersectionType::OVERLAY) { - endVec = vec3FromVariant(qApp->getOverlays().getProperty(objectID, "position").value); - } else if (type == IntersectionType::AVATAR) { - endVec = DependencyManager::get()->getAvatar(objectID)->getPosition(); + if (!_objectLockEnd.first.isNull()) { + glm::vec3 pos; + glm::quat rot; + glm::vec3 dim; + glm::vec3 registrationPoint; + if (_objectLockEnd.second) { + pos = vec3FromVariant(qApp->getOverlays().getProperty(_objectLockEnd.first, "position").value); + rot = quatFromVariant(qApp->getOverlays().getProperty(_objectLockEnd.first, "rotation").value); + dim = vec3FromVariant(qApp->getOverlays().getProperty(_objectLockEnd.first, "dimensions").value); + registrationPoint = glm::vec3(0.5f); + } else { + EntityItemProperties props = DependencyManager::get()->getEntityProperties(_objectLockEnd.first); + pos = props.getPosition(); + rot = props.getRotation(); + dim = props.getDimensions(); + registrationPoint = props.getRegistrationPoint(); + } + const glm::vec3 DEFAULT_REGISTRATION_POINT = glm::vec3(0.5f); + endVec = pos + rot * (dim * (DEFAULT_REGISTRATION_POINT - registrationPoint)); + } else { + if (type == IntersectionType::ENTITY) { + endVec = DependencyManager::get()->getEntityTransform(objectID)[3]; + } else if (type == IntersectionType::OVERLAY) { + endVec = vec3FromVariant(qApp->getOverlays().getProperty(objectID, "position").value); + } else if (type == IntersectionType::AVATAR) { + endVec = DependencyManager::get()->getAvatar(objectID)->getPosition(); + } } } QVariant end = vec3toVariant(endVec); diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index 34d9ee50df..6f70268b8c 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -68,6 +68,8 @@ public: void setIgnoreAvatars(const QScriptValue& ignoreAvatars) { DependencyManager::get()->setIgnoreAvatars(_rayPickUID, ignoreAvatars); } void setIncludeAvatars(const QScriptValue& includeAvatars) { DependencyManager::get()->setIncludeAvatars(_rayPickUID, includeAvatars); } + void setLockEndUUID(QUuid objectID, const bool isOverlay) { _objectLockEnd = QPair(objectID, isOverlay); } + void update(); private: @@ -78,6 +80,7 @@ private: bool _faceAvatar; bool _centerEndY; bool _lockEnd; + QPair _objectLockEnd { QPair(QUuid(), false)}; QUuid _rayPickUID; diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp index b05f56fa53..b852416463 100644 --- a/interface/src/raypick/LaserPointerManager.cpp +++ b/interface/src/raypick/LaserPointerManager.cpp @@ -143,4 +143,12 @@ void LaserPointerManager::setIncludeAvatars(QUuid uid, const QScriptValue& inclu QWriteLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->setIncludeAvatars(includeAvatars); } -} \ No newline at end of file +} + +void LaserPointerManager::setLockEndUUID(QUuid uid, QUuid objectID, const bool isOverlay) { + QReadLocker lock(&_containsLock); + if (_laserPointers.contains(uid)) { + QWriteLocker laserLock(_laserPointerLocks[uid].get()); + _laserPointers[uid]->setLockEndUUID(objectID, isOverlay); + } +} diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h index db035b197f..dc9790af4e 100644 --- a/interface/src/raypick/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -41,6 +41,8 @@ public: void setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars); void setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars); + void setLockEndUUID(QUuid uid, QUuid objectID, const bool isOverlay); + void update(); private: diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h index a6b61446a7..f28a09dbbc 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -37,6 +37,8 @@ public slots: Q_INVOKABLE void setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) { DependencyManager::get()->setIgnoreAvatars(uid, ignoreAvatars); } Q_INVOKABLE void setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) { DependencyManager::get()->setIncludeAvatars(uid, includeAvatars); } + Q_INVOKABLE void setLockEndUUID(QUuid uid, QUuid objectID, const bool isOverlay) { DependencyManager::get()->setLockEndUUID(uid, objectID, isOverlay); } + private: const RenderState buildRenderState(const QVariantMap & propMap); diff --git a/scripts/system/controllers/grab.js b/scripts/system/controllers/grab.js index a3473df7e3..1651877407 100644 --- a/scripts/system/controllers/grab.js +++ b/scripts/system/controllers/grab.js @@ -266,7 +266,6 @@ function Grabber() { this.mouseRayEntities = LaserPointers.createLaserPointer({ joint: "Mouse", filter: RayPick.PICK_ENTITIES, - lockEnd: true, faceAvatar: true, enabled: true }); @@ -341,6 +340,7 @@ Grabber.prototype.pressEvent = function(event) { } LaserPointers.setRenderState(this.mouseRayEntities, "grabbed"); + LaserPointers.setLockEndUUID(this.mouseRayEntities, pickResults.objectID, false); mouse.startDrag(event); diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index 855a50e009..dccf8e890b 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -1438,6 +1438,11 @@ function MyController(hand) { } LaserPointers.enableLaserPointer(laserPointerID); LaserPointers.setRenderState(laserPointerID, mode); + if (this.state === STATE_DISTANCE_HOLDING || this.state === STATE_DISTANCE_ROTATING) { + LaserPointers.setLockEndUUID(laserPointerID, this.grabbedThingID, this.grabbedIsOverlay); + } else { + LaserPointers.setLockEndUUID(laserPointerID, null, false); + } }; this.laserPointerOff = function() { From 42147640e25d2c689531b2f041c0bd31a455df78 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 7 Aug 2017 14:18:56 -0700 Subject: [PATCH 33/42] remove LaserPointerManager as a dependency --- interface/src/Application.cpp | 3 +-- interface/src/Application.h | 5 ++++ interface/src/raypick/LaserPointerManager.h | 4 +-- .../LaserPointerScriptingInterface.cpp | 4 +-- .../raypick/LaserPointerScriptingInterface.h | 25 ++++++++++--------- interface/src/raypick/RayPickManager.cpp | 2 -- 6 files changed, 22 insertions(+), 21 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index bc2e2f8ec8..5444968e67 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -602,7 +602,6 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { DependencyManager::set(); DependencyManager::set(); - DependencyManager::set(); DependencyManager::set(); return previousSessionCrashed; @@ -5049,7 +5048,7 @@ void Application::update(float deltaTime) { { PROFILE_RANGE(app, "LaserPointerManager"); - DependencyManager::get()->update(); + _laserPointerManager.update(); } // Update _viewFrustum with latest camera and view frustum data... diff --git a/interface/src/Application.h b/interface/src/Application.h index f8eb393f9e..83ae0b036a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -70,6 +70,7 @@ #include "ui/OverlayConductor.h" #include "ui/overlays/Overlays.h" #include "UndoStackScriptingInterface.h" +#include "raypick/LaserPointerManager.h" #include #include @@ -300,6 +301,8 @@ public: QUrl getAvatarOverrideUrl() { return _avatarOverrideUrl; } bool getSaveAvatarOverrideUrl() { return _saveAvatarOverrideUrl; } + LaserPointerManager& getLaserPointerManager() { return _laserPointerManager; } + signals: void svoImportRequested(const QString& url); @@ -697,5 +700,7 @@ private: QUrl _avatarOverrideUrl; bool _saveAvatarOverrideUrl { false }; + LaserPointerManager _laserPointerManager; + }; #endif // hifi_Application_h diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h index dc9790af4e..002b8ce38e 100644 --- a/interface/src/raypick/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -17,12 +17,10 @@ #include #include "LaserPointer.h" -#include "DependencyManager.h" class RayPickResult; -class LaserPointerManager : public Dependency { - SINGLETON_DEPENDENCY +class LaserPointerManager { public: QUuid createLaserPointer(const QVariantMap& rayProps, const QHash& renderStates, QHash>& defaultRenderStates, diff --git a/interface/src/raypick/LaserPointerScriptingInterface.cpp b/interface/src/raypick/LaserPointerScriptingInterface.cpp index 9bda37f26f..78a62d0ed8 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.cpp +++ b/interface/src/raypick/LaserPointerScriptingInterface.cpp @@ -69,7 +69,7 @@ QUuid LaserPointerScriptingInterface::createLaserPointer(const QVariant& propert } } - return DependencyManager::get()->createLaserPointer(propertyMap, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, enabled); + return qApp->getLaserPointerManager().createLaserPointer(propertyMap, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, enabled); } void LaserPointerScriptingInterface::editRenderState(QUuid uid, const QString& renderState, const QVariant& properties) { @@ -90,7 +90,7 @@ void LaserPointerScriptingInterface::editRenderState(QUuid uid, const QString& r endProps = propMap["end"]; } - DependencyManager::get()->editRenderState(uid, renderState, startProps, pathProps, endProps); + qApp->getLaserPointerManager().editRenderState(uid, renderState, startProps, pathProps, endProps); } const RenderState LaserPointerScriptingInterface::buildRenderState(const QVariantMap& propMap) { diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h index f28a09dbbc..70d2e9a1fd 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -16,6 +16,7 @@ #include "LaserPointerManager.h" #include "RegisteredMetaTypes.h" #include "DependencyManager.h" +#include "Application.h" class LaserPointerScriptingInterface : public QObject, public Dependency { Q_OBJECT @@ -23,21 +24,21 @@ class LaserPointerScriptingInterface : public QObject, public Dependency { public slots: Q_INVOKABLE QUuid createLaserPointer(const QVariant& properties); - Q_INVOKABLE void enableLaserPointer(QUuid uid) { DependencyManager::get()->enableLaserPointer(uid); } - Q_INVOKABLE void disableLaserPointer(QUuid uid) { DependencyManager::get()->disableLaserPointer(uid); } - Q_INVOKABLE void removeLaserPointer(QUuid uid) { DependencyManager::get()->removeLaserPointer(uid); } + Q_INVOKABLE void enableLaserPointer(QUuid uid) { qApp->getLaserPointerManager().enableLaserPointer(uid); } + Q_INVOKABLE void disableLaserPointer(QUuid uid) { qApp->getLaserPointerManager().disableLaserPointer(uid); } + Q_INVOKABLE void removeLaserPointer(QUuid uid) { qApp->getLaserPointerManager().removeLaserPointer(uid); } Q_INVOKABLE void editRenderState(QUuid uid, const QString& renderState, const QVariant& properties); - Q_INVOKABLE void setRenderState(QUuid uid, const QString& renderState) { DependencyManager::get()->setRenderState(uid, renderState); } - Q_INVOKABLE RayPickResult getPrevRayPickResult(QUuid uid) { return DependencyManager::get()->getPrevRayPickResult(uid); } + Q_INVOKABLE void setRenderState(QUuid uid, const QString& renderState) { qApp->getLaserPointerManager().setRenderState(uid, renderState); } + Q_INVOKABLE RayPickResult getPrevRayPickResult(QUuid uid) { return qApp->getLaserPointerManager().getPrevRayPickResult(uid); } - Q_INVOKABLE void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) { DependencyManager::get()->setIgnoreEntities(uid, ignoreEntities); } - Q_INVOKABLE void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) { DependencyManager::get()->setIncludeEntities(uid, includeEntities); } - Q_INVOKABLE void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) { DependencyManager::get()->setIgnoreOverlays(uid, ignoreOverlays); } - Q_INVOKABLE void setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays) { DependencyManager::get()->setIncludeOverlays(uid, includeOverlays); } - Q_INVOKABLE void setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) { DependencyManager::get()->setIgnoreAvatars(uid, ignoreAvatars); } - Q_INVOKABLE void setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) { DependencyManager::get()->setIncludeAvatars(uid, includeAvatars); } + Q_INVOKABLE void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) { qApp->getLaserPointerManager().setIgnoreEntities(uid, ignoreEntities); } + Q_INVOKABLE void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) { qApp->getLaserPointerManager().setIncludeEntities(uid, includeEntities); } + Q_INVOKABLE void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) { qApp->getLaserPointerManager().setIgnoreOverlays(uid, ignoreOverlays); } + Q_INVOKABLE void setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays) { qApp->getLaserPointerManager().setIncludeOverlays(uid, includeOverlays); } + Q_INVOKABLE void setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) { qApp->getLaserPointerManager().setIgnoreAvatars(uid, ignoreAvatars); } + Q_INVOKABLE void setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) { qApp->getLaserPointerManager().setIncludeAvatars(uid, includeAvatars); } - Q_INVOKABLE void setLockEndUUID(QUuid uid, QUuid objectID, const bool isOverlay) { DependencyManager::get()->setLockEndUUID(uid, objectID, isOverlay); } + Q_INVOKABLE void setLockEndUUID(QUuid uid, QUuid objectID, const bool isOverlay) { qApp->getLaserPointerManager().setLockEndUUID(uid, objectID, isOverlay); } private: const RenderState buildRenderState(const QVariantMap & propMap); diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp index 0814466e4b..e9698f4a17 100644 --- a/interface/src/raypick/RayPickManager.cpp +++ b/interface/src/raypick/RayPickManager.cpp @@ -59,8 +59,6 @@ void RayPickManager::update() { continue; } - // TODO: - // get rid of this and make PickRay hashable QPair rayKey = QPair(ray.origin, ray.direction); RayPickResult res; From 6d253fcc5f24cc0f60be8852cda7bbae339bc741 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 7 Aug 2017 18:37:55 -0700 Subject: [PATCH 34/42] cleaning up --- interface/src/raypick/LaserPointer.cpp | 33 +++++++++---------- interface/src/raypick/LaserPointer.h | 2 ++ interface/src/raypick/LaserPointerManager.cpp | 3 +- interface/src/raypick/RayPickManager.cpp | 2 +- interface/src/raypick/RayPickManager.h | 2 ++ 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 342d7b37de..2aeda6c800 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -38,27 +38,12 @@ LaserPointer::LaserPointer(const QVariantMap& rayProps, const QHash()->removeRayPick(_rayPickUID); + for (RenderState& renderState : _renderStates) { - if (!renderState.getStartID().isNull()) { - qApp->getOverlays().deleteOverlay(renderState.getStartID()); - } - if (!renderState.getPathID().isNull()) { - qApp->getOverlays().deleteOverlay(renderState.getPathID()); - } - if (!renderState.getEndID().isNull()) { - qApp->getOverlays().deleteOverlay(renderState.getEndID()); - } + renderState.deleteOverlays(); } for (QPair& renderState : _defaultRenderStates) { - if (!renderState.second.getStartID().isNull()) { - qApp->getOverlays().deleteOverlay(renderState.second.getStartID()); - } - if (!renderState.second.getPathID().isNull()) { - qApp->getOverlays().deleteOverlay(renderState.second.getPathID()); - } - if (!renderState.second.getEndID().isNull()) { - qApp->getOverlays().deleteOverlay(renderState.second.getEndID()); - } + renderState.second.deleteOverlays(); } } @@ -229,4 +214,16 @@ RenderState::RenderState(const OverlayID& startID, const OverlayID& pathID, cons if (!_endID.isNull()) { _endIgnoreRays = qApp->getOverlays().getOverlay(_endID)->getProperty("ignoreRayIntersection").toBool(); } +} + +void RenderState::deleteOverlays() { + if (!_startID.isNull()) { + qApp->getOverlays().deleteOverlay(_startID); + } + if (!_pathID.isNull()) { + qApp->getOverlays().deleteOverlay(_pathID); + } + if (!_endID.isNull()) { + qApp->getOverlays().deleteOverlay(_endID); + } } \ No newline at end of file diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index 6f70268b8c..da29aee3f1 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -36,6 +36,8 @@ public: const bool& doesPathIgnoreRays() const { return _pathIgnoreRays; } const bool& doesEndIgnoreRays() const { return _endIgnoreRays; } + void deleteOverlays(); + private: OverlayID _startID; OverlayID _pathID; diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp index b852416463..33f292b255 100644 --- a/interface/src/raypick/LaserPointerManager.cpp +++ b/interface/src/raypick/LaserPointerManager.cpp @@ -9,13 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "LaserPointerManager.h" -#include "LaserPointer.h" #include "RayPick.h" QUuid LaserPointerManager::createLaserPointer(const QVariantMap& rayProps, const QHash& renderStates, QHash>& defaultRenderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) { std::shared_ptr laserPointer = std::make_shared(rayProps, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, enabled); - if (laserPointer->getRayUID() != 0) { + if (!laserPointer->getRayUID().isNull()) { QWriteLocker lock(&_addLock); QUuid id = QUuid::createUuid(); _laserPointersToAdd.enqueue(QPair>(id, laserPointer)); diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp index e9698f4a17..f7f22a66bb 100644 --- a/interface/src/raypick/RayPickManager.cpp +++ b/interface/src/raypick/RayPickManager.cpp @@ -194,7 +194,7 @@ QUuid RayPickManager::createRayPick(const QVariantMap& rayProps) { return id; } - return 0; + return QUuid(); } void RayPickManager::removeRayPick(const QUuid uid) { diff --git a/interface/src/raypick/RayPickManager.h b/interface/src/raypick/RayPickManager.h index 27428ab43c..592541e7cf 100644 --- a/interface/src/raypick/RayPickManager.h +++ b/interface/src/raypick/RayPickManager.h @@ -30,11 +30,13 @@ enum RayPickMask { PICK_AVATARS = 1 << 2, PICK_HUD = 1 << 3, + // NOT YET IMPLEMENTED PICK_BOUNDING_BOX = 1 << 4, // if not set, picks again physics mesh (can't pick against graphics mesh, yet) PICK_INCLUDE_INVISIBLE = 1 << 5, // if not set, will not intersect invisible elements, otherwise, intersects both visible and invisible elements PICK_INCLUDE_NONCOLLIDABLE = 1 << 6, // if not set, will not intersect noncollidable elements, otherwise, intersects both collidable and noncollidable elements + // NOT YET IMPLEMENTED PICK_ALL_INTERSECTIONS = 1 << 7 // if not set, returns closest intersection, otherwise, returns list of all intersections }; From 684001a756e65c0e9d033360ecca2106c9859ec1 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 8 Aug 2017 11:11:19 -0700 Subject: [PATCH 35/42] workaround deadlock in editRenderState --- interface/src/raypick/LaserPointer.cpp | 21 ++++++--------------- interface/src/raypick/LaserPointer.h | 6 ++---- scripts/system/controllers/grab.js | 4 +++- 3 files changed, 11 insertions(+), 20 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 2aeda6c800..a59a85d700 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -78,24 +78,15 @@ void LaserPointer::setRenderState(const QString& state) { } void LaserPointer::editRenderState(const QString& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) { - _renderStates[state].setStartID(updateRenderStateOverlay(_renderStates[state].getStartID(), startProps)); - _renderStates[state].setPathID(updateRenderStateOverlay(_renderStates[state].getPathID(), pathProps)); - _renderStates[state].setEndID(updateRenderStateOverlay(_renderStates[state].getEndID(), endProps)); + updateRenderStateOverlay(_renderStates[state].getStartID(), startProps); + updateRenderStateOverlay(_renderStates[state].getPathID(), pathProps); + updateRenderStateOverlay(_renderStates[state].getEndID(), endProps); } -OverlayID LaserPointer::updateRenderStateOverlay(const OverlayID& id, const QVariant& props) { - if (props.isValid()) { - if (!id.isNull()) { - qApp->getOverlays().editOverlay(id, props); - return id; - } else { - QVariantMap propsMap = props.toMap(); - if (propsMap["type"].isValid()) { - return qApp->getOverlays().addOverlay(propsMap["type"].toString(), props); - } - } +void LaserPointer::updateRenderStateOverlay(const OverlayID& id, const QVariant& props) { + if (!id.isNull() && props.isValid()) { + qApp->getOverlays().editOverlay(id, props); } - return OverlayID(); } void LaserPointer::updateRenderState(const RenderState& renderState, const IntersectionType type, const float distance, const QUuid& objectID, const bool defaultState) { diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index da29aee3f1..946b01d3ba 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -29,9 +29,6 @@ public: const OverlayID& getStartID() const { return _startID; } const OverlayID& getPathID() const { return _pathID; } const OverlayID& getEndID() const { return _endID; } - void setStartID(const OverlayID& startID) { _startID = startID; } - void setPathID(const OverlayID& pathID) { _pathID = pathID; } - void setEndID(const OverlayID& endID) { _endID = endID; } const bool& doesStartIgnoreRays() const { return _startIgnoreRays; } const bool& doesPathIgnoreRays() const { return _pathIgnoreRays; } const bool& doesEndIgnoreRays() const { return _endIgnoreRays; } @@ -61,6 +58,7 @@ public: const RayPickResult getPrevRayPickResult() { return DependencyManager::get()->getPrevRayPickResult(_rayPickUID); } void setRenderState(const QString& state); + // You cannot use editRenderState to change the overlay type of any part of the laser pointer. You can only edit the properties of the existing overlays. void editRenderState(const QString& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps); void setIgnoreEntities(const QScriptValue& ignoreEntities) { DependencyManager::get()->setIgnoreEntities(_rayPickUID, ignoreEntities); } @@ -86,7 +84,7 @@ private: QUuid _rayPickUID; - OverlayID updateRenderStateOverlay(const OverlayID& id, const QVariant& props); + void updateRenderStateOverlay(const OverlayID& id, const QVariant& props); void updateRenderState(const RenderState& renderState, const IntersectionType type, const float distance, const QUuid& objectID, const bool defaultState); void disableRenderState(const RenderState& renderState); }; diff --git a/scripts/system/controllers/grab.js b/scripts/system/controllers/grab.js index 1651877407..2844940d2b 100644 --- a/scripts/system/controllers/grab.js +++ b/scripts/system/controllers/grab.js @@ -263,11 +263,13 @@ function Grabber() { enabled: true }); RayPick.setIncludeOverlays(this.mouseRayOverlays, [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID]); + var renderStates = [{name: "grabbed", end: beacon}]; this.mouseRayEntities = LaserPointers.createLaserPointer({ joint: "Mouse", filter: RayPick.PICK_ENTITIES, faceAvatar: true, - enabled: true + enabled: true, + renderStates: renderStates }); } From 3645bf04b6d5a178f2d5140f2a3e440ae542dedc Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 8 Aug 2017 18:10:53 -0700 Subject: [PATCH 36/42] possibly fix most annoying crash --- interface/src/avatar/AvatarManager.cpp | 16 +++++--- interface/src/avatar/AvatarManager.h | 3 ++ interface/src/raypick/LaserPointer.cpp | 6 +-- interface/src/raypick/RayPick.h | 39 ++++++++++--------- interface/src/ui/overlays/Overlays.cpp | 18 ++++----- interface/src/ui/overlays/Overlays.h | 10 +++-- .../entities/src/EntityScriptingInterface.cpp | 12 ++++-- .../entities/src/EntityScriptingInterface.h | 5 +++ 8 files changed, 67 insertions(+), 42 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index bd545c64e0..35039f168c 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -476,19 +476,25 @@ AvatarSharedPointer AvatarManager::getAvatarBySessionID(const QUuid& sessionID) RayToAvatarIntersectionResult AvatarManager::findRayIntersection(const PickRay& ray, const QScriptValue& avatarIdsToInclude, const QScriptValue& avatarIdsToDiscard) { + QVector avatarsToInclude = qVectorEntityItemIDFromScriptValue(avatarIdsToInclude); + QVector avatarsToDiscard = qVectorEntityItemIDFromScriptValue(avatarIdsToDiscard); + + return findRayIntersection(ray, avatarsToInclude, avatarsToDiscard); +} + +RayToAvatarIntersectionResult AvatarManager::findRayIntersection(const PickRay& ray, + const QVector& avatarsToInclude, + const QVector& avatarsToDiscard) { RayToAvatarIntersectionResult result; if (QThread::currentThread() != thread()) { BLOCKING_INVOKE_METHOD(const_cast(this), "findRayIntersection", Q_RETURN_ARG(RayToAvatarIntersectionResult, result), Q_ARG(const PickRay&, ray), - Q_ARG(const QScriptValue&, avatarIdsToInclude), - Q_ARG(const QScriptValue&, avatarIdsToDiscard)); + Q_ARG(const QVector&, avatarsToInclude), + Q_ARG(const QVector&, avatarsToDiscard)); return result; } - QVector avatarsToInclude = qVectorEntityItemIDFromScriptValue(avatarIdsToInclude); - QVector avatarsToDiscard = qVectorEntityItemIDFromScriptValue(avatarIdsToDiscard); - glm::vec3 normDirection = glm::normalize(ray.direction); for (auto avatarData : _avatarHash) { diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 30801807d6..c21214484b 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -73,6 +73,9 @@ public: Q_INVOKABLE RayToAvatarIntersectionResult findRayIntersection(const PickRay& ray, const QScriptValue& avatarIdsToInclude = QScriptValue(), const QScriptValue& avatarIdsToDiscard = QScriptValue()); + Q_INVOKABLE RayToAvatarIntersectionResult findRayIntersection(const PickRay& ray, + const QVector& avatarsToInclude, + const QVector& avatarsToDiscard); // TODO: remove this HACK once we settle on optimal default sort coefficients Q_INVOKABLE float getAvatarSortCoefficient(const QString& name); diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index a59a85d700..9dc1bdd72e 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -197,13 +197,13 @@ RenderState::RenderState(const OverlayID& startID, const OverlayID& pathID, cons _startID(startID), _pathID(pathID), _endID(endID) { if (!_startID.isNull()) { - _startIgnoreRays = qApp->getOverlays().getOverlay(_startID)->getProperty("ignoreRayIntersection").toBool(); + _startIgnoreRays = qApp->getOverlays().getProperty(_startID, "ignoreRayIntersection").value.toBool(); } if (!_pathID.isNull()) { - _pathIgnoreRays = qApp->getOverlays().getOverlay(_pathID)->getProperty("ignoreRayIntersection").toBool(); + _pathIgnoreRays = qApp->getOverlays().getProperty(_pathID, "ignoreRayIntersection").value.toBool(); } if (!_endID.isNull()) { - _endIgnoreRays = qApp->getOverlays().getOverlay(_endID)->getProperty("ignoreRayIntersection").toBool(); + _endIgnoreRays = qApp->getOverlays().getProperty(_endID, "ignoreRayIntersection").value.toBool(); } } diff --git a/interface/src/raypick/RayPick.h b/interface/src/raypick/RayPick.h index ca9660729a..48841b9518 100644 --- a/interface/src/raypick/RayPick.h +++ b/interface/src/raypick/RayPick.h @@ -14,6 +14,9 @@ #include #include "RegisteredMetaTypes.h" +#include "EntityItemID.h" +#include "ui/overlays/Overlay.h" + class RayPick { public: @@ -31,18 +34,18 @@ public: void setRayPickResult(const RayPickResult& rayPickResult) { _prevResult = rayPickResult; } - const QScriptValue& getIgnoreEntites() { return _ignoreEntities; } - const QScriptValue& getIncludeEntites() { return _includeEntities; } - const QScriptValue& getIgnoreOverlays() { return _ignoreOverlays; } - const QScriptValue& getIncludeOverlays() { return _includeOverlays; } - const QScriptValue& getIgnoreAvatars() { return _ignoreAvatars; } - const QScriptValue& getIncludeAvatars() { return _includeAvatars; } - void setIgnoreEntities(const QScriptValue& ignoreEntities) { _ignoreEntities = ignoreEntities; } - void setIncludeEntities(const QScriptValue& includeEntities) { _includeEntities = includeEntities; } - void setIgnoreOverlays(const QScriptValue& ignoreOverlays) { _ignoreOverlays = ignoreOverlays; } - void setIncludeOverlays(const QScriptValue& includeOverlays) { _includeOverlays = includeOverlays; } - void setIgnoreAvatars(const QScriptValue& ignoreAvatars) { _ignoreAvatars = ignoreAvatars; } - void setIncludeAvatars(const QScriptValue& includeAvatars) { _includeAvatars = includeAvatars; } + const QVector& getIgnoreEntites() { return _ignoreEntities; } + const QVector& getIncludeEntites() { return _includeEntities; } + const QVector& getIgnoreOverlays() { return _ignoreOverlays; } + const QVector& getIncludeOverlays() { return _includeOverlays; } + const QVector& getIgnoreAvatars() { return _ignoreAvatars; } + const QVector& getIncludeAvatars() { return _includeAvatars; } + void setIgnoreEntities(const QScriptValue& ignoreEntities) { _ignoreEntities = qVectorEntityItemIDFromScriptValue(ignoreEntities); } + void setIncludeEntities(const QScriptValue& includeEntities) { _includeEntities = qVectorEntityItemIDFromScriptValue(includeEntities); } + void setIgnoreOverlays(const QScriptValue& ignoreOverlays) { _ignoreOverlays = qVectorOverlayIDFromScriptValue(ignoreOverlays); } + void setIncludeOverlays(const QScriptValue& includeOverlays) { _includeOverlays = qVectorOverlayIDFromScriptValue(includeOverlays); } + void setIgnoreAvatars(const QScriptValue& ignoreAvatars) { _ignoreAvatars = qVectorEntityItemIDFromScriptValue(ignoreAvatars); } + void setIncludeAvatars(const QScriptValue& includeAvatars) { _includeAvatars = qVectorEntityItemIDFromScriptValue(includeAvatars); } private: uint16_t _filter; @@ -50,12 +53,12 @@ private: bool _enabled; RayPickResult _prevResult; - QScriptValue _ignoreEntities; - QScriptValue _includeEntities; - QScriptValue _ignoreOverlays; - QScriptValue _includeOverlays; - QScriptValue _ignoreAvatars; - QScriptValue _includeAvatars; + QVector _ignoreEntities; + QVector _includeEntities; + QVector _ignoreOverlays; + QVector _includeOverlays; + QVector _ignoreAvatars; + QVector _includeAvatars; }; #endif // hifi_RayPick_h diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 5ec669af15..04ee205ba6 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -534,15 +534,15 @@ RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray, const QVector overlaysToInclude = qVectorOverlayIDFromScriptValue(overlayIDsToInclude); const QVector overlaysToDiscard = qVectorOverlayIDFromScriptValue(overlayIDsToDiscard); - return findRayIntersectionInternal(ray, precisionPicking, - overlaysToInclude, overlaysToDiscard, visibleOnly, collidableOnly); + return findRayIntersection(ray, precisionPicking, + overlaysToInclude, overlaysToDiscard, visibleOnly, collidableOnly); } -RayToOverlayIntersectionResult Overlays::findRayIntersectionInternal(const PickRay& ray, bool precisionPicking, - const QVector& overlaysToInclude, - const QVector& overlaysToDiscard, - bool visibleOnly, bool collidableOnly) { +RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray, bool precisionPicking, + const QVector& overlaysToInclude, + const QVector& overlaysToDiscard, + bool visibleOnly, bool collidableOnly) { float bestDistance = std::numeric_limits::max(); bool bestIsFront = false; @@ -908,21 +908,21 @@ RayToOverlayIntersectionResult Overlays::findRayIntersectionForMouseEvent(PickRa // first priority is tablet screen overlaysToInclude << qApp->getTabletScreenID(); - rayPickResult = findRayIntersectionInternal(ray, true, overlaysToInclude, overlaysToDiscard); + rayPickResult = findRayIntersection(ray, true, overlaysToInclude, overlaysToDiscard); if (rayPickResult.intersects) { return rayPickResult; } // then tablet home button overlaysToInclude.clear(); overlaysToInclude << qApp->getTabletHomeButtonID(); - rayPickResult = findRayIntersectionInternal(ray, true, overlaysToInclude, overlaysToDiscard); + rayPickResult = findRayIntersection(ray, true, overlaysToInclude, overlaysToDiscard); if (rayPickResult.intersects) { return rayPickResult; } // then tablet frame overlaysToInclude.clear(); overlaysToInclude << OverlayID(qApp->getTabletFrameID()); - rayPickResult = findRayIntersectionInternal(ray, true, overlaysToInclude, overlaysToDiscard); + rayPickResult = findRayIntersection(ray, true, overlaysToInclude, overlaysToDiscard); if (rayPickResult.intersects) { return rayPickResult; } diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index f1042eb55b..9db6375e84 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -216,6 +216,12 @@ public slots: bool visibleOnly = false, bool collidableOnly = false); + // Same as above but with QVectors + RayToOverlayIntersectionResult findRayIntersection(const PickRay& ray, bool precisionPicking, + const QVector& overlaysToInclude, + const QVector& overlaysToDiscard, + bool visibleOnly = false, bool collidableOnly = false); + /**jsdoc * Return a list of 3d overlays with bounding boxes that touch the given sphere * @@ -350,10 +356,6 @@ private: OverlayID _currentClickingOnOverlayID { UNKNOWN_OVERLAY_ID }; OverlayID _currentHoverOverOverlayID { UNKNOWN_OVERLAY_ID }; - Q_INVOKABLE RayToOverlayIntersectionResult findRayIntersectionInternal(const PickRay& ray, bool precisionPicking, - const QVector& overlaysToInclude, - const QVector& overlaysToDiscard, - bool visibleOnly = false, bool collidableOnly = false); RayToOverlayIntersectionResult findRayIntersectionForMouseEvent(PickRay ray); }; diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index e21c9581e1..1eb9ef8462 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -679,11 +679,17 @@ QVector EntityScriptingInterface::findEntitiesByType(const QString entity RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersection(const PickRay& ray, bool precisionPicking, const QScriptValue& entityIdsToInclude, const QScriptValue& entityIdsToDiscard, bool visibleOnly, bool collidableOnly) { - PROFILE_RANGE(script_entities, __FUNCTION__); - QVector entitiesToInclude = qVectorEntityItemIDFromScriptValue(entityIdsToInclude); QVector entitiesToDiscard = qVectorEntityItemIDFromScriptValue(entityIdsToDiscard); - return findRayIntersectionWorker(ray, Octree::Lock, precisionPicking, entitiesToInclude, entitiesToDiscard, visibleOnly, collidableOnly); + + return findRayIntersection(ray, precisionPicking, entitiesToInclude, entitiesToDiscard, visibleOnly, collidableOnly); +} + +RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersection(const PickRay& ray, bool precisionPicking, + const QVector& entityIdsToInclude, const QVector& entityIdsToDiscard, bool visibleOnly, bool collidableOnly) { + PROFILE_RANGE(script_entities, __FUNCTION__); + + return findRayIntersectionWorker(ray, Octree::Lock, precisionPicking, entityIdsToInclude, entityIdsToDiscard, visibleOnly, collidableOnly); } // FIXME - we should remove this API and encourage all users to use findRayIntersection() instead. We've changed diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 575528fa78..fc5053bdd6 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -229,6 +229,11 @@ public slots: const QScriptValue& entityIdsToInclude = QScriptValue(), const QScriptValue& entityIdsToDiscard = QScriptValue(), bool visibleOnly = false, bool collidableOnly = false); + /// Same as above but with QVectors + Q_INVOKABLE RayToEntityIntersectionResult findRayIntersection(const PickRay& ray, bool precisionPicking, + const QVector& entityIdsToInclude, const QVector& entityIdsToDiscard, + bool visibleOnly, bool collidableOnly); + /// If the scripting context has visible entities, this will determine a ray intersection, and will block in /// order to return an accurate result Q_INVOKABLE RayToEntityIntersectionResult findRayIntersectionBlocking(const PickRay& ray, bool precisionPicking = false, const QScriptValue& entityIdsToInclude = QScriptValue(), const QScriptValue& entityIdsToDiscard = QScriptValue()); From 6157f4fa55c4c1ce82657aced2c3bd75982bc283 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 9 Aug 2017 11:56:25 -0700 Subject: [PATCH 37/42] script fixes --- scripts/system/controllers/handControllerGrab.js | 1 + scripts/system/controllers/handControllerPointer.js | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index dccf8e890b..44f79a5570 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -3442,6 +3442,7 @@ function MyController(hand) { }; this.offEnter = function() { + var existingSearchDistance = this.searchSphereDistance; this.release(); if (hoveredEntityID) { diff --git a/scripts/system/controllers/handControllerPointer.js b/scripts/system/controllers/handControllerPointer.js index f169204206..538fe0b1e4 100644 --- a/scripts/system/controllers/handControllerPointer.js +++ b/scripts/system/controllers/handControllerPointer.js @@ -160,7 +160,7 @@ var systemLaserOn = false; var triggerPath = { type: "line3d", - color: LASER_SEARCH_COLOR, + color: LASER_TRIGGER_COLOR, ignoreRayIntersection: true, visible: true, alpha: LASER_ALPHA, @@ -171,7 +171,7 @@ var triggerPath = { var triggerEnd = { type: "sphere", dimensions: {x: END_DIAMETER, y: END_DIAMETER, z: END_DIAMETER}, - color: LASER_SEARCH_COLOR, + color: LASER_TRIGGER_COLOR, ignoreRayIntersection: true, visible: true, alpha: LASER_ALPHA, @@ -181,7 +181,7 @@ var triggerEnd = { var searchPath = { type: "line3d", - color: LASER_TRIGGER_COLOR, + color: LASER_SEARCH_COLOR, ignoreRayIntersection: true, visible: true, alpha: LASER_ALPHA, @@ -192,7 +192,7 @@ var searchPath = { var searchEnd = { type: "sphere", dimensions: {x: END_DIAMETER, y: END_DIAMETER, z: END_DIAMETER}, - color: LASER_TRIGGER_COLOR, + color: LASER_SEARCH_COLOR, ignoreRayIntersection: true, visible: true, alpha: LASER_ALPHA, From d0d5ac8dd12385abb5cd1e9f95d0db97e65590e4 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 10 Aug 2017 15:32:58 -0700 Subject: [PATCH 38/42] switch to stl wherever possible, use bitset instead of unsigned ints --- interface/src/raypick/JointRayPick.cpp | 4 +- interface/src/raypick/JointRayPick.h | 6 +- interface/src/raypick/LaserPointer.cpp | 44 +++---- interface/src/raypick/LaserPointer.h | 21 +-- interface/src/raypick/LaserPointerManager.cpp | 84 ++++++------ interface/src/raypick/LaserPointerManager.h | 24 ++-- .../LaserPointerScriptingInterface.cpp | 12 +- .../raypick/LaserPointerScriptingInterface.h | 2 +- interface/src/raypick/MouseRayPick.cpp | 2 +- interface/src/raypick/MouseRayPick.h | 2 +- interface/src/raypick/RayPick.cpp | 2 +- interface/src/raypick/RayPick.h | 76 ++++++++++- interface/src/raypick/RayPickManager.cpp | 120 +++++++++--------- interface/src/raypick/RayPickManager.h | 66 ++++------ interface/src/raypick/StaticRayPick.cpp | 2 +- interface/src/raypick/StaticRayPick.h | 2 +- 16 files changed, 268 insertions(+), 201 deletions(-) diff --git a/interface/src/raypick/JointRayPick.cpp b/interface/src/raypick/JointRayPick.cpp index 6803700e4b..48ab908201 100644 --- a/interface/src/raypick/JointRayPick.cpp +++ b/interface/src/raypick/JointRayPick.cpp @@ -13,7 +13,7 @@ #include "DependencyManager.h" #include "avatar/AvatarManager.h" -JointRayPick::JointRayPick(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, const bool enabled) : +JointRayPick::JointRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const RayPickFilter& filter, const float maxDistance, const bool enabled) : RayPick(filter, maxDistance, enabled), _jointName(jointName), _posOffset(posOffset), @@ -23,7 +23,7 @@ JointRayPick::JointRayPick(const QString& jointName, const glm::vec3& posOffset, const PickRay JointRayPick::getPickRay(bool& valid) const { auto myAvatar = DependencyManager::get()->getMyAvatar(); - int jointIndex = myAvatar->getJointIndex(_jointName); + int jointIndex = myAvatar->getJointIndex(QString::fromStdString(_jointName)); bool useAvatarHead = _jointName == "Avatar"; const int INVALID_JOINT = -1; if (jointIndex != INVALID_JOINT || useAvatarHead) { diff --git a/interface/src/raypick/JointRayPick.h b/interface/src/raypick/JointRayPick.h index 0631372bdb..3cd622fbbe 100644 --- a/interface/src/raypick/JointRayPick.h +++ b/interface/src/raypick/JointRayPick.h @@ -13,17 +13,15 @@ #include "RayPick.h" -#include - class JointRayPick : public RayPick { public: - JointRayPick(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance = 0.0f, const bool enabled = false); + JointRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const RayPickFilter& filter, const float maxDistance = 0.0f, const bool enabled = false); const PickRay getPickRay(bool& valid) const override; private: - QString _jointName; + std::string _jointName; glm::vec3 _posOffset; glm::vec3 _dirOffset; diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 9dc1bdd72e..0e1d384e5d 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -13,7 +13,7 @@ #include "Application.h" #include "avatar/AvatarManager.h" -LaserPointer::LaserPointer(const QVariantMap& rayProps, const QHash& renderStates, QHash>& defaultRenderStates, +LaserPointer::LaserPointer(const QVariantMap& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) : _renderingEnabled(enabled), _renderStates(renderStates), @@ -24,14 +24,14 @@ LaserPointer::LaserPointer(const QVariantMap& rayProps, const QHash()->createRayPick(rayProps); - for (QString& state : _renderStates.keys()) { - if (!enabled || state != _currentRenderState) { - disableRenderState(_renderStates[state]); + for (auto& state : _renderStates) { + if (!enabled || state.first != _currentRenderState) { + disableRenderState(state.second); } } - for (QString& state : _defaultRenderStates.keys()) { - if (!enabled || state != _currentRenderState) { - disableRenderState(_defaultRenderStates[state].second); + for (auto& state : _defaultRenderStates) { + if (!enabled || state.first != _currentRenderState) { + disableRenderState(state.second.second); } } } @@ -39,12 +39,12 @@ LaserPointer::LaserPointer(const QVariantMap& rayProps, const QHash()->removeRayPick(_rayPickUID); - for (RenderState& renderState : _renderStates) { - renderState.deleteOverlays(); - } - for (QPair& renderState : _defaultRenderStates) { + for (auto& renderState : _renderStates) { renderState.second.deleteOverlays(); } + for (auto& renderState : _defaultRenderStates) { + renderState.second.second.deleteOverlays(); + } } void LaserPointer::enable() { @@ -55,29 +55,29 @@ void LaserPointer::enable() { void LaserPointer::disable() { DependencyManager::get()->disableRayPick(_rayPickUID); _renderingEnabled = false; - if (!_currentRenderState.isEmpty()) { - if (_renderStates.contains(_currentRenderState)) { + if (!_currentRenderState.empty()) { + if (_renderStates.find(_currentRenderState) != _renderStates.end()) { disableRenderState(_renderStates[_currentRenderState]); } - if (_defaultRenderStates.contains(_currentRenderState)) { + if (_defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) { disableRenderState(_defaultRenderStates[_currentRenderState].second); } } } -void LaserPointer::setRenderState(const QString& state) { - if (!_currentRenderState.isEmpty() && state != _currentRenderState) { - if (_renderStates.contains(_currentRenderState)) { +void LaserPointer::setRenderState(const std::string& state) { + if (!_currentRenderState.empty() && state != _currentRenderState) { + if (_renderStates.find(_currentRenderState) != _renderStates.end()) { disableRenderState(_renderStates[_currentRenderState]); } - if (_defaultRenderStates.contains(_currentRenderState)) { + if (_defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) { disableRenderState(_defaultRenderStates[_currentRenderState].second); } } _currentRenderState = state; } -void LaserPointer::editRenderState(const QString& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) { +void LaserPointer::editRenderState(const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) { updateRenderStateOverlay(_renderStates[state].getStartID(), startProps); updateRenderStateOverlay(_renderStates[state].getPathID(), pathProps); updateRenderStateOverlay(_renderStates[state].getEndID(), endProps); @@ -181,13 +181,13 @@ void LaserPointer::disableRenderState(const RenderState& renderState) { void LaserPointer::update() { RayPickResult prevRayPickResult = DependencyManager::get()->getPrevRayPickResult(_rayPickUID); - if (_renderingEnabled && !_currentRenderState.isEmpty() && _renderStates.contains(_currentRenderState) && prevRayPickResult.type != IntersectionType::NONE) { + if (_renderingEnabled && !_currentRenderState.empty() && _renderStates.find(_currentRenderState) != _renderStates.end() && prevRayPickResult.type != IntersectionType::NONE) { updateRenderState(_renderStates[_currentRenderState], prevRayPickResult.type, prevRayPickResult.distance, prevRayPickResult.objectID, false); disableRenderState(_defaultRenderStates[_currentRenderState].second); - } else if (_renderingEnabled && !_currentRenderState.isEmpty() && _defaultRenderStates.contains(_currentRenderState)) { + } else if (_renderingEnabled && !_currentRenderState.empty() && _defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) { disableRenderState(_renderStates[_currentRenderState]); updateRenderState(_defaultRenderStates[_currentRenderState].second, IntersectionType::NONE, _defaultRenderStates[_currentRenderState].first, QUuid(), true); - } else if (!_currentRenderState.isEmpty()) { + } else if (!_currentRenderState.empty()) { disableRenderState(_renderStates[_currentRenderState]); disableRenderState(_defaultRenderStates[_currentRenderState].second); } diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index 946b01d3ba..aaa9dad83f 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -48,7 +48,11 @@ private: class LaserPointer { public: - LaserPointer(const QVariantMap& rayProps, const QHash& renderStates, QHash>& defaultRenderStates, + + typedef std::unordered_map RenderStateMap; + typedef std::unordered_map> DefaultRenderStateMap; + + LaserPointer(const QVariantMap& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled); ~LaserPointer(); @@ -57,9 +61,9 @@ public: void disable(); const RayPickResult getPrevRayPickResult() { return DependencyManager::get()->getPrevRayPickResult(_rayPickUID); } - void setRenderState(const QString& state); + void setRenderState(const std::string& state); // You cannot use editRenderState to change the overlay type of any part of the laser pointer. You can only edit the properties of the existing overlays. - void editRenderState(const QString& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps); + void editRenderState(const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps); void setIgnoreEntities(const QScriptValue& ignoreEntities) { DependencyManager::get()->setIgnoreEntities(_rayPickUID, ignoreEntities); } void setIncludeEntities(const QScriptValue& includeEntities) { DependencyManager::get()->setIncludeEntities(_rayPickUID, includeEntities); } @@ -68,25 +72,26 @@ public: void setIgnoreAvatars(const QScriptValue& ignoreAvatars) { DependencyManager::get()->setIgnoreAvatars(_rayPickUID, ignoreAvatars); } void setIncludeAvatars(const QScriptValue& includeAvatars) { DependencyManager::get()->setIncludeAvatars(_rayPickUID, includeAvatars); } - void setLockEndUUID(QUuid objectID, const bool isOverlay) { _objectLockEnd = QPair(objectID, isOverlay); } + void setLockEndUUID(QUuid objectID, const bool isOverlay) { _objectLockEnd = std::pair(objectID, isOverlay); } void update(); private: bool _renderingEnabled; - QString _currentRenderState { "" }; - QHash _renderStates; - QHash> _defaultRenderStates; + std::string _currentRenderState { "" }; + RenderStateMap _renderStates; + DefaultRenderStateMap _defaultRenderStates; bool _faceAvatar; bool _centerEndY; bool _lockEnd; - QPair _objectLockEnd { QPair(QUuid(), false)}; + std::pair _objectLockEnd { std::pair(QUuid(), false)}; QUuid _rayPickUID; void updateRenderStateOverlay(const OverlayID& id, const QVariant& props); void updateRenderState(const RenderState& renderState, const IntersectionType type, const float distance, const QUuid& objectID, const bool defaultState); void disableRenderState(const RenderState& renderState); + }; #endif // hifi_LaserPointer_h diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp index 33f292b255..da20068cba 100644 --- a/interface/src/raypick/LaserPointerManager.cpp +++ b/interface/src/raypick/LaserPointerManager.cpp @@ -11,85 +11,87 @@ #include "LaserPointerManager.h" #include "RayPick.h" -QUuid LaserPointerManager::createLaserPointer(const QVariantMap& rayProps, const QHash& renderStates, QHash>& defaultRenderStates, +QUuid LaserPointerManager::createLaserPointer(const QVariantMap& rayProps, const LaserPointer::RenderStateMap& renderStates, const LaserPointer::DefaultRenderStateMap& defaultRenderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) { std::shared_ptr laserPointer = std::make_shared(rayProps, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, enabled); if (!laserPointer->getRayUID().isNull()) { - QWriteLocker lock(&_addLock); + WriteLock lock(_addLock); QUuid id = QUuid::createUuid(); - _laserPointersToAdd.enqueue(QPair>(id, laserPointer)); + _laserPointersToAdd.push(std::pair>(id, laserPointer)); return id; } return QUuid(); } void LaserPointerManager::removeLaserPointer(const QUuid uid) { - QWriteLocker lock(&_removeLock); - _laserPointersToRemove.enqueue(uid); + WriteLock lock(_removeLock); + _laserPointersToRemove.push(uid); } void LaserPointerManager::enableLaserPointer(const QUuid uid) { - QReadLocker lock(&_containsLock); + ReadLock lock(_containsLock); if (_laserPointers.contains(uid)) { - QWriteLocker laserLock(_laserPointerLocks[uid].get()); + WriteLock laserLock(*_laserPointerLocks[uid]); _laserPointers[uid]->enable(); } } void LaserPointerManager::disableLaserPointer(const QUuid uid) { - QReadLocker lock(&_containsLock); + ReadLock lock(_containsLock); if (_laserPointers.contains(uid)) { - QWriteLocker laserLock(_laserPointerLocks[uid].get()); + WriteLock laserLock(*_laserPointerLocks[uid]); _laserPointers[uid]->disable(); } } -void LaserPointerManager::setRenderState(QUuid uid, const QString & renderState) { - QReadLocker lock(&_containsLock); +void LaserPointerManager::setRenderState(QUuid uid, const std::string& renderState) { + ReadLock lock(_containsLock); if (_laserPointers.contains(uid)) { - QWriteLocker laserLock(_laserPointerLocks[uid].get()); + WriteLock laserLock(*_laserPointerLocks[uid]); _laserPointers[uid]->setRenderState(renderState); } } -void LaserPointerManager::editRenderState(QUuid uid, const QString& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) { - QReadLocker lock(&_containsLock); +void LaserPointerManager::editRenderState(QUuid uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) { + ReadLock lock(_containsLock); if (_laserPointers.contains(uid)) { - QWriteLocker laserLock(_laserPointerLocks[uid].get()); + WriteLock laserLock(*_laserPointerLocks[uid]); _laserPointers[uid]->editRenderState(state, startProps, pathProps, endProps); } } const RayPickResult LaserPointerManager::getPrevRayPickResult(const QUuid uid) { - QReadLocker lock(&_containsLock); + ReadLock lock(_containsLock); if (_laserPointers.contains(uid)) { - QReadLocker laserLock(_laserPointerLocks[uid].get()); + ReadLock laserLock(*_laserPointerLocks[uid]); return _laserPointers[uid]->getPrevRayPickResult(); } return RayPickResult(); } void LaserPointerManager::update() { - for (QUuid uid : _laserPointers.keys()) { + for (QUuid& uid : _laserPointers.keys()) { // This only needs to be a read lock because update won't change any of the properties that can be modified from scripts - QReadLocker laserLock(_laserPointerLocks[uid].get()); + ReadLock laserLock(*_laserPointerLocks[uid]); _laserPointers[uid]->update(); } - QWriteLocker containsLock(&_containsLock); + WriteLock containsLock(_containsLock); { - QWriteLocker lock(&_addLock); - while (!_laserPointersToAdd.isEmpty()) { - QPair> laserPointerToAdd = _laserPointersToAdd.dequeue(); + WriteLock lock(_addLock); + while (!_laserPointersToAdd.empty()) { + std::pair> laserPointerToAdd = _laserPointersToAdd.front(); + _laserPointersToAdd.pop(); _laserPointers[laserPointerToAdd.first] = laserPointerToAdd.second; - _laserPointerLocks[laserPointerToAdd.first] = std::make_shared(); + _laserPointerLocks[laserPointerToAdd.first] = std::make_shared(); } } { - QWriteLocker lock(&_removeLock); - while (!_laserPointersToRemove.isEmpty()) { - QUuid uid = _laserPointersToRemove.dequeue(); + WriteLock lock(_removeLock); + while (!_laserPointersToRemove.empty()) { + QUuid uid = _laserPointersToRemove.front(); + _laserPointersToRemove.pop(); _laserPointers.remove(uid); _laserPointerLocks.remove(uid); } @@ -97,57 +99,57 @@ void LaserPointerManager::update() { } void LaserPointerManager::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) { - QReadLocker lock(&_containsLock); + ReadLock lock(_containsLock); if (_laserPointers.contains(uid)) { - QWriteLocker laserLock(_laserPointerLocks[uid].get()); + WriteLock laserLock(*_laserPointerLocks[uid]); _laserPointers[uid]->setIgnoreEntities(ignoreEntities); } } void LaserPointerManager::setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) { - QReadLocker lock(&_containsLock); + ReadLock lock(_containsLock); if (_laserPointers.contains(uid)) { - QWriteLocker laserLock(_laserPointerLocks[uid].get()); + WriteLock laserLock(*_laserPointerLocks[uid]); _laserPointers[uid]->setIncludeEntities(includeEntities); } } void LaserPointerManager::setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) { - QReadLocker lock(&_containsLock); + ReadLock lock(_containsLock); if (_laserPointers.contains(uid)) { - QWriteLocker laserLock(_laserPointerLocks[uid].get()); + WriteLock laserLock(*_laserPointerLocks[uid]); _laserPointers[uid]->setIgnoreOverlays(ignoreOverlays); } } void LaserPointerManager::setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays) { - QReadLocker lock(&_containsLock); + ReadLock lock(_containsLock); if (_laserPointers.contains(uid)) { - QWriteLocker laserLock(_laserPointerLocks[uid].get()); + WriteLock laserLock(*_laserPointerLocks[uid]); _laserPointers[uid]->setIncludeOverlays(includeOverlays); } } void LaserPointerManager::setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) { - QReadLocker lock(&_containsLock); + ReadLock lock(_containsLock); if (_laserPointers.contains(uid)) { - QWriteLocker laserLock(_laserPointerLocks[uid].get()); + WriteLock laserLock(*_laserPointerLocks[uid]); _laserPointers[uid]->setIgnoreAvatars(ignoreAvatars); } } void LaserPointerManager::setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) { - QReadLocker lock(&_containsLock); + ReadLock lock(_containsLock); if (_laserPointers.contains(uid)) { - QWriteLocker laserLock(_laserPointerLocks[uid].get()); + WriteLock laserLock(*_laserPointerLocks[uid]); _laserPointers[uid]->setIncludeAvatars(includeAvatars); } } void LaserPointerManager::setLockEndUUID(QUuid uid, QUuid objectID, const bool isOverlay) { - QReadLocker lock(&_containsLock); + ReadLock lock(_containsLock); if (_laserPointers.contains(uid)) { - QWriteLocker laserLock(_laserPointerLocks[uid].get()); + WriteLock laserLock(*_laserPointerLocks[uid]); _laserPointers[uid]->setLockEndUUID(objectID, isOverlay); } } diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h index 002b8ce38e..5e33ac77d8 100644 --- a/interface/src/raypick/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -11,9 +11,8 @@ #ifndef hifi_LaserPointerManager_h #define hifi_LaserPointerManager_h -#include -#include #include +#include #include #include "LaserPointer.h" @@ -23,13 +22,13 @@ class RayPickResult; class LaserPointerManager { public: - QUuid createLaserPointer(const QVariantMap& rayProps, const QHash& renderStates, QHash>& defaultRenderStates, + QUuid createLaserPointer(const QVariantMap& rayProps, const LaserPointer::RenderStateMap& renderStates, const LaserPointer::DefaultRenderStateMap& defaultRenderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled); void removeLaserPointer(const QUuid uid); void enableLaserPointer(const QUuid uid); void disableLaserPointer(const QUuid uid); - void setRenderState(QUuid uid, const QString& renderState); - void editRenderState(QUuid uid, const QString& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps); + void setRenderState(QUuid uid, const std::string& renderState); + void editRenderState(QUuid uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps); const RayPickResult getPrevRayPickResult(const QUuid uid); void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities); @@ -45,12 +44,15 @@ public: private: QHash> _laserPointers; - QHash> _laserPointerLocks; - QReadWriteLock _addLock; - QQueue>> _laserPointersToAdd; - QReadWriteLock _removeLock; - QQueue _laserPointersToRemove; - QReadWriteLock _containsLock; + QHash> _laserPointerLocks; + std::shared_mutex _addLock; + std::queue>> _laserPointersToAdd; + std::shared_mutex _removeLock; + std::queue _laserPointersToRemove; + std::shared_mutex _containsLock; + + typedef std::lock_guard WriteLock; + typedef std::shared_lock ReadLock; }; diff --git a/interface/src/raypick/LaserPointerScriptingInterface.cpp b/interface/src/raypick/LaserPointerScriptingInterface.cpp index 78a62d0ed8..9b7f18d436 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.cpp +++ b/interface/src/raypick/LaserPointerScriptingInterface.cpp @@ -40,30 +40,30 @@ QUuid LaserPointerScriptingInterface::createLaserPointer(const QVariant& propert enabled = propertyMap["enabled"].toBool(); } - QHash renderStates; + LaserPointer::RenderStateMap renderStates; if (propertyMap["renderStates"].isValid()) { QList renderStateVariants = propertyMap["renderStates"].toList(); for (QVariant& renderStateVariant : renderStateVariants) { if (renderStateVariant.isValid()) { QVariantMap renderStateMap = renderStateVariant.toMap(); if (renderStateMap["name"].isValid()) { - QString name = renderStateMap["name"].toString(); + std::string name = renderStateMap["name"].toString().toStdString(); renderStates[name] = buildRenderState(renderStateMap); } } } } - QHash> defaultRenderStates; + LaserPointer::DefaultRenderStateMap defaultRenderStates; if (propertyMap["defaultRenderStates"].isValid()) { QList renderStateVariants = propertyMap["defaultRenderStates"].toList(); for (QVariant& renderStateVariant : renderStateVariants) { if (renderStateVariant.isValid()) { QVariantMap renderStateMap = renderStateVariant.toMap(); if (renderStateMap["name"].isValid() && renderStateMap["distance"].isValid()) { - QString name = renderStateMap["name"].toString(); + std::string name = renderStateMap["name"].toString().toStdString(); float distance = renderStateMap["distance"].toFloat(); - defaultRenderStates[name] = QPair(distance, buildRenderState(renderStateMap)); + defaultRenderStates[name] = std::pair(distance, buildRenderState(renderStateMap)); } } } @@ -90,7 +90,7 @@ void LaserPointerScriptingInterface::editRenderState(QUuid uid, const QString& r endProps = propMap["end"]; } - qApp->getLaserPointerManager().editRenderState(uid, renderState, startProps, pathProps, endProps); + qApp->getLaserPointerManager().editRenderState(uid, renderState.toStdString(), startProps, pathProps, endProps); } const RenderState LaserPointerScriptingInterface::buildRenderState(const QVariantMap& propMap) { diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h index 70d2e9a1fd..7866a5da51 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -28,7 +28,7 @@ public slots: Q_INVOKABLE void disableLaserPointer(QUuid uid) { qApp->getLaserPointerManager().disableLaserPointer(uid); } Q_INVOKABLE void removeLaserPointer(QUuid uid) { qApp->getLaserPointerManager().removeLaserPointer(uid); } Q_INVOKABLE void editRenderState(QUuid uid, const QString& renderState, const QVariant& properties); - Q_INVOKABLE void setRenderState(QUuid uid, const QString& renderState) { qApp->getLaserPointerManager().setRenderState(uid, renderState); } + Q_INVOKABLE void setRenderState(QUuid uid, const QString& renderState) { qApp->getLaserPointerManager().setRenderState(uid, renderState.toStdString()); } Q_INVOKABLE RayPickResult getPrevRayPickResult(QUuid uid) { return qApp->getLaserPointerManager().getPrevRayPickResult(uid); } Q_INVOKABLE void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) { qApp->getLaserPointerManager().setIgnoreEntities(uid, ignoreEntities); } diff --git a/interface/src/raypick/MouseRayPick.cpp b/interface/src/raypick/MouseRayPick.cpp index 39dcb74090..de59fde88d 100644 --- a/interface/src/raypick/MouseRayPick.cpp +++ b/interface/src/raypick/MouseRayPick.cpp @@ -14,7 +14,7 @@ #include "Application.h" #include "display-plugins/CompositorHelper.h" -MouseRayPick::MouseRayPick(const uint16_t filter, const float maxDistance, const bool enabled) : +MouseRayPick::MouseRayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled) : RayPick(filter, maxDistance, enabled) { } diff --git a/interface/src/raypick/MouseRayPick.h b/interface/src/raypick/MouseRayPick.h index 84d1c86e24..848a5de336 100644 --- a/interface/src/raypick/MouseRayPick.h +++ b/interface/src/raypick/MouseRayPick.h @@ -16,7 +16,7 @@ class MouseRayPick : public RayPick { public: - MouseRayPick(const uint16_t filter, const float maxDistance = 0.0f, const bool enabled = false); + MouseRayPick(const RayPickFilter& filter, const float maxDistance = 0.0f, const bool enabled = false); const PickRay getPickRay(bool& valid) const override; }; diff --git a/interface/src/raypick/RayPick.cpp b/interface/src/raypick/RayPick.cpp index e807ef23ff..70170a8f85 100644 --- a/interface/src/raypick/RayPick.cpp +++ b/interface/src/raypick/RayPick.cpp @@ -10,7 +10,7 @@ // #include "RayPick.h" -RayPick::RayPick(const uint16_t filter, const float maxDistance, const bool enabled) : +RayPick::RayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled) : _filter(filter), _maxDistance(maxDistance), _enabled(enabled) diff --git a/interface/src/raypick/RayPick.h b/interface/src/raypick/RayPick.h index 48841b9518..e108145d55 100644 --- a/interface/src/raypick/RayPick.h +++ b/interface/src/raypick/RayPick.h @@ -17,17 +17,87 @@ #include "EntityItemID.h" #include "ui/overlays/Overlay.h" +class RayPickFilter { +public: + enum FlagBit { + PICK_NOTHING = 0, + PICK_ENTITIES, + PICK_OVERLAYS, + PICK_AVATARS, + PICK_HUD, + + PICK_COURSE, // if not set, does precise intersection, otherwise, doesn't + + PICK_INCLUDE_INVISIBLE, // if not set, will not intersect invisible elements, otherwise, intersects both visible and invisible elements + PICK_INCLUDE_NONCOLLIDABLE, // if not set, will not intersect noncollidable elements, otherwise, intersects both collidable and noncollidable elements + + // NOT YET IMPLEMENTED + PICK_ALL_INTERSECTIONS, // if not set, returns closest intersection, otherwise, returns list of all intersections + + NUM_FLAGS, // Not a valid flag + }; + typedef std::bitset Flags; + + // The key is the Flags + Flags _flags; + + RayPickFilter() : _flags(PICK_NOTHING) {} + RayPickFilter(const Flags& flags) : _flags(flags) {} + + bool operator== (const RayPickFilter& rhs) const { return _flags == rhs._flags; } + bool operator!= (const RayPickFilter& rhs) const { return _flags != rhs._flags; } + + bool doesPickNothing() const { return _flags[PICK_NOTHING]; } + bool doesPickEntities() const { return _flags[PICK_ENTITIES]; } + bool doesPickOverlays() const { return _flags[PICK_OVERLAYS]; } + bool doesPickAvatars() const { return _flags[PICK_AVATARS]; } + bool doesPickHUD() const { return _flags[PICK_HUD]; } + + bool doesPickCourse() const { return _flags[PICK_COURSE]; } + bool doesPickInvisible() const { return _flags[PICK_INCLUDE_INVISIBLE]; } + bool doesPickNonCollidable() const { return _flags[PICK_INCLUDE_NONCOLLIDABLE]; } + + bool doesWantAllIntersections() const { return _flags[PICK_ALL_INTERSECTIONS]; } + + // Helpers for RayPickManager + Flags getEntityFlags() const { + Flags toReturn(PICK_ENTITIES); + if (doesPickInvisible()) { + toReturn |= Flags(PICK_INCLUDE_INVISIBLE); + } + if (doesPickNonCollidable()) { + toReturn |= Flags(PICK_INCLUDE_NONCOLLIDABLE); + } + return toReturn; + } + Flags getOverlayFlags() const { + Flags toReturn(PICK_OVERLAYS); + if (doesPickInvisible()) { + toReturn |= Flags(PICK_INCLUDE_INVISIBLE); + } + if (doesPickNonCollidable()) { + toReturn |= Flags(PICK_INCLUDE_NONCOLLIDABLE); + } + return toReturn; + } + Flags getAvatarFlags() const { return Flags(PICK_AVATARS); } + Flags getHUDFlags() const { return Flags(PICK_HUD); } + + static unsigned int getBitMask(FlagBit bit) { return 1 << bit; } + +}; + class RayPick { public: - RayPick(const uint16_t filter, const float maxDistance, const bool enabled); + RayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled); virtual const PickRay getPickRay(bool& valid) const = 0; void enable() { _enabled = true; } void disable() { _enabled = false; } - const uint16_t& getFilter() { return _filter; } + const RayPickFilter& getFilter() { return _filter; } const float& getMaxDistance() { return _maxDistance; } const bool& isEnabled() { return _enabled; } const RayPickResult& getPrevRayPickResult() { return _prevResult; } @@ -48,7 +118,7 @@ public: void setIncludeAvatars(const QScriptValue& includeAvatars) { _includeAvatars = qVectorEntityItemIDFromScriptValue(includeAvatars); } private: - uint16_t _filter; + RayPickFilter _filter; float _maxDistance; bool _enabled; RayPickResult _prevResult; diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp index f7f22a66bb..0fe7fdb823 100644 --- a/interface/src/raypick/RayPickManager.cpp +++ b/interface/src/raypick/RayPickManager.cpp @@ -10,8 +10,6 @@ // #include "RayPickManager.h" -#include "RayPick.h" - #include "Application.h" #include "EntityScriptingInterface.h" #include "ui/overlays/Overlays.h" @@ -23,8 +21,8 @@ #include "StaticRayPick.h" #include "MouseRayPick.h" -bool RayPickManager::checkAndCompareCachedResults(QPair& ray, RayPickCache& cache, RayPickResult& res, unsigned int mask) { - if (cache.contains(ray) && cache[ray].contains(mask)) { +bool RayPickManager::checkAndCompareCachedResults(QPair& ray, RayPickCache& cache, RayPickResult& res, const RayPickFilter::Flags& mask) { + if (cache.contains(ray) && cache[ray].find(mask) != cache[ray].end()) { if (cache[ray][mask].distance < res.distance) { res = cache[ray][mask]; } @@ -33,7 +31,7 @@ bool RayPickManager::checkAndCompareCachedResults(QPair& r return false; } -void RayPickManager::cacheResult(const bool intersects, const RayPickResult& resTemp, unsigned int mask, RayPickResult& res, QPair& ray, RayPickCache& cache) { +void RayPickManager::cacheResult(const bool intersects, const RayPickResult& resTemp, const RayPickFilter::Flags& mask, RayPickResult& res, QPair& ray, RayPickCache& cache) { if (intersects) { cache[ray][mask] = resTemp; if (resTemp.distance < res.distance) { @@ -48,7 +46,7 @@ void RayPickManager::update() { RayPickCache results; for (auto& uid : _rayPicks.keys()) { std::shared_ptr rayPick = _rayPicks[uid]; - if (!rayPick->isEnabled() || rayPick->getFilter() == RayPickMask::PICK_NOTHING || rayPick->getMaxDistance() < 0.0f) { + if (!rayPick->isEnabled() || rayPick->getFilter().doesPickNothing() || rayPick->getMaxDistance() < 0.0f) { continue; } @@ -62,12 +60,12 @@ void RayPickManager::update() { QPair rayKey = QPair(ray.origin, ray.direction); RayPickResult res; - if (rayPick->getFilter() & RayPickMask::PICK_ENTITIES) { + if (rayPick->getFilter().doesPickEntities()) { RayToEntityIntersectionResult entityRes; bool fromCache = true; - unsigned int invisible = rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE; - unsigned int noncollidable = rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE; - unsigned int entityMask = RayPickMask::PICK_ENTITIES | invisible | noncollidable; + bool invisible = rayPick->getFilter().doesPickInvisible(); + bool noncollidable = rayPick->getFilter().doesPickNonCollidable(); + RayPickFilter::Flags entityMask = rayPick->getFilter().getEntityFlags(); if (!checkAndCompareCachedResults(rayKey, results, res, entityMask)) { entityRes = DependencyManager::get()->findRayIntersection(ray, true, rayPick->getIncludeEntites(), rayPick->getIgnoreEntites(), !invisible, !noncollidable); fromCache = false; @@ -79,12 +77,12 @@ void RayPickManager::update() { } } - if (rayPick->getFilter() & RayPickMask::PICK_OVERLAYS) { + if (rayPick->getFilter().doesPickOverlays()) { RayToOverlayIntersectionResult overlayRes; bool fromCache = true; - unsigned int invisible = rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE; - unsigned int noncollidable = rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE; - unsigned int overlayMask = RayPickMask::PICK_OVERLAYS | invisible | noncollidable; + bool invisible = rayPick->getFilter().doesPickInvisible(); + bool noncollidable = rayPick->getFilter().doesPickNonCollidable(); + RayPickFilter::Flags overlayMask = rayPick->getFilter().getOverlayFlags(); if (!checkAndCompareCachedResults(rayKey, results, res, overlayMask)) { overlayRes = qApp->getOverlays().findRayIntersection(ray, true, rayPick->getIncludeOverlays(), rayPick->getIgnoreOverlays(), !invisible, !noncollidable); fromCache = false; @@ -96,22 +94,24 @@ void RayPickManager::update() { } } - if (rayPick->getFilter() & RayPickMask::PICK_AVATARS) { - if (!checkAndCompareCachedResults(rayKey, results, res, RayPickMask::PICK_AVATARS)) { + if (rayPick->getFilter().doesPickAvatars()) { + RayPickFilter::Flags avatarMask = rayPick->getFilter().getAvatarFlags(); + if (!checkAndCompareCachedResults(rayKey, results, res, avatarMask)) { RayToAvatarIntersectionResult avatarRes = DependencyManager::get()->findRayIntersection(ray, rayPick->getIncludeAvatars(), rayPick->getIgnoreAvatars()); - cacheResult(avatarRes.intersects, RayPickResult(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection), RayPickMask::PICK_AVATARS, res, rayKey, results); + cacheResult(avatarRes.intersects, RayPickResult(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection), avatarMask, res, rayKey, results); } } // Can't intersect with HUD in desktop mode - if (rayPick->getFilter() & RayPickMask::PICK_HUD && DependencyManager::get()->isHMDMode()) { - if (!checkAndCompareCachedResults(rayKey, results, res, RayPickMask::PICK_HUD)) { + if (rayPick->getFilter().doesPickHUD() && DependencyManager::get()->isHMDMode()) { + RayPickFilter::Flags hudMask = rayPick->getFilter().getHUDFlags(); + if (!checkAndCompareCachedResults(rayKey, results, res, hudMask)) { glm::vec3 hudRes = DependencyManager::get()->calculateRayUICollisionPoint(ray.origin, ray.direction); - cacheResult(true, RayPickResult(IntersectionType::HUD, 0, glm::distance(ray.origin, hudRes), hudRes), RayPickMask::PICK_HUD, res, rayKey, results); + cacheResult(true, RayPickResult(IntersectionType::HUD, 0, glm::distance(ray.origin, hudRes), hudRes), hudMask, res, rayKey, results); } } - QWriteLocker lock(_rayPickLocks[uid].get()); + WriteLock lock(*_rayPickLocks[uid]); if (rayPick->getMaxDistance() == 0.0f || (rayPick->getMaxDistance() > 0.0f && res.distance < rayPick->getMaxDistance())) { rayPick->setRayPickResult(res); } else { @@ -119,20 +119,22 @@ void RayPickManager::update() { } } - QWriteLocker containsLock(&_containsLock); + WriteLock containsLock(_containsLock); { - QWriteLocker lock(&_addLock); - while (!_rayPicksToAdd.isEmpty()) { - QPair> rayPickToAdd = _rayPicksToAdd.dequeue(); + WriteLock lock(_addLock); + while (!_rayPicksToAdd.empty()) { + std::pair> rayPickToAdd = _rayPicksToAdd.front(); + _rayPicksToAdd.pop(); _rayPicks[rayPickToAdd.first] = rayPickToAdd.second; - _rayPickLocks[rayPickToAdd.first] = std::make_shared(); + _rayPickLocks[rayPickToAdd.first] = std::make_shared(); } } { - QWriteLocker lock(&_removeLock); - while (!_rayPicksToRemove.isEmpty()) { - QUuid uid = _rayPicksToRemove.dequeue(); + WriteLock lock(_removeLock); + while (!_rayPicksToRemove.empty()) { + QUuid uid = _rayPicksToRemove.front(); + _rayPicksToRemove.pop(); _rayPicks.remove(uid); _rayPickLocks.remove(uid); } @@ -145,9 +147,9 @@ QUuid RayPickManager::createRayPick(const QVariantMap& rayProps) { enabled = rayProps["enabled"].toBool(); } - uint16_t filter = 0; + RayPickFilter filter = RayPickFilter(); if (rayProps["filter"].isValid()) { - filter = rayProps["filter"].toUInt(); + filter = RayPickFilter(rayProps["filter"].toUInt()); } float maxDistance = 0.0f; @@ -156,7 +158,7 @@ QUuid RayPickManager::createRayPick(const QVariantMap& rayProps) { } if (rayProps["joint"].isValid()) { - QString jointName = rayProps["joint"].toString(); + std::string jointName = rayProps["joint"].toString().toStdString(); if (jointName != "Mouse") { // x = upward, y = forward, z = lateral @@ -170,14 +172,14 @@ QUuid RayPickManager::createRayPick(const QVariantMap& rayProps) { dirOffset = vec3FromVariant(rayProps["dirOffset"]); } - QWriteLocker lock(&_addLock); + WriteLock lock(_addLock); QUuid id = QUuid::createUuid(); - _rayPicksToAdd.enqueue(QPair>(id, std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled))); + _rayPicksToAdd.push(std::pair>(id, std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled))); return id; } else { - QWriteLocker lock(&_addLock); + WriteLock lock(_addLock); QUuid id = QUuid::createUuid(); - _rayPicksToAdd.enqueue(QPair>(id, std::make_shared(filter, maxDistance, enabled))); + _rayPicksToAdd.push(std::pair>(id, std::make_shared(filter, maxDistance, enabled))); return id; } } else if (rayProps["position"].isValid()) { @@ -188,9 +190,9 @@ QUuid RayPickManager::createRayPick(const QVariantMap& rayProps) { direction = vec3FromVariant(rayProps["direction"]); } - QWriteLocker lock(&_addLock); + WriteLock lock(_addLock); QUuid id = QUuid::createUuid(); - _rayPicksToAdd.enqueue(QPair>(id, std::make_shared(position, direction, filter, maxDistance, enabled))); + _rayPicksToAdd.push(std::pair>(id, std::make_shared(position, direction, filter, maxDistance, enabled))); return id; } @@ -198,28 +200,28 @@ QUuid RayPickManager::createRayPick(const QVariantMap& rayProps) { } void RayPickManager::removeRayPick(const QUuid uid) { - QWriteLocker lock(&_removeLock); - _rayPicksToRemove.enqueue(uid); + WriteLock lock(_removeLock); + _rayPicksToRemove.push(uid); } void RayPickManager::enableRayPick(const QUuid uid) { - QReadLocker containsLock(&_containsLock); + ReadLock containsLock(_containsLock); if (_rayPicks.contains(uid)) { - QWriteLocker rayPickLock(_rayPickLocks[uid].get()); + WriteLock rayPickLock(*_rayPickLocks[uid]); _rayPicks[uid]->enable(); } } void RayPickManager::disableRayPick(const QUuid uid) { - QReadLocker containsLock(&_containsLock); + ReadLock containsLock(_containsLock); if (_rayPicks.contains(uid)) { - QWriteLocker rayPickLock(_rayPickLocks[uid].get()); + WriteLock rayPickLock(*_rayPickLocks[uid]); _rayPicks[uid]->disable(); } } const PickRay RayPickManager::getPickRay(const QUuid uid) { - QReadLocker containsLock(&_containsLock); + ReadLock containsLock(_containsLock); if (_rayPicks.contains(uid)) { bool valid; PickRay pickRay = _rayPicks[uid]->getPickRay(valid); @@ -231,58 +233,58 @@ const PickRay RayPickManager::getPickRay(const QUuid uid) { } const RayPickResult RayPickManager::getPrevRayPickResult(const QUuid uid) { - QReadLocker containsLock(&_containsLock); + ReadLock containsLock(_containsLock); if (_rayPicks.contains(uid)) { - QReadLocker lock(_rayPickLocks[uid].get()); + ReadLock lock(*_rayPickLocks[uid]); return _rayPicks[uid]->getPrevRayPickResult(); } return RayPickResult(); } void RayPickManager::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) { - QReadLocker containsLock(&_containsLock); + ReadLock containsLock(_containsLock); if (_rayPicks.contains(uid)) { - QWriteLocker lock(_rayPickLocks[uid].get()); + WriteLock lock(*_rayPickLocks[uid]); _rayPicks[uid]->setIgnoreEntities(ignoreEntities); } } void RayPickManager::setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) { - QReadLocker containsLock(&_containsLock); + ReadLock containsLock(_containsLock); if (_rayPicks.contains(uid)) { - QWriteLocker lock(_rayPickLocks[uid].get()); + WriteLock lock(*_rayPickLocks[uid]); _rayPicks[uid]->setIncludeEntities(includeEntities); } } void RayPickManager::setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) { - QReadLocker containsLock(&_containsLock); + ReadLock containsLock(_containsLock); if (_rayPicks.contains(uid)) { - QWriteLocker lock(_rayPickLocks[uid].get()); + WriteLock lock(*_rayPickLocks[uid]); _rayPicks[uid]->setIgnoreOverlays(ignoreOverlays); } } void RayPickManager::setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays) { - QReadLocker containsLock(&_containsLock); + ReadLock containsLock(_containsLock); if (_rayPicks.contains(uid)) { - QWriteLocker lock(_rayPickLocks[uid].get()); + WriteLock lock(*_rayPickLocks[uid]); _rayPicks[uid]->setIncludeOverlays(includeOverlays); } } void RayPickManager::setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) { - QReadLocker containsLock(&_containsLock); + ReadLock containsLock(_containsLock); if (_rayPicks.contains(uid)) { - QWriteLocker lock(_rayPickLocks[uid].get()); + WriteLock lock(*_rayPickLocks[uid]); _rayPicks[uid]->setIgnoreAvatars(ignoreAvatars); } } void RayPickManager::setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) { - QReadLocker containsLock(&_containsLock); + ReadLock containsLock(_containsLock); if (_rayPicks.contains(uid)) { - QWriteLocker lock(_rayPickLocks[uid].get()); + WriteLock lock(*_rayPickLocks[uid]); _rayPicks[uid]->setIncludeAvatars(includeAvatars); } } \ No newline at end of file diff --git a/interface/src/raypick/RayPickManager.h b/interface/src/raypick/RayPickManager.h index 592541e7cf..9055e060ef 100644 --- a/interface/src/raypick/RayPickManager.h +++ b/interface/src/raypick/RayPickManager.h @@ -11,35 +11,20 @@ #ifndef hifi_RayPickManager_h #define hifi_RayPickManager_h -#include -#include -#include +#include "RayPick.h" + #include +#include #include #include "RegisteredMetaTypes.h" #include "DependencyManager.h" -class RayPick; +#include +#include + class RayPickResult; -enum RayPickMask { - PICK_NOTHING = 0, - PICK_ENTITIES = 1 << 0, - PICK_OVERLAYS = 1 << 1, - PICK_AVATARS = 1 << 2, - PICK_HUD = 1 << 3, - - // NOT YET IMPLEMENTED - PICK_BOUNDING_BOX = 1 << 4, // if not set, picks again physics mesh (can't pick against graphics mesh, yet) - - PICK_INCLUDE_INVISIBLE = 1 << 5, // if not set, will not intersect invisible elements, otherwise, intersects both visible and invisible elements - PICK_INCLUDE_NONCOLLIDABLE = 1 << 6, // if not set, will not intersect noncollidable elements, otherwise, intersects both collidable and noncollidable elements - - // NOT YET IMPLEMENTED - PICK_ALL_INTERSECTIONS = 1 << 7 // if not set, returns closest intersection, otherwise, returns list of all intersections -}; - class RayPickManager : public QObject, public Dependency { Q_OBJECT Q_PROPERTY(unsigned int PICK_NOTHING READ PICK_NOTHING CONSTANT) @@ -78,34 +63,37 @@ public slots: private: QHash> _rayPicks; - QHash> _rayPickLocks; - QReadWriteLock _addLock; - QQueue>> _rayPicksToAdd; - QReadWriteLock _removeLock; - QQueue _rayPicksToRemove; - QReadWriteLock _containsLock; + QHash> _rayPickLocks; + std::shared_mutex _addLock; + std::queue>> _rayPicksToAdd; + std::shared_mutex _removeLock; + std::queue _rayPicksToRemove; + std::shared_mutex _containsLock; - typedef QHash, QHash> RayPickCache; + typedef QHash, std::unordered_map> RayPickCache; // Returns true if this ray exists in the cache, and if it does, update res if the cached result is closer - bool checkAndCompareCachedResults(QPair& ray, RayPickCache& cache, RayPickResult& res, unsigned int mask); - void cacheResult(const bool intersects, const RayPickResult& resTemp, unsigned int mask, RayPickResult& res, QPair& ray, RayPickCache& cache); + bool checkAndCompareCachedResults(QPair& ray, RayPickCache& cache, RayPickResult& res, const RayPickFilter::Flags& mask); + void cacheResult(const bool intersects, const RayPickResult& resTemp, const RayPickFilter::Flags& mask, RayPickResult& res, QPair& ray, RayPickCache& cache); - unsigned int PICK_NOTHING() { return RayPickMask::PICK_NOTHING; } - unsigned int PICK_ENTITIES() { return RayPickMask::PICK_ENTITIES; } - unsigned int PICK_OVERLAYS() { return RayPickMask::PICK_OVERLAYS; } - unsigned int PICK_AVATARS() { return RayPickMask::PICK_AVATARS; } - unsigned int PICK_HUD() { return RayPickMask::PICK_HUD; } - unsigned int PICK_BOUNDING_BOX() { return RayPickMask::PICK_BOUNDING_BOX; } - unsigned int PICK_INCLUDE_INVISIBLE() { return RayPickMask::PICK_INCLUDE_INVISIBLE; } - unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return RayPickMask::PICK_INCLUDE_NONCOLLIDABLE; } - unsigned int PICK_ALL_INTERSECTIONS() { return RayPickMask::PICK_ALL_INTERSECTIONS; } + unsigned int PICK_NOTHING() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_NOTHING); } + unsigned int PICK_ENTITIES() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_ENTITIES); } + unsigned int PICK_OVERLAYS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_OVERLAYS); } + unsigned int PICK_AVATARS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_AVATARS); } + unsigned int PICK_HUD() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_HUD); } + unsigned int PICK_BOUNDING_BOX() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_COURSE); } + unsigned int PICK_INCLUDE_INVISIBLE() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_INCLUDE_INVISIBLE); } + unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_INCLUDE_NONCOLLIDABLE); } + unsigned int PICK_ALL_INTERSECTIONS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_ALL_INTERSECTIONS); } unsigned int INTERSECTED_NONE() { return IntersectionType::NONE; } unsigned int INTERSECTED_ENTITY() { return IntersectionType::ENTITY; } unsigned int INTERSECTED_OVERLAY() { return IntersectionType::OVERLAY; } unsigned int INTERSECTED_AVATAR() { return IntersectionType::AVATAR; } unsigned int INTERSECTED_HUD() { return IntersectionType::HUD; } + typedef std::lock_guard WriteLock; + typedef std::shared_lock ReadLock; + }; #endif // hifi_RayPickManager_h \ No newline at end of file diff --git a/interface/src/raypick/StaticRayPick.cpp b/interface/src/raypick/StaticRayPick.cpp index 43088150ad..89bcddb3df 100644 --- a/interface/src/raypick/StaticRayPick.cpp +++ b/interface/src/raypick/StaticRayPick.cpp @@ -10,7 +10,7 @@ // #include "StaticRayPick.h" -StaticRayPick::StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance, const bool enabled) : +StaticRayPick::StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const RayPickFilter& filter, const float maxDistance, const bool enabled) : RayPick(filter, maxDistance, enabled), _pickRay(position, direction) { diff --git a/interface/src/raypick/StaticRayPick.h b/interface/src/raypick/StaticRayPick.h index 05ff4ef397..fc09ee6a27 100644 --- a/interface/src/raypick/StaticRayPick.h +++ b/interface/src/raypick/StaticRayPick.h @@ -16,7 +16,7 @@ class StaticRayPick : public RayPick { public: - StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance = 0.0f, const bool enabled = false); + StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const RayPickFilter& filter, const float maxDistance = 0.0f, const bool enabled = false); const PickRay getPickRay(bool& valid) const override; From f058781f49c82d97074a797ac35c24ef1b9c7a0e Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 11 Aug 2017 10:07:20 -0700 Subject: [PATCH 39/42] just kidding shared_mutexes are c++17 --- interface/src/raypick/LaserPointerManager.cpp | 62 +++++++++---------- interface/src/raypick/LaserPointerManager.h | 13 ++-- interface/src/raypick/RayPickManager.cpp | 56 ++++++++--------- interface/src/raypick/RayPickManager.h | 13 ++-- 4 files changed, 69 insertions(+), 75 deletions(-) diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp index da20068cba..089b9911d0 100644 --- a/interface/src/raypick/LaserPointerManager.cpp +++ b/interface/src/raypick/LaserPointerManager.cpp @@ -15,7 +15,7 @@ QUuid LaserPointerManager::createLaserPointer(const QVariantMap& rayProps, const const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) { std::shared_ptr laserPointer = std::make_shared(rayProps, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, enabled); if (!laserPointer->getRayUID().isNull()) { - WriteLock lock(_addLock); + QWriteLocker lock(&_addLock); QUuid id = QUuid::createUuid(); _laserPointersToAdd.push(std::pair>(id, laserPointer)); return id; @@ -24,46 +24,46 @@ QUuid LaserPointerManager::createLaserPointer(const QVariantMap& rayProps, const } void LaserPointerManager::removeLaserPointer(const QUuid uid) { - WriteLock lock(_removeLock); + QWriteLocker lock(&_removeLock); _laserPointersToRemove.push(uid); } void LaserPointerManager::enableLaserPointer(const QUuid uid) { - ReadLock lock(_containsLock); + QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { - WriteLock laserLock(*_laserPointerLocks[uid]); + QWriteLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->enable(); } } void LaserPointerManager::disableLaserPointer(const QUuid uid) { - ReadLock lock(_containsLock); + QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { - WriteLock laserLock(*_laserPointerLocks[uid]); + QWriteLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->disable(); } } void LaserPointerManager::setRenderState(QUuid uid, const std::string& renderState) { - ReadLock lock(_containsLock); + QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { - WriteLock laserLock(*_laserPointerLocks[uid]); + QWriteLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->setRenderState(renderState); } } void LaserPointerManager::editRenderState(QUuid uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) { - ReadLock lock(_containsLock); + QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { - WriteLock laserLock(*_laserPointerLocks[uid]); + QWriteLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->editRenderState(state, startProps, pathProps, endProps); } } const RayPickResult LaserPointerManager::getPrevRayPickResult(const QUuid uid) { - ReadLock lock(_containsLock); + QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { - ReadLock laserLock(*_laserPointerLocks[uid]); + QReadLocker laserLock(_laserPointerLocks[uid].get()); return _laserPointers[uid]->getPrevRayPickResult(); } return RayPickResult(); @@ -72,23 +72,23 @@ const RayPickResult LaserPointerManager::getPrevRayPickResult(const QUuid uid) { void LaserPointerManager::update() { for (QUuid& uid : _laserPointers.keys()) { // This only needs to be a read lock because update won't change any of the properties that can be modified from scripts - ReadLock laserLock(*_laserPointerLocks[uid]); + QReadLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->update(); } - WriteLock containsLock(_containsLock); + QWriteLocker containsLock(&_containsLock); { - WriteLock lock(_addLock); + QWriteLocker lock(&_addLock); while (!_laserPointersToAdd.empty()) { std::pair> laserPointerToAdd = _laserPointersToAdd.front(); _laserPointersToAdd.pop(); _laserPointers[laserPointerToAdd.first] = laserPointerToAdd.second; - _laserPointerLocks[laserPointerToAdd.first] = std::make_shared(); + _laserPointerLocks[laserPointerToAdd.first] = std::make_shared(); } } { - WriteLock lock(_removeLock); + QWriteLocker lock(&_removeLock); while (!_laserPointersToRemove.empty()) { QUuid uid = _laserPointersToRemove.front(); _laserPointersToRemove.pop(); @@ -99,57 +99,57 @@ void LaserPointerManager::update() { } void LaserPointerManager::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) { - ReadLock lock(_containsLock); + QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { - WriteLock laserLock(*_laserPointerLocks[uid]); + QWriteLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->setIgnoreEntities(ignoreEntities); } } void LaserPointerManager::setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) { - ReadLock lock(_containsLock); + QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { - WriteLock laserLock(*_laserPointerLocks[uid]); + QWriteLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->setIncludeEntities(includeEntities); } } void LaserPointerManager::setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) { - ReadLock lock(_containsLock); + QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { - WriteLock laserLock(*_laserPointerLocks[uid]); + QWriteLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->setIgnoreOverlays(ignoreOverlays); } } void LaserPointerManager::setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays) { - ReadLock lock(_containsLock); + QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { - WriteLock laserLock(*_laserPointerLocks[uid]); + QWriteLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->setIncludeOverlays(includeOverlays); } } void LaserPointerManager::setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) { - ReadLock lock(_containsLock); + QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { - WriteLock laserLock(*_laserPointerLocks[uid]); + QWriteLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->setIgnoreAvatars(ignoreAvatars); } } void LaserPointerManager::setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) { - ReadLock lock(_containsLock); + QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { - WriteLock laserLock(*_laserPointerLocks[uid]); + QWriteLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->setIncludeAvatars(includeAvatars); } } void LaserPointerManager::setLockEndUUID(QUuid uid, QUuid objectID, const bool isOverlay) { - ReadLock lock(_containsLock); + QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { - WriteLock laserLock(*_laserPointerLocks[uid]); + QWriteLocker laserLock(_laserPointerLocks[uid].get()); _laserPointers[uid]->setLockEndUUID(objectID, isOverlay); } } diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h index 5e33ac77d8..b981dde9fb 100644 --- a/interface/src/raypick/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -12,8 +12,8 @@ #define hifi_LaserPointerManager_h #include -#include #include +#include #include "LaserPointer.h" @@ -44,15 +44,12 @@ public: private: QHash> _laserPointers; - QHash> _laserPointerLocks; - std::shared_mutex _addLock; + QHash> _laserPointerLocks; + QReadWriteLock _addLock; std::queue>> _laserPointersToAdd; - std::shared_mutex _removeLock; + QReadWriteLock _removeLock; std::queue _laserPointersToRemove; - std::shared_mutex _containsLock; - - typedef std::lock_guard WriteLock; - typedef std::shared_lock ReadLock; + QReadWriteLock _containsLock; }; diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp index 0fe7fdb823..68c850b295 100644 --- a/interface/src/raypick/RayPickManager.cpp +++ b/interface/src/raypick/RayPickManager.cpp @@ -111,7 +111,7 @@ void RayPickManager::update() { } } - WriteLock lock(*_rayPickLocks[uid]); + QWriteLocker lock(_rayPickLocks[uid].get()); if (rayPick->getMaxDistance() == 0.0f || (rayPick->getMaxDistance() > 0.0f && res.distance < rayPick->getMaxDistance())) { rayPick->setRayPickResult(res); } else { @@ -119,19 +119,19 @@ void RayPickManager::update() { } } - WriteLock containsLock(_containsLock); + QWriteLocker containsLock(&_containsLock); { - WriteLock lock(_addLock); + QWriteLocker lock(&_addLock); while (!_rayPicksToAdd.empty()) { std::pair> rayPickToAdd = _rayPicksToAdd.front(); _rayPicksToAdd.pop(); _rayPicks[rayPickToAdd.first] = rayPickToAdd.second; - _rayPickLocks[rayPickToAdd.first] = std::make_shared(); + _rayPickLocks[rayPickToAdd.first] = std::make_shared(); } } { - WriteLock lock(_removeLock); + QWriteLocker lock(&_removeLock); while (!_rayPicksToRemove.empty()) { QUuid uid = _rayPicksToRemove.front(); _rayPicksToRemove.pop(); @@ -172,12 +172,12 @@ QUuid RayPickManager::createRayPick(const QVariantMap& rayProps) { dirOffset = vec3FromVariant(rayProps["dirOffset"]); } - WriteLock lock(_addLock); + QWriteLocker lock(&_addLock); QUuid id = QUuid::createUuid(); _rayPicksToAdd.push(std::pair>(id, std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled))); return id; } else { - WriteLock lock(_addLock); + QWriteLocker lock(&_addLock); QUuid id = QUuid::createUuid(); _rayPicksToAdd.push(std::pair>(id, std::make_shared(filter, maxDistance, enabled))); return id; @@ -190,7 +190,7 @@ QUuid RayPickManager::createRayPick(const QVariantMap& rayProps) { direction = vec3FromVariant(rayProps["direction"]); } - WriteLock lock(_addLock); + QWriteLocker lock(&_addLock); QUuid id = QUuid::createUuid(); _rayPicksToAdd.push(std::pair>(id, std::make_shared(position, direction, filter, maxDistance, enabled))); return id; @@ -200,28 +200,28 @@ QUuid RayPickManager::createRayPick(const QVariantMap& rayProps) { } void RayPickManager::removeRayPick(const QUuid uid) { - WriteLock lock(_removeLock); + QWriteLocker lock(&_removeLock); _rayPicksToRemove.push(uid); } void RayPickManager::enableRayPick(const QUuid uid) { - ReadLock containsLock(_containsLock); + QReadLocker containsLock(&_containsLock); if (_rayPicks.contains(uid)) { - WriteLock rayPickLock(*_rayPickLocks[uid]); + QWriteLocker rayPickLock(_rayPickLocks[uid].get()); _rayPicks[uid]->enable(); } } void RayPickManager::disableRayPick(const QUuid uid) { - ReadLock containsLock(_containsLock); + QReadLocker containsLock(&_containsLock); if (_rayPicks.contains(uid)) { - WriteLock rayPickLock(*_rayPickLocks[uid]); + QWriteLocker rayPickLock(_rayPickLocks[uid].get()); _rayPicks[uid]->disable(); } } const PickRay RayPickManager::getPickRay(const QUuid uid) { - ReadLock containsLock(_containsLock); + QReadLocker containsLock(&_containsLock); if (_rayPicks.contains(uid)) { bool valid; PickRay pickRay = _rayPicks[uid]->getPickRay(valid); @@ -233,58 +233,58 @@ const PickRay RayPickManager::getPickRay(const QUuid uid) { } const RayPickResult RayPickManager::getPrevRayPickResult(const QUuid uid) { - ReadLock containsLock(_containsLock); + QReadLocker containsLock(&_containsLock); if (_rayPicks.contains(uid)) { - ReadLock lock(*_rayPickLocks[uid]); + QReadLocker lock(_rayPickLocks[uid].get()); return _rayPicks[uid]->getPrevRayPickResult(); } return RayPickResult(); } void RayPickManager::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) { - ReadLock containsLock(_containsLock); + QReadLocker containsLock(&_containsLock); if (_rayPicks.contains(uid)) { - WriteLock lock(*_rayPickLocks[uid]); + QWriteLocker lock(_rayPickLocks[uid].get()); _rayPicks[uid]->setIgnoreEntities(ignoreEntities); } } void RayPickManager::setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) { - ReadLock containsLock(_containsLock); + QReadLocker containsLock(&_containsLock); if (_rayPicks.contains(uid)) { - WriteLock lock(*_rayPickLocks[uid]); + QWriteLocker lock(_rayPickLocks[uid].get()); _rayPicks[uid]->setIncludeEntities(includeEntities); } } void RayPickManager::setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) { - ReadLock containsLock(_containsLock); + QReadLocker containsLock(&_containsLock); if (_rayPicks.contains(uid)) { - WriteLock lock(*_rayPickLocks[uid]); + QWriteLocker lock(_rayPickLocks[uid].get()); _rayPicks[uid]->setIgnoreOverlays(ignoreOverlays); } } void RayPickManager::setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays) { - ReadLock containsLock(_containsLock); + QReadLocker containsLock(&_containsLock); if (_rayPicks.contains(uid)) { - WriteLock lock(*_rayPickLocks[uid]); + QWriteLocker lock(_rayPickLocks[uid].get()); _rayPicks[uid]->setIncludeOverlays(includeOverlays); } } void RayPickManager::setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) { - ReadLock containsLock(_containsLock); + QReadLocker containsLock(&_containsLock); if (_rayPicks.contains(uid)) { - WriteLock lock(*_rayPickLocks[uid]); + QWriteLocker lock(_rayPickLocks[uid].get()); _rayPicks[uid]->setIgnoreAvatars(ignoreAvatars); } } void RayPickManager::setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) { - ReadLock containsLock(_containsLock); + QReadLocker containsLock(&_containsLock); if (_rayPicks.contains(uid)) { - WriteLock lock(*_rayPickLocks[uid]); + QWriteLocker lock(_rayPickLocks[uid].get()); _rayPicks[uid]->setIncludeAvatars(includeAvatars); } } \ No newline at end of file diff --git a/interface/src/raypick/RayPickManager.h b/interface/src/raypick/RayPickManager.h index 9055e060ef..e422995810 100644 --- a/interface/src/raypick/RayPickManager.h +++ b/interface/src/raypick/RayPickManager.h @@ -14,8 +14,8 @@ #include "RayPick.h" #include -#include #include +#include #include "RegisteredMetaTypes.h" #include "DependencyManager.h" @@ -63,12 +63,12 @@ public slots: private: QHash> _rayPicks; - QHash> _rayPickLocks; - std::shared_mutex _addLock; + QHash> _rayPickLocks; + QReadWriteLock _addLock; std::queue>> _rayPicksToAdd; - std::shared_mutex _removeLock; + QReadWriteLock _removeLock; std::queue _rayPicksToRemove; - std::shared_mutex _containsLock; + QReadWriteLock _containsLock; typedef QHash, std::unordered_map> RayPickCache; @@ -91,9 +91,6 @@ private: unsigned int INTERSECTED_AVATAR() { return IntersectionType::AVATAR; } unsigned int INTERSECTED_HUD() { return IntersectionType::HUD; } - typedef std::lock_guard WriteLock; - typedef std::shared_lock ReadLock; - }; #endif // hifi_RayPickManager_h \ No newline at end of file From 9bb7e6685945a9e051af3f2e0cf6dfef6880ff35 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 15 Aug 2017 13:36:41 -0700 Subject: [PATCH 40/42] separate raypickscriptinginterface, cleanup --- interface/src/Application.cpp | 13 ++- interface/src/Application.h | 4 + interface/src/raypick/LaserPointer.cpp | 15 +-- interface/src/raypick/LaserPointer.h | 19 ++-- interface/src/raypick/LaserPointerManager.cpp | 3 +- interface/src/raypick/LaserPointerManager.h | 2 +- .../LaserPointerScriptingInterface.cpp | 5 +- .../raypick/LaserPointerScriptingInterface.h | 3 +- interface/src/raypick/RayPickManager.cpp | 71 +++--------- interface/src/raypick/RayPickManager.h | 60 +++------- .../src/raypick/RayPickScriptingInterface.cpp | 107 ++++++++++++++++++ .../src/raypick/RayPickScriptingInterface.h | 70 ++++++++++++ 12 files changed, 240 insertions(+), 132 deletions(-) create mode 100644 interface/src/raypick/RayPickScriptingInterface.cpp create mode 100644 interface/src/raypick/RayPickScriptingInterface.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3d2841923f..750c41d48a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -193,8 +193,9 @@ #include #include #include + +#include #include -#include #include "commerce/Ledger.h" #include "commerce/Wallet.h" @@ -608,7 +609,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { DependencyManager::set(); DependencyManager::set(); - DependencyManager::set(); + DependencyManager::set(); return previousSessionCrashed; } @@ -5096,8 +5097,8 @@ void Application::update(float deltaTime) { } { - PROFILE_RANGE(app, "RayPick"); - DependencyManager::get()->update(); + PROFILE_RANGE(app, "RayPickManager"); + _rayPickManager.update(); } { @@ -5965,6 +5966,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("AudioScope", DependencyManager::get().data()); scriptEngine->registerGlobalObject("AvatarBookmarks", DependencyManager::get().data()); scriptEngine->registerGlobalObject("LocationBookmarks", DependencyManager::get().data()); + + scriptEngine->registerGlobalObject("RayPick", DependencyManager::get().data()); scriptEngine->registerGlobalObject("LaserPointers", DependencyManager::get().data()); // Caches @@ -6019,8 +6022,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("AvatarInputs", AvatarInputs::getInstance()); scriptEngine->registerGlobalObject("ContextOverlay", DependencyManager::get().data()); - scriptEngine->registerGlobalObject("RayPick", DependencyManager::get().data()); - qScriptRegisterMetaType(scriptEngine, OverlayIDtoScriptValue, OverlayIDfromScriptValue); // connect this script engines printedMessage signal to the global ScriptEngines these various messages diff --git a/interface/src/Application.h b/interface/src/Application.h index fcd47faa41..8a38116fe8 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -70,6 +70,8 @@ #include "ui/OverlayConductor.h" #include "ui/overlays/Overlays.h" #include "UndoStackScriptingInterface.h" + +#include "raypick/RayPickManager.h" #include "raypick/LaserPointerManager.h" #include @@ -303,6 +305,7 @@ public: bool getSaveAvatarOverrideUrl() { return _saveAvatarOverrideUrl; } LaserPointerManager& getLaserPointerManager() { return _laserPointerManager; } + RayPickManager& getRayPickManager() { return _rayPickManager; } signals: void svoImportRequested(const QString& url); @@ -702,6 +705,7 @@ private: bool _saveAvatarOverrideUrl { false }; LaserPointerManager _laserPointerManager; + RayPickManager _rayPickManager; }; #endif // hifi_Application_h diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 0e1d384e5d..f4adcc736d 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -11,9 +11,10 @@ #include "LaserPointer.h" #include "Application.h" +#include "ui/overlays/Overlay.h" #include "avatar/AvatarManager.h" -LaserPointer::LaserPointer(const QVariantMap& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, +LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) : _renderingEnabled(enabled), _renderStates(renderStates), @@ -22,7 +23,7 @@ LaserPointer::LaserPointer(const QVariantMap& rayProps, const RenderStateMap& re _centerEndY(centerEndY), _lockEnd(lockEnd) { - _rayPickUID = DependencyManager::get()->createRayPick(rayProps); + _rayPickUID = DependencyManager::get()->createRayPick(rayProps); for (auto& state : _renderStates) { if (!enabled || state.first != _currentRenderState) { @@ -37,7 +38,7 @@ LaserPointer::LaserPointer(const QVariantMap& rayProps, const RenderStateMap& re } LaserPointer::~LaserPointer() { - DependencyManager::get()->removeRayPick(_rayPickUID); + DependencyManager::get()->removeRayPick(_rayPickUID); for (auto& renderState : _renderStates) { renderState.second.deleteOverlays(); @@ -48,12 +49,12 @@ LaserPointer::~LaserPointer() { } void LaserPointer::enable() { - DependencyManager::get()->enableRayPick(_rayPickUID); + DependencyManager::get()->enableRayPick(_rayPickUID); _renderingEnabled = true; } void LaserPointer::disable() { - DependencyManager::get()->disableRayPick(_rayPickUID); + DependencyManager::get()->disableRayPick(_rayPickUID); _renderingEnabled = false; if (!_currentRenderState.empty()) { if (_renderStates.find(_currentRenderState) != _renderStates.end()) { @@ -90,7 +91,7 @@ void LaserPointer::updateRenderStateOverlay(const OverlayID& id, const QVariant& } void LaserPointer::updateRenderState(const RenderState& renderState, const IntersectionType type, const float distance, const QUuid& objectID, const bool defaultState) { - PickRay pickRay = DependencyManager::get()->getPickRay(_rayPickUID); + PickRay pickRay = qApp->getRayPickManager().getPickRay(_rayPickUID); if (!renderState.getStartID().isNull()) { QVariantMap startProps; startProps.insert("position", vec3toVariant(pickRay.origin)); @@ -180,7 +181,7 @@ void LaserPointer::disableRenderState(const RenderState& renderState) { } void LaserPointer::update() { - RayPickResult prevRayPickResult = DependencyManager::get()->getPrevRayPickResult(_rayPickUID); + RayPickResult prevRayPickResult = DependencyManager::get()->getPrevRayPickResult(_rayPickUID); if (_renderingEnabled && !_currentRenderState.empty() && _renderStates.find(_currentRenderState) != _renderStates.end() && prevRayPickResult.type != IntersectionType::NONE) { updateRenderState(_renderStates[_currentRenderState], prevRayPickResult.type, prevRayPickResult.distance, prevRayPickResult.objectID, false); disableRenderState(_defaultRenderStates[_currentRenderState].second); diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index aaa9dad83f..d901d12cf4 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -13,10 +13,9 @@ #include #include "glm/glm.hpp" -#include "ui/overlays/Overlay.h" #include -#include "RayPickManager.h" +#include "raypick/RayPickScriptingInterface.h" class RayPickResult; @@ -52,25 +51,25 @@ public: typedef std::unordered_map RenderStateMap; typedef std::unordered_map> DefaultRenderStateMap; - LaserPointer(const QVariantMap& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, + LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled); ~LaserPointer(); QUuid getRayUID() { return _rayPickUID; } void enable(); void disable(); - const RayPickResult getPrevRayPickResult() { return DependencyManager::get()->getPrevRayPickResult(_rayPickUID); } + const RayPickResult getPrevRayPickResult() { return DependencyManager::get()->getPrevRayPickResult(_rayPickUID); } void setRenderState(const std::string& state); // You cannot use editRenderState to change the overlay type of any part of the laser pointer. You can only edit the properties of the existing overlays. void editRenderState(const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps); - void setIgnoreEntities(const QScriptValue& ignoreEntities) { DependencyManager::get()->setIgnoreEntities(_rayPickUID, ignoreEntities); } - void setIncludeEntities(const QScriptValue& includeEntities) { DependencyManager::get()->setIncludeEntities(_rayPickUID, includeEntities); } - void setIgnoreOverlays(const QScriptValue& ignoreOverlays) { DependencyManager::get()->setIgnoreOverlays(_rayPickUID, ignoreOverlays); } - void setIncludeOverlays(const QScriptValue& includeOverlays) { DependencyManager::get()->setIncludeOverlays(_rayPickUID, includeOverlays); } - void setIgnoreAvatars(const QScriptValue& ignoreAvatars) { DependencyManager::get()->setIgnoreAvatars(_rayPickUID, ignoreAvatars); } - void setIncludeAvatars(const QScriptValue& includeAvatars) { DependencyManager::get()->setIncludeAvatars(_rayPickUID, includeAvatars); } + void setIgnoreEntities(const QScriptValue& ignoreEntities) { DependencyManager::get()->setIgnoreEntities(_rayPickUID, ignoreEntities); } + void setIncludeEntities(const QScriptValue& includeEntities) { DependencyManager::get()->setIncludeEntities(_rayPickUID, includeEntities); } + void setIgnoreOverlays(const QScriptValue& ignoreOverlays) { DependencyManager::get()->setIgnoreOverlays(_rayPickUID, ignoreOverlays); } + void setIncludeOverlays(const QScriptValue& includeOverlays) { DependencyManager::get()->setIncludeOverlays(_rayPickUID, includeOverlays); } + void setIgnoreAvatars(const QScriptValue& ignoreAvatars) { DependencyManager::get()->setIgnoreAvatars(_rayPickUID, ignoreAvatars); } + void setIncludeAvatars(const QScriptValue& includeAvatars) { DependencyManager::get()->setIncludeAvatars(_rayPickUID, includeAvatars); } void setLockEndUUID(QUuid objectID, const bool isOverlay) { _objectLockEnd = std::pair(objectID, isOverlay); } diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp index 089b9911d0..908bcc39f1 100644 --- a/interface/src/raypick/LaserPointerManager.cpp +++ b/interface/src/raypick/LaserPointerManager.cpp @@ -9,9 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "LaserPointerManager.h" -#include "RayPick.h" -QUuid LaserPointerManager::createLaserPointer(const QVariantMap& rayProps, const LaserPointer::RenderStateMap& renderStates, const LaserPointer::DefaultRenderStateMap& defaultRenderStates, +QUuid LaserPointerManager::createLaserPointer(const QVariant& rayProps, const LaserPointer::RenderStateMap& renderStates, const LaserPointer::DefaultRenderStateMap& defaultRenderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) { std::shared_ptr laserPointer = std::make_shared(rayProps, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, enabled); if (!laserPointer->getRayUID().isNull()) { diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h index b981dde9fb..020b778983 100644 --- a/interface/src/raypick/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -22,7 +22,7 @@ class RayPickResult; class LaserPointerManager { public: - QUuid createLaserPointer(const QVariantMap& rayProps, const LaserPointer::RenderStateMap& renderStates, const LaserPointer::DefaultRenderStateMap& defaultRenderStates, + QUuid createLaserPointer(const QVariant& rayProps, const LaserPointer::RenderStateMap& renderStates, const LaserPointer::DefaultRenderStateMap& defaultRenderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled); void removeLaserPointer(const QUuid uid); void enableLaserPointer(const QUuid uid); diff --git a/interface/src/raypick/LaserPointerScriptingInterface.cpp b/interface/src/raypick/LaserPointerScriptingInterface.cpp index 9b7f18d436..a976a00893 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.cpp +++ b/interface/src/raypick/LaserPointerScriptingInterface.cpp @@ -12,11 +12,8 @@ #include "LaserPointerScriptingInterface.h" #include -#include "RegisteredMetaTypes.h" #include "GLMHelpers.h" -#include "Application.h" - QUuid LaserPointerScriptingInterface::createLaserPointer(const QVariant& properties) { QVariantMap propertyMap = properties.toMap(); @@ -69,7 +66,7 @@ QUuid LaserPointerScriptingInterface::createLaserPointer(const QVariant& propert } } - return qApp->getLaserPointerManager().createLaserPointer(propertyMap, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, enabled); + return qApp->getLaserPointerManager().createLaserPointer(properties, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, enabled); } void LaserPointerScriptingInterface::editRenderState(QUuid uid, const QString& renderState, const QVariant& properties) { diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h index 7866a5da51..8ae263b0ec 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -13,7 +13,6 @@ #include -#include "LaserPointerManager.h" #include "RegisteredMetaTypes.h" #include "DependencyManager.h" #include "Application.h" @@ -41,7 +40,7 @@ public slots: Q_INVOKABLE void setLockEndUUID(QUuid uid, QUuid objectID, const bool isOverlay) { qApp->getLaserPointerManager().setLockEndUUID(uid, objectID, isOverlay); } private: - const RenderState buildRenderState(const QVariantMap & propMap); + const RenderState buildRenderState(const QVariantMap& propMap); }; diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp index 68c850b295..cf135ffdca 100644 --- a/interface/src/raypick/RayPickManager.cpp +++ b/interface/src/raypick/RayPickManager.cpp @@ -141,62 +141,25 @@ void RayPickManager::update() { } } -QUuid RayPickManager::createRayPick(const QVariantMap& rayProps) { - bool enabled = false; - if (rayProps["enabled"].isValid()) { - enabled = rayProps["enabled"].toBool(); - } +QUuid RayPickManager::createRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const RayPickFilter& filter, const float maxDistance, const bool enabled) { + QWriteLocker lock(&_addLock); + QUuid id = QUuid::createUuid(); + _rayPicksToAdd.push(std::pair>(id, std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled))); + return id; +} - RayPickFilter filter = RayPickFilter(); - if (rayProps["filter"].isValid()) { - filter = RayPickFilter(rayProps["filter"].toUInt()); - } +QUuid RayPickManager::createRayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled) { + QWriteLocker lock(&_addLock); + QUuid id = QUuid::createUuid(); + _rayPicksToAdd.push(std::pair>(id, std::make_shared(filter, maxDistance, enabled))); + return id; +} - float maxDistance = 0.0f; - if (rayProps["maxDistance"].isValid()) { - maxDistance = rayProps["maxDistance"].toFloat(); - } - - if (rayProps["joint"].isValid()) { - std::string jointName = rayProps["joint"].toString().toStdString(); - - if (jointName != "Mouse") { - // x = upward, y = forward, z = lateral - glm::vec3 posOffset = Vectors::ZERO; - if (rayProps["posOffset"].isValid()) { - posOffset = vec3FromVariant(rayProps["posOffset"]); - } - - glm::vec3 dirOffset = Vectors::UP; - if (rayProps["dirOffset"].isValid()) { - dirOffset = vec3FromVariant(rayProps["dirOffset"]); - } - - QWriteLocker lock(&_addLock); - QUuid id = QUuid::createUuid(); - _rayPicksToAdd.push(std::pair>(id, std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled))); - return id; - } else { - QWriteLocker lock(&_addLock); - QUuid id = QUuid::createUuid(); - _rayPicksToAdd.push(std::pair>(id, std::make_shared(filter, maxDistance, enabled))); - return id; - } - } else if (rayProps["position"].isValid()) { - glm::vec3 position = vec3FromVariant(rayProps["position"]); - - glm::vec3 direction = -Vectors::UP; - if (rayProps["direction"].isValid()) { - direction = vec3FromVariant(rayProps["direction"]); - } - - QWriteLocker lock(&_addLock); - QUuid id = QUuid::createUuid(); - _rayPicksToAdd.push(std::pair>(id, std::make_shared(position, direction, filter, maxDistance, enabled))); - return id; - } - - return QUuid(); +QUuid RayPickManager::createRayPick(const glm::vec3& position, const glm::vec3& direction, const RayPickFilter& filter, const float maxDistance, const bool enabled) { + QWriteLocker lock(&_addLock); + QUuid id = QUuid::createUuid(); + _rayPicksToAdd.push(std::pair>(id, std::make_shared(position, direction, filter, maxDistance, enabled))); + return id; } void RayPickManager::removeRayPick(const QUuid uid) { diff --git a/interface/src/raypick/RayPickManager.h b/interface/src/raypick/RayPickManager.h index e422995810..8ef2ceebe0 100644 --- a/interface/src/raypick/RayPickManager.h +++ b/interface/src/raypick/RayPickManager.h @@ -18,48 +18,32 @@ #include #include "RegisteredMetaTypes.h" -#include "DependencyManager.h" #include #include class RayPickResult; -class RayPickManager : public QObject, public Dependency { - Q_OBJECT - Q_PROPERTY(unsigned int PICK_NOTHING READ PICK_NOTHING CONSTANT) - Q_PROPERTY(unsigned int PICK_ENTITIES READ PICK_ENTITIES CONSTANT) - Q_PROPERTY(unsigned int PICK_OVERLAYS READ PICK_OVERLAYS CONSTANT) - Q_PROPERTY(unsigned int PICK_AVATARS READ PICK_AVATARS CONSTANT) - Q_PROPERTY(unsigned int PICK_HUD READ PICK_HUD CONSTANT) - Q_PROPERTY(unsigned int PICK_BOUNDING_BOX READ PICK_BOUNDING_BOX CONSTANT) - Q_PROPERTY(unsigned int PICK_INCLUDE_INVISIBLE READ PICK_INCLUDE_INVISIBLE CONSTANT) - Q_PROPERTY(unsigned int PICK_INCLUDE_NONCOLLIDABLE READ PICK_INCLUDE_NONCOLLIDABLE CONSTANT) - Q_PROPERTY(unsigned int PICK_ALL_INTERSECTIONS READ PICK_ALL_INTERSECTIONS CONSTANT) - Q_PROPERTY(unsigned int INTERSECTED_NONE READ INTERSECTED_NONE CONSTANT) - Q_PROPERTY(unsigned int INTERSECTED_ENTITY READ INTERSECTED_ENTITY CONSTANT) - Q_PROPERTY(unsigned int INTERSECTED_OVERLAY READ INTERSECTED_OVERLAY CONSTANT) - Q_PROPERTY(unsigned int INTERSECTED_AVATAR READ INTERSECTED_AVATAR CONSTANT) - Q_PROPERTY(unsigned int INTERSECTED_HUD READ INTERSECTED_HUD CONSTANT) - SINGLETON_DEPENDENCY +class RayPickManager { public: void update(); const PickRay getPickRay(const QUuid uid); -public slots: - Q_INVOKABLE QUuid createRayPick(const QVariantMap& rayProps); - Q_INVOKABLE void removeRayPick(const QUuid uid); - Q_INVOKABLE void enableRayPick(const QUuid uid); - Q_INVOKABLE void disableRayPick(const QUuid uid); - Q_INVOKABLE const RayPickResult getPrevRayPickResult(const QUuid uid); + QUuid createRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const RayPickFilter& filter, const float maxDistance, const bool enabled); + QUuid createRayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled); + QUuid createRayPick(const glm::vec3& position, const glm::vec3& direction, const RayPickFilter& filter, const float maxDistance, const bool enabled); + void removeRayPick(const QUuid uid); + void enableRayPick(const QUuid uid); + void disableRayPick(const QUuid uid); + const RayPickResult getPrevRayPickResult(const QUuid uid); - Q_INVOKABLE void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities); - Q_INVOKABLE void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities); - Q_INVOKABLE void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays); - Q_INVOKABLE void setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays); - Q_INVOKABLE void setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars); - Q_INVOKABLE void setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars); + void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities); + void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities); + void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays); + void setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays); + void setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars); + void setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars); private: QHash> _rayPicks; @@ -75,22 +59,6 @@ private: // Returns true if this ray exists in the cache, and if it does, update res if the cached result is closer bool checkAndCompareCachedResults(QPair& ray, RayPickCache& cache, RayPickResult& res, const RayPickFilter::Flags& mask); void cacheResult(const bool intersects, const RayPickResult& resTemp, const RayPickFilter::Flags& mask, RayPickResult& res, QPair& ray, RayPickCache& cache); - - unsigned int PICK_NOTHING() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_NOTHING); } - unsigned int PICK_ENTITIES() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_ENTITIES); } - unsigned int PICK_OVERLAYS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_OVERLAYS); } - unsigned int PICK_AVATARS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_AVATARS); } - unsigned int PICK_HUD() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_HUD); } - unsigned int PICK_BOUNDING_BOX() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_COURSE); } - unsigned int PICK_INCLUDE_INVISIBLE() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_INCLUDE_INVISIBLE); } - unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_INCLUDE_NONCOLLIDABLE); } - unsigned int PICK_ALL_INTERSECTIONS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_ALL_INTERSECTIONS); } - unsigned int INTERSECTED_NONE() { return IntersectionType::NONE; } - unsigned int INTERSECTED_ENTITY() { return IntersectionType::ENTITY; } - unsigned int INTERSECTED_OVERLAY() { return IntersectionType::OVERLAY; } - unsigned int INTERSECTED_AVATAR() { return IntersectionType::AVATAR; } - unsigned int INTERSECTED_HUD() { return IntersectionType::HUD; } - }; #endif // hifi_RayPickManager_h \ No newline at end of file diff --git a/interface/src/raypick/RayPickScriptingInterface.cpp b/interface/src/raypick/RayPickScriptingInterface.cpp new file mode 100644 index 0000000000..aa1613d696 --- /dev/null +++ b/interface/src/raypick/RayPickScriptingInterface.cpp @@ -0,0 +1,107 @@ +// +// RayPickScriptingInterface.cpp +// interface/src/raypick +// +// Created by Sam Gondelman 8/15/2017 +// Copyright 2017 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 "RayPickScriptingInterface.h" + +#include +#include "GLMHelpers.h" +#include "Application.h" + +QUuid RayPickScriptingInterface::createRayPick(const QVariant& properties) { + QVariantMap propMap = properties.toMap(); + + bool enabled = false; + if (propMap["enabled"].isValid()) { + enabled = propMap["enabled"].toBool(); + } + + RayPickFilter filter = RayPickFilter(); + if (propMap["filter"].isValid()) { + filter = RayPickFilter(propMap["filter"].toUInt()); + } + + float maxDistance = 0.0f; + if (propMap["maxDistance"].isValid()) { + maxDistance = propMap["maxDistance"].toFloat(); + } + + if (propMap["joint"].isValid()) { + std::string jointName = propMap["joint"].toString().toStdString(); + + if (jointName != "Mouse") { + // x = upward, y = forward, z = lateral + glm::vec3 posOffset = Vectors::ZERO; + if (propMap["posOffset"].isValid()) { + posOffset = vec3FromVariant(propMap["posOffset"]); + } + + glm::vec3 dirOffset = Vectors::UP; + if (propMap["dirOffset"].isValid()) { + dirOffset = vec3FromVariant(propMap["dirOffset"]); + } + + return qApp->getRayPickManager().createRayPick(jointName, posOffset, dirOffset, filter, maxDistance, enabled); + } else { + return qApp->getRayPickManager().createRayPick(filter, maxDistance, enabled); + } + } else if (propMap["position"].isValid()) { + glm::vec3 position = vec3FromVariant(propMap["position"]); + + glm::vec3 direction = -Vectors::UP; + if (propMap["direction"].isValid()) { + direction = vec3FromVariant(propMap["direction"]); + } + + return qApp->getRayPickManager().createRayPick(position, direction, filter, maxDistance, enabled); + } + + return QUuid(); +} + +void RayPickScriptingInterface::enableRayPick(QUuid uid) { + qApp->getRayPickManager().enableRayPick(uid); +} + +void RayPickScriptingInterface::disableRayPick(QUuid uid) { + qApp->getRayPickManager().disableRayPick(uid); +} + +void RayPickScriptingInterface::removeRayPick(QUuid uid) { + qApp->getRayPickManager().removeRayPick(uid); +} + +RayPickResult RayPickScriptingInterface::getPrevRayPickResult(QUuid uid) { + return qApp->getRayPickManager().getPrevRayPickResult(uid); +} + +void RayPickScriptingInterface::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) { + qApp->getRayPickManager().setIgnoreEntities(uid, ignoreEntities); +} + +void RayPickScriptingInterface::setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) { + qApp->getRayPickManager().setIncludeEntities(uid, includeEntities); +} + +void RayPickScriptingInterface::setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) { + qApp->getRayPickManager().setIgnoreOverlays(uid, ignoreOverlays); +} + +void RayPickScriptingInterface::setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays) { + qApp->getRayPickManager().setIncludeOverlays(uid, includeOverlays); +} + +void RayPickScriptingInterface::setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) { + qApp->getRayPickManager().setIgnoreAvatars(uid, ignoreAvatars); +} + +void RayPickScriptingInterface::setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) { + qApp->getRayPickManager().setIncludeAvatars(uid, includeAvatars); +} \ No newline at end of file diff --git a/interface/src/raypick/RayPickScriptingInterface.h b/interface/src/raypick/RayPickScriptingInterface.h new file mode 100644 index 0000000000..e576b5d076 --- /dev/null +++ b/interface/src/raypick/RayPickScriptingInterface.h @@ -0,0 +1,70 @@ +// +// RayPickScriptingInterface.h +// interface/src/raypick +// +// Created by Sam Gondelman 8/15/2017 +// Copyright 2017 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_RayPickScriptingInterface_h +#define hifi_RayPickScriptingInterface_h + +#include + +#include "RegisteredMetaTypes.h" +#include "DependencyManager.h" + +#include "RayPick.h" + +class RayPickScriptingInterface : public QObject, public Dependency { + Q_OBJECT + Q_PROPERTY(unsigned int PICK_NOTHING READ PICK_NOTHING CONSTANT) + Q_PROPERTY(unsigned int PICK_ENTITIES READ PICK_ENTITIES CONSTANT) + Q_PROPERTY(unsigned int PICK_OVERLAYS READ PICK_OVERLAYS CONSTANT) + Q_PROPERTY(unsigned int PICK_AVATARS READ PICK_AVATARS CONSTANT) + Q_PROPERTY(unsigned int PICK_HUD READ PICK_HUD CONSTANT) + Q_PROPERTY(unsigned int PICK_COURSE READ PICK_COURSE CONSTANT) + Q_PROPERTY(unsigned int PICK_INCLUDE_INVISIBLE READ PICK_INCLUDE_INVISIBLE CONSTANT) + Q_PROPERTY(unsigned int PICK_INCLUDE_NONCOLLIDABLE READ PICK_INCLUDE_NONCOLLIDABLE CONSTANT) + Q_PROPERTY(unsigned int PICK_ALL_INTERSECTIONS READ PICK_ALL_INTERSECTIONS CONSTANT) + Q_PROPERTY(unsigned int INTERSECTED_NONE READ INTERSECTED_NONE CONSTANT) + Q_PROPERTY(unsigned int INTERSECTED_ENTITY READ INTERSECTED_ENTITY CONSTANT) + Q_PROPERTY(unsigned int INTERSECTED_OVERLAY READ INTERSECTED_OVERLAY CONSTANT) + Q_PROPERTY(unsigned int INTERSECTED_AVATAR READ INTERSECTED_AVATAR CONSTANT) + Q_PROPERTY(unsigned int INTERSECTED_HUD READ INTERSECTED_HUD CONSTANT) + SINGLETON_DEPENDENCY + +public slots: + Q_INVOKABLE QUuid createRayPick(const QVariant& properties); + Q_INVOKABLE void enableRayPick(QUuid uid); + Q_INVOKABLE void disableRayPick(QUuid uid); + Q_INVOKABLE void removeRayPick(QUuid uid); + Q_INVOKABLE RayPickResult getPrevRayPickResult(QUuid uid); + + Q_INVOKABLE void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities); + Q_INVOKABLE void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities); + Q_INVOKABLE void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays); + Q_INVOKABLE void setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays); + Q_INVOKABLE void setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars); + Q_INVOKABLE void setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars); + +private: + unsigned int PICK_NOTHING() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_NOTHING); } + unsigned int PICK_ENTITIES() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_ENTITIES); } + unsigned int PICK_OVERLAYS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_OVERLAYS); } + unsigned int PICK_AVATARS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_AVATARS); } + unsigned int PICK_HUD() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_HUD); } + unsigned int PICK_COURSE() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_COURSE); } + unsigned int PICK_INCLUDE_INVISIBLE() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_INCLUDE_INVISIBLE); } + unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_INCLUDE_NONCOLLIDABLE); } + unsigned int PICK_ALL_INTERSECTIONS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_ALL_INTERSECTIONS); } + unsigned int INTERSECTED_NONE() { return IntersectionType::NONE; } + unsigned int INTERSECTED_ENTITY() { return IntersectionType::ENTITY; } + unsigned int INTERSECTED_OVERLAY() { return IntersectionType::OVERLAY; } + unsigned int INTERSECTED_AVATAR() { return IntersectionType::AVATAR; } + unsigned int INTERSECTED_HUD() { return IntersectionType::HUD; } +}; + +#endif // hifi_RayPickScriptingInterface_h From a641fb7a7fbe1af7a4b1b6a2cf79571203e629fe Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 15 Aug 2017 18:03:52 -0700 Subject: [PATCH 41/42] rename qvector findRayIntersection to avoid script conflicts --- interface/src/avatar/AvatarManager.cpp | 10 +++++----- interface/src/avatar/AvatarManager.h | 6 +++--- interface/src/raypick/RayPickManager.cpp | 6 +++--- interface/src/ui/overlays/Overlays.cpp | 18 +++++++++--------- interface/src/ui/overlays/Overlays.h | 8 ++++---- .../entities/src/EntityScriptingInterface.cpp | 4 ++-- .../entities/src/EntityScriptingInterface.h | 2 +- 7 files changed, 27 insertions(+), 27 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 154cd945f1..e7a83b5abc 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -476,15 +476,15 @@ RayToAvatarIntersectionResult AvatarManager::findRayIntersection(const PickRay& QVector avatarsToInclude = qVectorEntityItemIDFromScriptValue(avatarIdsToInclude); QVector avatarsToDiscard = qVectorEntityItemIDFromScriptValue(avatarIdsToDiscard); - return findRayIntersection(ray, avatarsToInclude, avatarsToDiscard); + return findRayIntersectionVector(ray, avatarsToInclude, avatarsToDiscard); } -RayToAvatarIntersectionResult AvatarManager::findRayIntersection(const PickRay& ray, - const QVector& avatarsToInclude, - const QVector& avatarsToDiscard) { +RayToAvatarIntersectionResult AvatarManager::findRayIntersectionVector(const PickRay& ray, + const QVector& avatarsToInclude, + const QVector& avatarsToDiscard) { RayToAvatarIntersectionResult result; if (QThread::currentThread() != thread()) { - BLOCKING_INVOKE_METHOD(const_cast(this), "findRayIntersection", + BLOCKING_INVOKE_METHOD(const_cast(this), "findRayIntersectionVector", Q_RETURN_ARG(RayToAvatarIntersectionResult, result), Q_ARG(const PickRay&, ray), Q_ARG(const QVector&, avatarsToInclude), diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index c21214484b..810d419a55 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -73,9 +73,9 @@ public: Q_INVOKABLE RayToAvatarIntersectionResult findRayIntersection(const PickRay& ray, const QScriptValue& avatarIdsToInclude = QScriptValue(), const QScriptValue& avatarIdsToDiscard = QScriptValue()); - Q_INVOKABLE RayToAvatarIntersectionResult findRayIntersection(const PickRay& ray, - const QVector& avatarsToInclude, - const QVector& avatarsToDiscard); + RayToAvatarIntersectionResult findRayIntersectionVector(const PickRay& ray, + const QVector& avatarsToInclude, + const QVector& avatarsToDiscard); // TODO: remove this HACK once we settle on optimal default sort coefficients Q_INVOKABLE float getAvatarSortCoefficient(const QString& name); diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp index cf135ffdca..8b639d4a81 100644 --- a/interface/src/raypick/RayPickManager.cpp +++ b/interface/src/raypick/RayPickManager.cpp @@ -67,7 +67,7 @@ void RayPickManager::update() { bool noncollidable = rayPick->getFilter().doesPickNonCollidable(); RayPickFilter::Flags entityMask = rayPick->getFilter().getEntityFlags(); if (!checkAndCompareCachedResults(rayKey, results, res, entityMask)) { - entityRes = DependencyManager::get()->findRayIntersection(ray, true, rayPick->getIncludeEntites(), rayPick->getIgnoreEntites(), !invisible, !noncollidable); + entityRes = DependencyManager::get()->findRayIntersectionVector(ray, true, rayPick->getIncludeEntites(), rayPick->getIgnoreEntites(), !invisible, !noncollidable); fromCache = false; } @@ -84,7 +84,7 @@ void RayPickManager::update() { bool noncollidable = rayPick->getFilter().doesPickNonCollidable(); RayPickFilter::Flags overlayMask = rayPick->getFilter().getOverlayFlags(); if (!checkAndCompareCachedResults(rayKey, results, res, overlayMask)) { - overlayRes = qApp->getOverlays().findRayIntersection(ray, true, rayPick->getIncludeOverlays(), rayPick->getIgnoreOverlays(), !invisible, !noncollidable); + overlayRes = qApp->getOverlays().findRayIntersectionVector(ray, true, rayPick->getIncludeOverlays(), rayPick->getIgnoreOverlays(), !invisible, !noncollidable); fromCache = false; } @@ -97,7 +97,7 @@ void RayPickManager::update() { if (rayPick->getFilter().doesPickAvatars()) { RayPickFilter::Flags avatarMask = rayPick->getFilter().getAvatarFlags(); if (!checkAndCompareCachedResults(rayKey, results, res, avatarMask)) { - RayToAvatarIntersectionResult avatarRes = DependencyManager::get()->findRayIntersection(ray, rayPick->getIncludeAvatars(), rayPick->getIgnoreAvatars()); + RayToAvatarIntersectionResult avatarRes = DependencyManager::get()->findRayIntersectionVector(ray, rayPick->getIncludeAvatars(), rayPick->getIgnoreAvatars()); cacheResult(avatarRes.intersects, RayPickResult(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection), avatarMask, res, rayKey, results); } } diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index a598788771..0f7de8bd79 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -534,15 +534,15 @@ RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray, const QVector overlaysToInclude = qVectorOverlayIDFromScriptValue(overlayIDsToInclude); const QVector overlaysToDiscard = qVectorOverlayIDFromScriptValue(overlayIDsToDiscard); - return findRayIntersection(ray, precisionPicking, - overlaysToInclude, overlaysToDiscard, visibleOnly, collidableOnly); + return findRayIntersectionVector(ray, precisionPicking, + overlaysToInclude, overlaysToDiscard, visibleOnly, collidableOnly); } -RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray, bool precisionPicking, - const QVector& overlaysToInclude, - const QVector& overlaysToDiscard, - bool visibleOnly, bool collidableOnly) { +RayToOverlayIntersectionResult Overlays::findRayIntersectionVector(const PickRay& ray, bool precisionPicking, + const QVector& overlaysToInclude, + const QVector& overlaysToDiscard, + bool visibleOnly, bool collidableOnly) { float bestDistance = std::numeric_limits::max(); bool bestIsFront = false; @@ -908,21 +908,21 @@ RayToOverlayIntersectionResult Overlays::findRayIntersectionForMouseEvent(PickRa // first priority is tablet screen overlaysToInclude << qApp->getTabletScreenID(); - rayPickResult = findRayIntersection(ray, true, overlaysToInclude, overlaysToDiscard); + rayPickResult = findRayIntersectionVector(ray, true, overlaysToInclude, overlaysToDiscard); if (rayPickResult.intersects) { return rayPickResult; } // then tablet home button overlaysToInclude.clear(); overlaysToInclude << qApp->getTabletHomeButtonID(); - rayPickResult = findRayIntersection(ray, true, overlaysToInclude, overlaysToDiscard); + rayPickResult = findRayIntersectionVector(ray, true, overlaysToInclude, overlaysToDiscard); if (rayPickResult.intersects) { return rayPickResult; } // then tablet frame overlaysToInclude.clear(); overlaysToInclude << OverlayID(qApp->getTabletFrameID()); - rayPickResult = findRayIntersection(ray, true, overlaysToInclude, overlaysToDiscard); + rayPickResult = findRayIntersectionVector(ray, true, overlaysToInclude, overlaysToDiscard); if (rayPickResult.intersects) { return rayPickResult; } diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 9db6375e84..1e85562485 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -217,10 +217,10 @@ public slots: bool collidableOnly = false); // Same as above but with QVectors - RayToOverlayIntersectionResult findRayIntersection(const PickRay& ray, bool precisionPicking, - const QVector& overlaysToInclude, - const QVector& overlaysToDiscard, - bool visibleOnly = false, bool collidableOnly = false); + RayToOverlayIntersectionResult findRayIntersectionVector(const PickRay& ray, bool precisionPicking, + const QVector& overlaysToInclude, + const QVector& overlaysToDiscard, + bool visibleOnly = false, bool collidableOnly = false); /**jsdoc * Return a list of 3d overlays with bounding boxes that touch the given sphere diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 1eb9ef8462..f3e677fc29 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -682,10 +682,10 @@ RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersection(cons QVector entitiesToInclude = qVectorEntityItemIDFromScriptValue(entityIdsToInclude); QVector entitiesToDiscard = qVectorEntityItemIDFromScriptValue(entityIdsToDiscard); - return findRayIntersection(ray, precisionPicking, entitiesToInclude, entitiesToDiscard, visibleOnly, collidableOnly); + return findRayIntersectionVector(ray, precisionPicking, entitiesToInclude, entitiesToDiscard, visibleOnly, collidableOnly); } -RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersection(const PickRay& ray, bool precisionPicking, +RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionVector(const PickRay& ray, bool precisionPicking, const QVector& entityIdsToInclude, const QVector& entityIdsToDiscard, bool visibleOnly, bool collidableOnly) { PROFILE_RANGE(script_entities, __FUNCTION__); diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index fc5053bdd6..60c12a2f7d 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -230,7 +230,7 @@ public slots: bool visibleOnly = false, bool collidableOnly = false); /// Same as above but with QVectors - Q_INVOKABLE RayToEntityIntersectionResult findRayIntersection(const PickRay& ray, bool precisionPicking, + RayToEntityIntersectionResult findRayIntersectionVector(const PickRay& ray, bool precisionPicking, const QVector& entityIdsToInclude, const QVector& entityIdsToDiscard, bool visibleOnly, bool collidableOnly); From c9f4958925979aea07c2df9e68a1eea2dc02ac4e Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 18 Aug 2017 10:39:40 -0700 Subject: [PATCH 42/42] handControllerGrab fix, maybe, hopefully --- scripts/system/controllers/handControllerGrab.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index 44f79a5570..9318873f64 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -352,7 +352,7 @@ function projectOntoXYPlane(worldPos, position, rotation, dimensions, registrati function projectOntoEntityXYPlane(entityID, worldPos) { var props = entityPropertiesCache.getProps(entityID); - if (props) { + if (props && props.position && props.rotation && props.dimensions && props.registrationPoint) { return projectOntoXYPlane(worldPos, props.position, props.rotation, props.dimensions, props.registrationPoint); } } @@ -368,16 +368,20 @@ function projectOntoOverlayXYPlane(overlayID, worldPos) { var resolution = Overlays.getProperty(overlayID, "resolution"); resolution.z = 1; // Circumvent divide-by-zero. var scale = Overlays.getProperty(overlayID, "dimensions"); - scale.z = 0.01; // overlay dimensions are 2D, not 3D. - dimensions = Vec3.multiplyVbyV(Vec3.multiply(resolution, INCHES_TO_METERS / dpi), scale); + if (scale) { + scale.z = 0.01; // overlay dimensions are 2D, not 3D. + dimensions = Vec3.multiplyVbyV(Vec3.multiply(resolution, INCHES_TO_METERS / dpi), scale); + } } else { dimensions = Overlays.getProperty(overlayID, "dimensions"); - if (dimensions.z) { + if (dimensions && dimensions.z) { dimensions.z = 0.01; // overlay dimensions are 2D, not 3D. } } - return projectOntoXYPlane(worldPos, position, rotation, dimensions, DEFAULT_REGISTRATION_POINT); + if (position && rotation && dimensions) { + return projectOntoXYPlane(worldPos, position, rotation, dimensions, DEFAULT_REGISTRATION_POINT); + } } function handLaserIntersectItem(position, rotation, start) {