Merge pull request #11226 from SamGondelman/miceWithLasers

EntityTreeRender uses RayPick API with precision picking
This commit is contained in:
Brad Hefta-Gaub 2017-08-24 08:10:21 -07:00 committed by GitHub
commit 5c832eae9c
13 changed files with 87 additions and 62 deletions

View file

@ -1735,6 +1735,27 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
connect(&_myCamera, &Camera::modeUpdated, this, &Application::cameraModeChanged); connect(&_myCamera, &Camera::modeUpdated, this, &Application::cameraModeChanged);
// Setup the mouse ray pick and related operators
DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickID(_rayPickManager.createRayPick(
RayPickFilter(DependencyManager::get<RayPickScriptingInterface>()->PICK_ENTITIES() | DependencyManager::get<RayPickScriptingInterface>()->PICK_INCLUDE_NONCOLLIDABLE()),
0.0f, true));
DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickResultOperator([&](QUuid rayPickID) {
RayToEntityIntersectionResult entityResult;
RayPickResult result = _rayPickManager.getPrevRayPickResult(rayPickID);
entityResult.intersects = result.type != DependencyManager::get<RayPickScriptingInterface>()->INTERSECTED_NONE();
if (entityResult.intersects) {
entityResult.intersection = result.intersection;
entityResult.distance = result.distance;
entityResult.surfaceNormal = result.surfaceNormal;
entityResult.entityID = result.objectID;
entityResult.entity = DependencyManager::get<EntityTreeRenderer>()->getTree()->findEntityByID(entityResult.entityID);
}
return entityResult;
});
DependencyManager::get<EntityTreeRenderer>()->setSetPrecisionPickingOperator([&](QUuid rayPickID, bool value) {
_rayPickManager.setPrecisionPicking(rayPickID, value);
});
qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID()); qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID());
} }

View file

@ -64,6 +64,7 @@ public:
// 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. // 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 editRenderState(const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps);
void setPrecisionPicking(const bool precisionPicking) { DependencyManager::get<RayPickScriptingInterface>()->setPrecisionPicking(_rayPickUID, precisionPicking); }
void setIgnoreEntities(const QScriptValue& ignoreEntities) { DependencyManager::get<RayPickScriptingInterface>()->setIgnoreEntities(_rayPickUID, ignoreEntities); } void setIgnoreEntities(const QScriptValue& ignoreEntities) { DependencyManager::get<RayPickScriptingInterface>()->setIgnoreEntities(_rayPickUID, ignoreEntities); }
void setIncludeEntities(const QScriptValue& includeEntities) { DependencyManager::get<RayPickScriptingInterface>()->setIncludeEntities(_rayPickUID, includeEntities); } void setIncludeEntities(const QScriptValue& includeEntities) { DependencyManager::get<RayPickScriptingInterface>()->setIncludeEntities(_rayPickUID, includeEntities); }
void setIgnoreOverlays(const QScriptValue& ignoreOverlays) { DependencyManager::get<RayPickScriptingInterface>()->setIgnoreOverlays(_rayPickUID, ignoreOverlays); } void setIgnoreOverlays(const QScriptValue& ignoreOverlays) { DependencyManager::get<RayPickScriptingInterface>()->setIgnoreOverlays(_rayPickUID, ignoreOverlays); }

View file

@ -97,6 +97,14 @@ void LaserPointerManager::update() {
} }
} }
void LaserPointerManager::setPrecisionPicking(QUuid uid, const bool precisionPicking) {
QReadLocker lock(&_containsLock);
if (_laserPointers.contains(uid)) {
QWriteLocker laserLock(_laserPointerLocks[uid].get());
_laserPointers[uid]->setPrecisionPicking(precisionPicking);
}
}
void LaserPointerManager::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) { void LaserPointerManager::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) {
QReadLocker lock(&_containsLock); QReadLocker lock(&_containsLock);
if (_laserPointers.contains(uid)) { if (_laserPointers.contains(uid)) {

View file

@ -31,6 +31,7 @@ public:
void editRenderState(QUuid uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps); void editRenderState(QUuid uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps);
const RayPickResult getPrevRayPickResult(const QUuid uid); const RayPickResult getPrevRayPickResult(const QUuid uid);
void setPrecisionPicking(QUuid uid, const bool precisionPicking);
void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities); void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities);
void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities); void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities);
void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays); void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays);

