diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index b696afa8e5..55ddd01123 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -92,8 +92,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 = qApp->getRayPickManager().getPickRay(_rayPickUID); +void LaserPointer::updateRenderState(const RenderState& renderState, const IntersectionType type, const float distance, const QUuid& objectID, const PickRay& pickRay, const bool defaultState) { if (!renderState.getStartID().isNull()) { QVariantMap startProps; startProps.insert("position", vec3toVariant(pickRay.origin)); @@ -185,12 +184,14 @@ void LaserPointer::disableRenderState(const RenderState& renderState) { void LaserPointer::update() { 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); + if (_renderingEnabled && !_currentRenderState.empty() && _renderStates.find(_currentRenderState) != _renderStates.end() && + (prevRayPickResult.type != IntersectionType::NONE || _laserLength > 0.0f || !_objectLockEnd.first.isNull())) { + float distance = _laserLength > 0.0f ? _laserLength : prevRayPickResult.distance; + updateRenderState(_renderStates[_currentRenderState], prevRayPickResult.type, distance, prevRayPickResult.objectID, prevRayPickResult.searchRay, false); disableRenderState(_defaultRenderStates[_currentRenderState].second); } else if (_renderingEnabled && !_currentRenderState.empty() && _defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) { disableRenderState(_renderStates[_currentRenderState]); - updateRenderState(_defaultRenderStates[_currentRenderState].second, IntersectionType::NONE, _defaultRenderStates[_currentRenderState].first, QUuid(), true); + updateRenderState(_defaultRenderStates[_currentRenderState].second, IntersectionType::NONE, _defaultRenderStates[_currentRenderState].first, QUuid(), prevRayPickResult.searchRay, true); } 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 23f023cf7a..5467a8233e 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -65,6 +65,7 @@ public: void editRenderState(const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps); void setPrecisionPicking(const bool precisionPicking) { DependencyManager::get()->setPrecisionPicking(_rayPickUID, precisionPicking); } + void setLaserLength(const float laserLength) { _laserLength = laserLength; } 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); } @@ -78,6 +79,7 @@ public: private: bool _renderingEnabled; + float _laserLength { 0.0f }; std::string _currentRenderState { "" }; RenderStateMap _renderStates; DefaultRenderStateMap _defaultRenderStates; @@ -89,7 +91,7 @@ private: 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 updateRenderState(const RenderState& renderState, const IntersectionType type, const float distance, const QUuid& objectID, const PickRay& pickRay, const bool defaultState); void disableRenderState(const RenderState& renderState); }; diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp index 1fd0fe9e88..b19ecc14f0 100644 --- a/interface/src/raypick/LaserPointerManager.cpp +++ b/interface/src/raypick/LaserPointerManager.cpp @@ -14,17 +14,19 @@ QUuid LaserPointerManager::createLaserPointer(const QVariant& rayProps, const La 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); + QWriteLocker containsLock(&_containsLock); QUuid id = QUuid::createUuid(); - _laserPointersToAdd.push(std::pair>(id, laserPointer)); + _laserPointers[id] = laserPointer; + _laserPointerLocks[id] = std::make_shared(); return id; } return QUuid(); } void LaserPointerManager::removeLaserPointer(const QUuid uid) { - QWriteLocker lock(&_removeLock); - _laserPointersToRemove.push(uid); + QWriteLocker lock(&_containsLock); + _laserPointers.remove(uid); + _laserPointerLocks.remove(uid); } void LaserPointerManager::enableLaserPointer(const QUuid uid) { @@ -69,32 +71,12 @@ const RayPickResult LaserPointerManager::getPrevRayPickResult(const QUuid uid) { } void LaserPointerManager::update() { + QReadLocker lock(&_containsLock); 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(); } - - QWriteLocker containsLock(&_containsLock); - { - QWriteLocker lock(&_addLock); - while (!_laserPointersToAdd.empty()) { - std::pair> laserPointerToAdd = _laserPointersToAdd.front(); - _laserPointersToAdd.pop(); - _laserPointers[laserPointerToAdd.first] = laserPointerToAdd.second; - _laserPointerLocks[laserPointerToAdd.first] = std::make_shared(); - } - } - - { - QWriteLocker lock(&_removeLock); - while (!_laserPointersToRemove.empty()) { - QUuid uid = _laserPointersToRemove.front(); - _laserPointersToRemove.pop(); - _laserPointers.remove(uid); - _laserPointerLocks.remove(uid); - } - } } void LaserPointerManager::setPrecisionPicking(QUuid uid, const bool precisionPicking) { @@ -105,6 +87,14 @@ void LaserPointerManager::setPrecisionPicking(QUuid uid, const bool precisionPic } } +void LaserPointerManager::setLaserLength(QUuid uid, const float laserLength) { + QReadLocker lock(&_containsLock); + if (_laserPointers.contains(uid)) { + QWriteLocker laserLock(_laserPointerLocks[uid].get()); + _laserPointers[uid]->setLaserLength(laserLength); + } +} + void LaserPointerManager::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) { QReadLocker lock(&_containsLock); if (_laserPointers.contains(uid)) { diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h index b573410fe7..6494bb7056 100644 --- a/interface/src/raypick/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -32,6 +32,7 @@ public: const RayPickResult getPrevRayPickResult(const QUuid uid); void setPrecisionPicking(QUuid uid, const bool precisionPicking); + void setLaserLength(QUuid uid, const float laserLength); void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities); void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities); void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays); @@ -46,10 +47,6 @@ public: private: QHash> _laserPointers; QHash> _laserPointerLocks; - QReadWriteLock _addLock; - std::queue>> _laserPointersToAdd; - QReadWriteLock _removeLock; - std::queue _laserPointersToRemove; QReadWriteLock _containsLock; }; diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h index d65eb335b3..2f6da87b5f 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -31,6 +31,7 @@ public slots: Q_INVOKABLE RayPickResult getPrevRayPickResult(QUuid uid) { return qApp->getLaserPointerManager().getPrevRayPickResult(uid); } Q_INVOKABLE void setPrecisionPicking(QUuid uid, const bool precisionPicking) { qApp->getLaserPointerManager().setPrecisionPicking(uid, precisionPicking); } + Q_INVOKABLE void setLaserLength(QUuid uid, const float laserLength) { qApp->getLaserPointerManager().setLaserLength(uid, laserLength); } 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); } diff --git a/interface/src/raypick/RayPick.h b/interface/src/raypick/RayPick.h index 04045b2116..0686a05718 100644 --- a/interface/src/raypick/RayPick.h +++ b/interface/src/raypick/RayPick.h @@ -70,6 +70,9 @@ public: if (doesPickNonCollidable()) { toReturn |= getBitMask(PICK_INCLUDE_NONCOLLIDABLE); } + if (doesPickCourse()) { + toReturn |= getBitMask(PICK_COURSE); + } return Flags(toReturn); } Flags getOverlayFlags() const { @@ -80,6 +83,9 @@ public: if (doesPickNonCollidable()) { toReturn |= getBitMask(PICK_INCLUDE_NONCOLLIDABLE); } + if (doesPickCourse()) { + toReturn |= getBitMask(PICK_COURSE); + } return Flags(toReturn); } Flags getAvatarFlags() const { return Flags(getBitMask(PICK_AVATARS)); } diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp index 1ec8efc331..bfc6e3fcb2 100644 --- a/interface/src/raypick/RayPickManager.cpp +++ b/interface/src/raypick/RayPickManager.cpp @@ -38,11 +38,12 @@ void RayPickManager::cacheResult(const bool intersects, const RayPickResult& res res = resTemp; } } else { - cache[ray][mask] = RayPickResult(); + cache[ray][mask] = RayPickResult(res.searchRay); } } void RayPickManager::update() { + QReadLocker lock(&_containsLock); RayPickCache results; for (auto& uid : _rayPicks.keys()) { std::shared_ptr rayPick = _rayPicks[uid]; @@ -58,7 +59,7 @@ void RayPickManager::update() { } QPair rayKey = QPair(ray.origin, ray.direction); - RayPickResult res; + RayPickResult res = RayPickResult(ray); if (rayPick->getFilter().doesPickEntities()) { RayToEntityIntersectionResult entityRes; @@ -73,7 +74,7 @@ void RayPickManager::update() { } if (!fromCache) { - cacheResult(entityRes.intersects, RayPickResult(IntersectionType::ENTITY, entityRes.entityID, entityRes.distance, entityRes.intersection, entityRes.surfaceNormal), + cacheResult(entityRes.intersects, RayPickResult(IntersectionType::ENTITY, entityRes.entityID, entityRes.distance, entityRes.intersection, ray, entityRes.surfaceNormal), entityMask, res, rayKey, results); } } @@ -91,7 +92,7 @@ void RayPickManager::update() { } if (!fromCache) { - cacheResult(overlayRes.intersects, RayPickResult(IntersectionType::OVERLAY, overlayRes.overlayID, overlayRes.distance, overlayRes.intersection, overlayRes.surfaceNormal), + cacheResult(overlayRes.intersects, RayPickResult(IntersectionType::OVERLAY, overlayRes.overlayID, overlayRes.distance, overlayRes.intersection, ray, overlayRes.surfaceNormal), overlayMask, res, rayKey, results); } } @@ -100,7 +101,7 @@ void RayPickManager::update() { RayPickFilter::Flags avatarMask = rayPick->getFilter().getAvatarFlags(); if (!checkAndCompareCachedResults(rayKey, results, res, avatarMask)) { 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); + cacheResult(avatarRes.intersects, RayPickResult(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection, ray), avatarMask, res, rayKey, results); } } @@ -109,7 +110,7 @@ void RayPickManager::update() { 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), hudMask, res, rayKey, results); + cacheResult(true, RayPickResult(IntersectionType::HUD, 0, glm::distance(ray.origin, hudRes), hudRes, ray), hudMask, res, rayKey, results); } } @@ -117,56 +118,39 @@ void RayPickManager::update() { 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.empty()) { - std::pair> rayPickToAdd = _rayPicksToAdd.front(); - _rayPicksToAdd.pop(); - _rayPicks[rayPickToAdd.first] = rayPickToAdd.second; - _rayPickLocks[rayPickToAdd.first] = std::make_shared(); - } - } - - { - QWriteLocker lock(&_removeLock); - while (!_rayPicksToRemove.empty()) { - QUuid uid = _rayPicksToRemove.front(); - _rayPicksToRemove.pop(); - _rayPicks.remove(uid); - _rayPickLocks.remove(uid); + rayPick->setRayPickResult(RayPickResult(ray)); } } } 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); + QWriteLocker lock(&_containsLock); QUuid id = QUuid::createUuid(); - _rayPicksToAdd.push(std::pair>(id, std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled))); + _rayPicks[id] = std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled); + _rayPickLocks[id] = std::make_shared(); return id; } QUuid RayPickManager::createRayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled) { - QWriteLocker lock(&_addLock); + QWriteLocker lock(&_containsLock); QUuid id = QUuid::createUuid(); - _rayPicksToAdd.push(std::pair>(id, std::make_shared(filter, maxDistance, enabled))); + _rayPicks[id] = std::make_shared(filter, maxDistance, enabled); + _rayPickLocks[id] = std::make_shared(); return id; } QUuid RayPickManager::createRayPick(const glm::vec3& position, const glm::vec3& direction, const RayPickFilter& filter, const float maxDistance, const bool enabled) { - QWriteLocker lock(&_addLock); + QWriteLocker lock(&_containsLock); QUuid id = QUuid::createUuid(); - _rayPicksToAdd.push(std::pair>(id, std::make_shared(position, direction, filter, maxDistance, enabled))); + _rayPicks[id] = std::make_shared(position, direction, filter, maxDistance, enabled); + _rayPickLocks[id] = std::make_shared(); return id; } void RayPickManager::removeRayPick(const QUuid uid) { - QWriteLocker lock(&_removeLock); - _rayPicksToRemove.push(uid); + QWriteLocker lock(&_containsLock); + _rayPicks.remove(uid); + _rayPickLocks.remove(uid); } void RayPickManager::enableRayPick(const QUuid uid) { @@ -185,18 +169,6 @@ void RayPickManager::disableRayPick(const QUuid uid) { } } -const PickRay RayPickManager::getPickRay(const QUuid uid) { - QReadLocker containsLock(&_containsLock); - if (_rayPicks.contains(uid)) { - bool valid; - PickRay pickRay = _rayPicks[uid]->getPickRay(valid); - if (valid) { - return pickRay; - } - } - return PickRay(); -} - const RayPickResult RayPickManager::getPrevRayPickResult(const QUuid uid) { QReadLocker containsLock(&_containsLock); if (_rayPicks.contains(uid)) { diff --git a/interface/src/raypick/RayPickManager.h b/interface/src/raypick/RayPickManager.h index f2b1ff4ae4..9717767f19 100644 --- a/interface/src/raypick/RayPickManager.h +++ b/interface/src/raypick/RayPickManager.h @@ -28,7 +28,6 @@ class RayPickManager { public: void update(); - const PickRay getPickRay(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); @@ -49,10 +48,6 @@ public: private: QHash> _rayPicks; QHash> _rayPickLocks; - QReadWriteLock _addLock; - std::queue>> _rayPicksToAdd; - QReadWriteLock _removeLock; - std::queue _rayPicksToRemove; QReadWriteLock _containsLock; typedef QHash, std::unordered_map> RayPickCache; diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index 8257c883a2..7d0df3ac78 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -762,6 +762,8 @@ QScriptValue rayPickResultToScriptValue(QScriptEngine* engine, const RayPickResu QScriptValue intersection = vec3toScriptValue(engine, rayPickResult.intersection); obj.setProperty("intersection", intersection); obj.setProperty("intersects", rayPickResult.type != NONE); + QScriptValue searchRay = pickRayToScriptValue(engine, rayPickResult.searchRay); + obj.setProperty("searchRay", searchRay); QScriptValue surfaceNormal = vec3toScriptValue(engine, rayPickResult.surfaceNormal); obj.setProperty("surfaceNormal", surfaceNormal); return obj; diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index ed928a6e7b..7b7d8d8f47 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -137,7 +137,7 @@ QScriptValue pickRayToScriptValue(QScriptEngine* engine, const PickRay& pickRay) void pickRayFromScriptValue(const QScriptValue& object, PickRay& pickRay); enum IntersectionType { - NONE, + NONE = 0, ENTITY, OVERLAY, AVATAR, @@ -147,12 +147,14 @@ enum IntersectionType { class RayPickResult { public: RayPickResult() {} - 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) {} + RayPickResult(const PickRay& searchRay) : searchRay(searchRay) {} + RayPickResult(const IntersectionType type, const QUuid& objectID, const float distance, const glm::vec3& intersection, const PickRay& searchRay, const glm::vec3& surfaceNormal = glm::vec3(NAN)) : + type(type), objectID(objectID), distance(distance), intersection(intersection), searchRay(searchRay), surfaceNormal(surfaceNormal) {} IntersectionType type { NONE }; - QUuid objectID { 0 }; + QUuid objectID; float distance { FLT_MAX }; glm::vec3 intersection { NAN }; + PickRay searchRay; glm::vec3 surfaceNormal { NAN }; }; Q_DECLARE_METATYPE(RayPickResult)