View file

@ -30,6 +30,7 @@ public slots:
Q_INVOKABLE void setRenderState(QUuid uid, const QString& renderState) { qApp->getLaserPointerManager().setRenderState(uid, renderState.toStdString()); } 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 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 setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) { qApp->getLaserPointerManager().setIgnoreEntities(uid, ignoreEntities); } 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 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 setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) { qApp->getLaserPointerManager().setIgnoreOverlays(uid, ignoreOverlays); }

View file

@ -41,12 +41,14 @@ public:
// The key is the Flags // The key is the Flags
Flags _flags; Flags _flags;
RayPickFilter() : _flags(PICK_NOTHING) {} RayPickFilter() : _flags(getBitMask(PICK_NOTHING)) {}
RayPickFilter(const Flags& flags) : _flags(flags) {} 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 operator!= (const RayPickFilter& rhs) const { return _flags != rhs._flags; } bool operator!= (const RayPickFilter& rhs) const { return _flags != rhs._flags; }
void setFlag(FlagBit flag, bool value) { _flags[flag] = value; }
bool doesPickNothing() const { return _flags[PICK_NOTHING]; } bool doesPickNothing() const { return _flags[PICK_NOTHING]; }
bool doesPickEntities() const { return _flags[PICK_ENTITIES]; } bool doesPickEntities() const { return _flags[PICK_ENTITIES]; }
bool doesPickOverlays() const { return _flags[PICK_OVERLAYS]; } bool doesPickOverlays() const { return _flags[PICK_OVERLAYS]; }
@ -61,27 +63,27 @@ public:
// Helpers for RayPickManager // Helpers for RayPickManager
Flags getEntityFlags() const { Flags getEntityFlags() const {
Flags toReturn(PICK_ENTITIES); unsigned int toReturn = getBitMask(PICK_ENTITIES);
if (doesPickInvisible()) { if (doesPickInvisible()) {
toReturn |= Flags(PICK_INCLUDE_INVISIBLE); toReturn |= getBitMask(PICK_INCLUDE_INVISIBLE);
} }
if (doesPickNonCollidable()) { if (doesPickNonCollidable()) {
toReturn |= Flags(PICK_INCLUDE_NONCOLLIDABLE); toReturn |= getBitMask(PICK_INCLUDE_NONCOLLIDABLE);
} }
return toReturn; return Flags(toReturn);
} }
Flags getOverlayFlags() const { Flags getOverlayFlags() const {
Flags toReturn(PICK_OVERLAYS); unsigned int toReturn = getBitMask(PICK_OVERLAYS);
if (doesPickInvisible()) { if (doesPickInvisible()) {
toReturn |= Flags(PICK_INCLUDE_INVISIBLE); toReturn |= getBitMask(PICK_INCLUDE_INVISIBLE);
} }
if (doesPickNonCollidable()) { if (doesPickNonCollidable()) {
toReturn |= Flags(PICK_INCLUDE_NONCOLLIDABLE); toReturn |= getBitMask(PICK_INCLUDE_NONCOLLIDABLE);
} }
return toReturn; return Flags(toReturn);
} }
Flags getAvatarFlags() const { return Flags(PICK_AVATARS); } Flags getAvatarFlags() const { return Flags(getBitMask(PICK_AVATARS)); }
Flags getHUDFlags() const { return Flags(PICK_HUD); } Flags getHUDFlags() const { return Flags(getBitMask(PICK_HUD)); }
static unsigned int getBitMask(FlagBit bit) { return 1 << bit; } static unsigned int getBitMask(FlagBit bit) { return 1 << bit; }
@ -98,10 +100,12 @@ public:
void disable() { _enabled = false; } void disable() { _enabled = false; }
const RayPickFilter& getFilter() { return _filter; } const RayPickFilter& getFilter() { return _filter; }
const float& getMaxDistance() { return _maxDistance; } float getMaxDistance() { return _maxDistance; }
const bool& isEnabled() { return _enabled; } bool isEnabled() { return _enabled; }
const RayPickResult& getPrevRayPickResult() { return _prevResult; } const RayPickResult& getPrevRayPickResult() { return _prevResult; }
void setPrecisionPicking(bool precisionPicking) { _filter.setFlag(RayPickFilter::PICK_COURSE, !precisionPicking); }
void setRayPickResult(const RayPickResult& rayPickResult) { _prevResult = rayPickResult; } void setRayPickResult(const RayPickResult& rayPickResult) { _prevResult = rayPickResult; }
const QVector<EntityItemID>& getIgnoreEntites() { return _ignoreEntities; } const QVector<EntityItemID>& getIgnoreEntites() { return _ignoreEntities; }

View file

@ -64,10 +64,11 @@ void RayPickManager::update() {
RayToEntityIntersectionResult entityRes; RayToEntityIntersectionResult entityRes;
bool fromCache = true; bool fromCache = true;
bool invisible = rayPick->getFilter().doesPickInvisible(); bool invisible = rayPick->getFilter().doesPickInvisible();
bool noncollidable = rayPick->getFilter().doesPickNonCollidable(); bool nonCollidable = rayPick->getFilter().doesPickNonCollidable();
RayPickFilter::Flags entityMask = rayPick->getFilter().getEntityFlags(); RayPickFilter::Flags entityMask = rayPick->getFilter().getEntityFlags();
if (!checkAndCompareCachedResults(rayKey, results, res, entityMask)) { if (!checkAndCompareCachedResults(rayKey, results, res, entityMask)) {
entityRes = DependencyManager::get<EntityScriptingInterface>()->findRayIntersectionVector(ray, true, rayPick->getIncludeEntites(), rayPick->getIgnoreEntites(), !invisible, !noncollidable); entityRes = DependencyManager::get<EntityScriptingInterface>()->findRayIntersectionVector(ray, !rayPick->getFilter().doesPickCourse(),
rayPick->getIncludeEntites(), rayPick->getIgnoreEntites(), !invisible, !nonCollidable);
fromCache = false; fromCache = false;
} }
@ -81,10 +82,11 @@ void RayPickManager::update() {
RayToOverlayIntersectionResult overlayRes; RayToOverlayIntersectionResult overlayRes;
bool fromCache = true; bool fromCache = true;
bool invisible = rayPick->getFilter().doesPickInvisible(); bool invisible = rayPick->getFilter().doesPickInvisible();
bool noncollidable = rayPick->getFilter().doesPickNonCollidable(); bool nonCollidable = rayPick->getFilter().doesPickNonCollidable();
RayPickFilter::Flags overlayMask = rayPick->getFilter().getOverlayFlags(); RayPickFilter::Flags overlayMask = rayPick->getFilter().getOverlayFlags();
if (!checkAndCompareCachedResults(rayKey, results, res, overlayMask)) { if (!checkAndCompareCachedResults(rayKey, results, res, overlayMask)) {
overlayRes = qApp->getOverlays().findRayIntersectionVector(ray, true, rayPick->getIncludeOverlays(), rayPick->getIgnoreOverlays(), !invisible, !noncollidable); overlayRes = qApp->getOverlays().findRayIntersectionVector(ray, !rayPick->getFilter().doesPickCourse(),
rayPick->getIncludeOverlays(), rayPick->getIgnoreOverlays(), !invisible, !nonCollidable);
fromCache = false; fromCache = false;
} }
@ -204,6 +206,14 @@ const RayPickResult RayPickManager::getPrevRayPickResult(const QUuid uid) {
return RayPickResult(); return RayPickResult();
} }
void RayPickManager::setPrecisionPicking(QUuid uid, const bool precisionPicking) {
QReadLocker containsLock(&_containsLock);
if (_rayPicks.contains(uid)) {
QWriteLocker lock(_rayPickLocks[uid].get());
_rayPicks[uid]->setPrecisionPicking(precisionPicking);
}
}
void RayPickManager::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) { void RayPickManager::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) {
QReadLocker containsLock(&_containsLock); QReadLocker containsLock(&_containsLock);
if (_rayPicks.contains(uid)) { if (_rayPicks.contains(uid)) {

View file

@ -38,6 +38,7 @@ public:
void disableRayPick(const QUuid uid); void disableRayPick(const QUuid uid);
const RayPickResult getPrevRayPickResult(const QUuid uid); const RayPickResult getPrevRayPickResult(const QUuid uid);
void setPrecisionPicking(QUuid uid, const bool precisionPicking);
void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities); void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities);
void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities); void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities);
void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays); void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays);

View file

@ -82,6 +82,10 @@ RayPickResult RayPickScriptingInterface::getPrevRayPickResult(QUuid uid) {
return qApp->getRayPickManager().getPrevRayPickResult(uid); return qApp->getRayPickManager().getPrevRayPickResult(uid);
} }
void RayPickScriptingInterface::setPrecisionPicking(QUuid uid, const bool precisionPicking) {
qApp->getRayPickManager().setPrecisionPicking(uid, precisionPicking);
}
void RayPickScriptingInterface::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) { void RayPickScriptingInterface::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) {
qApp->getRayPickManager().setIgnoreEntities(uid, ignoreEntities); qApp->getRayPickManager().setIgnoreEntities(uid, ignoreEntities);
} }

View file

@ -43,6 +43,7 @@ public slots:
Q_INVOKABLE void removeRayPick(QUuid uid); Q_INVOKABLE void removeRayPick(QUuid uid);
Q_INVOKABLE RayPickResult getPrevRayPickResult(QUuid uid); Q_INVOKABLE RayPickResult getPrevRayPickResult(QUuid uid);
Q_INVOKABLE void setPrecisionPicking(QUuid uid, const bool precisionPicking);
Q_INVOKABLE void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities); Q_INVOKABLE void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities);
Q_INVOKABLE void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities); Q_INVOKABLE void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities);
Q_INVOKABLE void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays); Q_INVOKABLE void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays);
@ -50,7 +51,6 @@ public slots:
Q_INVOKABLE void setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars); Q_INVOKABLE void setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars);
Q_INVOKABLE void setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars); Q_INVOKABLE void setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars);
private:
unsigned int PICK_NOTHING() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_NOTHING); } 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_ENTITIES() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_ENTITIES); }
unsigned int PICK_OVERLAYS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_OVERLAYS); } unsigned int PICK_OVERLAYS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_OVERLAYS); }

View file

@ -53,7 +53,6 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
_viewState(viewState), _viewState(viewState),
_scriptingServices(scriptingServices), _scriptingServices(scriptingServices),
_displayModelBounds(false), _displayModelBounds(false),
_dontDoPrecisionPicking(false),
_layeredZones(this) _layeredZones(this)
{ {
REGISTER_ENTITY_TYPE_WITH_FACTORY(Model, RenderableModelEntityItem::factory) REGISTER_ENTITY_TYPE_WITH_FACTORY(Model, RenderableModelEntityItem::factory)
@ -428,28 +427,6 @@ void EntityTreeRenderer::deleteReleasedModels() {
} }
} }
RayToEntityIntersectionResult EntityTreeRenderer::findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType,
bool precisionPicking, const QVector<EntityItemID>& entityIdsToInclude,
const QVector<EntityItemID>& entityIdsToDiscard, bool visibleOnly, bool collidableOnly) {
RayToEntityIntersectionResult result;
if (_tree) {
EntityTreePointer entityTree = std::static_pointer_cast<EntityTree>(_tree);
OctreeElementPointer element;
EntityItemPointer intersectedEntity = NULL;
result.intersects = entityTree->findRayIntersection(ray.origin, ray.direction,
entityIdsToInclude, entityIdsToDiscard, visibleOnly, collidableOnly, precisionPicking,
element, result.distance, result.face, result.surfaceNormal,
(void**)&intersectedEntity, lockType, &result.accurate);
if (result.intersects && intersectedEntity) {
result.entityID = intersectedEntity->getEntityItemID();
result.intersection = ray.origin + (ray.direction * result.distance);
result.entity = intersectedEntity;
}
}
return result;
}
void EntityTreeRenderer::connectSignalsToSlots(EntityScriptingInterface* entityScriptingInterface) { void EntityTreeRenderer::connectSignalsToSlots(EntityScriptingInterface* entityScriptingInterface) {
connect(this, &EntityTreeRenderer::mousePressOnEntity, entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity); connect(this, &EntityTreeRenderer::mousePressOnEntity, entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity);
@ -530,11 +507,10 @@ void EntityTreeRenderer::mousePressEvent(QMouseEvent* event) {
if (!_tree || _shuttingDown) { if (!_tree || _shuttingDown) {
return; return;
} }
PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent"); PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent");
PickRay ray = _viewState->computePickRay(event->x(), event->y()); PickRay ray = _viewState->computePickRay(event->x(), event->y());
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
bool precisionPicking = !_dontDoPrecisionPicking;
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking);
if (rayPickResult.intersects) { if (rayPickResult.intersects) {
//qCDebug(entitiesrenderer) << "mousePressEvent over entity:" << rayPickResult.entityID; //qCDebug(entitiesrenderer) << "mousePressEvent over entity:" << rayPickResult.entityID;
@ -579,11 +555,10 @@ void EntityTreeRenderer::mouseDoublePressEvent(QMouseEvent* event) {
if (!_tree || _shuttingDown) { if (!_tree || _shuttingDown) {
return; return;
} }
PerformanceTimer perfTimer("EntityTreeRenderer::mouseDoublePressEvent"); PerformanceTimer perfTimer("EntityTreeRenderer::mouseDoublePressEvent");
PickRay ray = _viewState->computePickRay(event->x(), event->y()); PickRay ray = _viewState->computePickRay(event->x(), event->y());
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
bool precisionPicking = !_dontDoPrecisionPicking;
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking);
if (rayPickResult.intersects) { if (rayPickResult.intersects) {
//qCDebug(entitiesrenderer) << "mouseDoublePressEvent over entity:" << rayPickResult.entityID; //qCDebug(entitiesrenderer) << "mouseDoublePressEvent over entity:" << rayPickResult.entityID;
@ -622,8 +597,7 @@ void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event) {
PerformanceTimer perfTimer("EntityTreeRenderer::mouseReleaseEvent"); PerformanceTimer perfTimer("EntityTreeRenderer::mouseReleaseEvent");
PickRay ray = _viewState->computePickRay(event->x(), event->y()); PickRay ray = _viewState->computePickRay(event->x(), event->y());
bool precisionPicking = !_dontDoPrecisionPicking; RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking);
if (rayPickResult.intersects) { if (rayPickResult.intersects) {
//qCDebug(entitiesrenderer) << "mouseReleaseEvent over entity:" << rayPickResult.entityID; //qCDebug(entitiesrenderer) << "mouseReleaseEvent over entity:" << rayPickResult.entityID;
@ -671,14 +645,11 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) {
if (!_tree || _shuttingDown) { if (!_tree || _shuttingDown) {
return; return;
} }
PerformanceTimer perfTimer("EntityTreeRenderer::mouseMoveEvent"); PerformanceTimer perfTimer("EntityTreeRenderer::mouseMoveEvent");
PickRay ray = _viewState->computePickRay(event->x(), event->y()); PickRay ray = _viewState->computePickRay(event->x(), event->y());
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
bool precisionPicking = false; // for mouse moves we do not do precision picking
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::TryLock, precisionPicking);
if (rayPickResult.intersects) { if (rayPickResult.intersects) {
glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult); glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult);
PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID, PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID,
pos2D, rayPickResult.intersection, pos2D, rayPickResult.intersection,

View file

@ -59,6 +59,10 @@ public:
float getEntityLoadingPriority(const EntityItem& item) const { return _calculateEntityLoadingPriorityFunc(item); } float getEntityLoadingPriority(const EntityItem& item) const { return _calculateEntityLoadingPriorityFunc(item); }
void setEntityLoadingPriorityFunction(CalculateEntityLoadingPriority fn) { this->_calculateEntityLoadingPriorityFunc = fn; } void setEntityLoadingPriorityFunction(CalculateEntityLoadingPriority fn) { this->_calculateEntityLoadingPriorityFunc = fn; }
void setMouseRayPickID(QUuid rayPickID) { _mouseRayPickID = rayPickID; }
void setMouseRayPickResultOperator(std::function<RayToEntityIntersectionResult(QUuid)> getPrevRayPickResultOperator) { _getPrevRayPickResultOperator = getPrevRayPickResultOperator; }
void setSetPrecisionPickingOperator(std::function<void(QUuid, bool)> setPrecisionPickingOperator) { _setPrecisionPickingOperator = setPrecisionPickingOperator; }
void shutdown(); void shutdown();
void update(); void update();
@ -130,7 +134,7 @@ public slots:
// optional slots that can be wired to menu items // optional slots that can be wired to menu items
void setDisplayModelBounds(bool value) { _displayModelBounds = value; } void setDisplayModelBounds(bool value) { _displayModelBounds = value; }
void setDontDoPrecisionPicking(bool value) { _dontDoPrecisionPicking = value; } void setPrecisionPicking(bool value) { _setPrecisionPickingOperator(_mouseRayPickID, value); }
protected: protected:
virtual OctreePointer createTree() override { virtual OctreePointer createTree() override {
@ -150,10 +154,6 @@ private:
void checkAndCallPreload(const EntityItemID& entityID, bool reload = false, bool unloadFirst = false); void checkAndCallPreload(const EntityItemID& entityID, bool reload = false, bool unloadFirst = false);
QList<ModelPointer> _releasedModels; QList<ModelPointer> _releasedModels;
RayToEntityIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType,
bool precisionPicking, const QVector<EntityItemID>& entityIdsToInclude = QVector<EntityItemID>(),
const QVector<EntityItemID>& entityIdsToDiscard = QVector<EntityItemID>(), bool visibleOnly=false,
bool collidableOnly = false);
EntityItemID _currentHoverOverEntityID; EntityItemID _currentHoverOverEntityID;
EntityItemID _currentClickingOnEntityID; EntityItemID _currentClickingOnEntityID;
@ -176,12 +176,15 @@ private:
AbstractViewStateInterface* _viewState; AbstractViewStateInterface* _viewState;
AbstractScriptingServicesInterface* _scriptingServices; AbstractScriptingServicesInterface* _scriptingServices;
bool _displayModelBounds; bool _displayModelBounds;
bool _dontDoPrecisionPicking;
bool _shuttingDown { false }; bool _shuttingDown { false };
QMultiMap<QUrl, EntityItemID> _waitingOnPreload; QMultiMap<QUrl, EntityItemID> _waitingOnPreload;
QUuid _mouseRayPickID;
std::function<RayToEntityIntersectionResult(QUuid)> _getPrevRayPickResultOperator;
std::function<void(QUuid, bool)> _setPrecisionPickingOperator;
class LayeredZone { class LayeredZone {
public: public:
LayeredZone(std::shared_ptr<ZoneEntityItem> zone, QUuid id, float volume) : zone(zone), id(id), volume(volume) {} LayeredZone(std::shared_ptr<ZoneEntityItem> zone, QUuid id, float volume) : zone(zone), id(id), volume(volume) {}

View file

@ -1182,7 +1182,7 @@ function MyController(hand) {
this.fullEnd = fullEnd; this.fullEnd = fullEnd;
this.laserPointer = LaserPointers.createLaserPointer({ this.laserPointer = LaserPointers.createLaserPointer({
joint: (hand == RIGHT_HAND) ? "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", joint: (hand == RIGHT_HAND) ? "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND",
filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS | RayPick.PICK_INCLUDE_NONCOLLIDABLE,
maxDistance: PICK_MAX_DISTANCE, maxDistance: PICK_MAX_DISTANCE,
posOffset: getGrabPointSphereOffset(this.handToController()), posOffset: getGrabPointSphereOffset(this.handToController()),
renderStates: renderStates, renderStates: renderStates,
@ -1191,7 +1191,7 @@ function MyController(hand) {
}); });
this.headLaserPointer = LaserPointers.createLaserPointer({ this.headLaserPointer = LaserPointers.createLaserPointer({
joint: "Avatar", joint: "Avatar",
filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS | RayPick.PICK_INCLUDE_NONCOLLIDABLE,
maxDistance: PICK_MAX_DISTANCE, maxDistance: PICK_MAX_DISTANCE,
renderStates: headRenderStates, renderStates: headRenderStates,
faceAvatar: true, faceAvatar: true,