mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-25 16:55:07 +02:00
non-templated pickresult wip
This commit is contained in:
parent
640ad514bc
commit
3572f7f5db
17 changed files with 217 additions and 206 deletions
|
@ -1823,14 +1823,17 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
0.0f, true));
|
||||
DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickResultOperator([&](QUuid rayPickID) {
|
||||
RayToEntityIntersectionResult entityResult;
|
||||
RayPickResult result = _rayPickManager.getPrevPickResult(rayPickID);
|
||||
entityResult.intersects = result.type != 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);
|
||||
entityResult.intersects = false;
|
||||
QVariantMap result = _rayPickManager.getPrevPickResult(rayPickID);
|
||||
if (result["type"].isValid()) {
|
||||
entityResult.intersects = result["type"] != RayPickScriptingInterface::INTERSECTED_NONE();
|
||||
if (entityResult.intersects) {
|
||||
entityResult.intersection = vec3FromVariant(result["intersection"]);
|
||||
entityResult.distance = result["distance"].toFloat();
|
||||
entityResult.surfaceNormal = vec3FromVariant(result["surfaceNormal"]);
|
||||
entityResult.entityID = result["objectID"].toUuid();
|
||||
entityResult.entity = DependencyManager::get<EntityTreeRenderer>()->getTree()->findEntityByID(entityResult.entityID);
|
||||
}
|
||||
}
|
||||
return entityResult;
|
||||
});
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
#include "Application.h"
|
||||
#include "avatar/AvatarManager.h"
|
||||
#include "RayPickScriptingInterface.h"
|
||||
|
||||
LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates,
|
||||
const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) :
|
||||
|
@ -101,7 +100,7 @@ void LaserPointer::updateRenderStateOverlay(const OverlayID& id, const QVariant&
|
|||
}
|
||||
}
|
||||
|
||||
const RayPickResult LaserPointer::getPrevRayPickResult() {
|
||||
const QVariantMap LaserPointer::getPrevRayPickResult() {
|
||||
return qApp->getRayPickManager().getPrevPickResult(_rayPickUID);
|
||||
}
|
||||
|
||||
|
@ -198,15 +197,18 @@ void LaserPointer::disableRenderState(const RenderState& renderState) {
|
|||
void LaserPointer::update() {
|
||||
// This only needs to be a read lock because update won't change any of the properties that can be modified from scripts
|
||||
withReadLock([&] {
|
||||
RayPickResult prevRayPickResult = qApp->getRayPickManager().getPrevPickResult(_rayPickUID);
|
||||
QVariantMap prevRayPickResult = qApp->getRayPickManager().getPrevPickResult(_rayPickUID);
|
||||
IntersectionType type = IntersectionType(prevRayPickResult["type"].toInt());
|
||||
PickRay pickRay = PickRay(prevRayPickResult["searchRay"].toMap());
|
||||
QUuid uid = prevRayPickResult["objectID"].toUuid();
|
||||
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);
|
||||
(type != IntersectionType::NONE || _laserLength > 0.0f || !_objectLockEnd.first.isNull())) {
|
||||
float distance = _laserLength > 0.0f ? _laserLength : prevRayPickResult["distance"].toFloat();
|
||||
updateRenderState(_renderStates[_currentRenderState], type, distance, uid, pickRay, 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(), prevRayPickResult.searchRay, true);
|
||||
updateRenderState(_defaultRenderStates[_currentRenderState].second, IntersectionType::NONE, _defaultRenderStates[_currentRenderState].first, QUuid(), pickRay, true);
|
||||
} else if (!_currentRenderState.empty()) {
|
||||
disableRenderState(_renderStates[_currentRenderState]);
|
||||
disableRenderState(_defaultRenderStates[_currentRenderState].second);
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include "ui/overlays/Overlay.h"
|
||||
|
||||
class RayPickResult;
|
||||
#include "RayPickScriptingInterface.h"
|
||||
|
||||
class RenderState {
|
||||
|
||||
|
@ -61,7 +61,7 @@ public:
|
|||
QUuid getRayUID() { return _rayPickUID; }
|
||||
void enable();
|
||||
void disable();
|
||||
const RayPickResult getPrevRayPickResult();
|
||||
const QVariantMap getPrevRayPickResult();
|
||||
|
||||
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.
|
||||
|
|
|
@ -67,12 +67,12 @@ void LaserPointerManager::editRenderState(const QUuid& uid, const std::string& s
|
|||
}
|
||||
}
|
||||
|
||||
const RayPickResult LaserPointerManager::getPrevRayPickResult(const QUuid& uid) const {
|
||||
const QVariantMap LaserPointerManager::getPrevRayPickResult(const QUuid& uid) const {
|
||||
auto laserPointer = find(uid);
|
||||
if (laserPointer) {
|
||||
return laserPointer->getPrevRayPickResult();
|
||||
}
|
||||
return RayPickResult();
|
||||
return QVariantMap();
|
||||
}
|
||||
|
||||
void LaserPointerManager::update() {
|
||||
|
|
|
@ -18,9 +18,6 @@
|
|||
|
||||
#include "LaserPointer.h"
|
||||
|
||||
class RayPickResult;
|
||||
|
||||
|
||||
class LaserPointerManager : protected ReadWriteLockable {
|
||||
|
||||
public:
|
||||
|
@ -31,7 +28,7 @@ public:
|
|||
void disableLaserPointer(const QUuid& uid) const;
|
||||
void setRenderState(const QUuid& uid, const std::string& renderState) const;
|
||||
void editRenderState(const QUuid& uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) const;
|
||||
const RayPickResult getPrevRayPickResult(const QUuid& uid) const;
|
||||
const QVariantMap getPrevRayPickResult(const QUuid& uid) const;
|
||||
|
||||
void setPrecisionPicking(const QUuid& uid, const bool precisionPicking) const;
|
||||
void setLaserLength(const QUuid& uid, const float laserLength) const;
|
||||
|
|
|
@ -28,7 +28,7 @@ public slots:
|
|||
Q_INVOKABLE void removeLaserPointer(const QUuid& uid) const { qApp->getLaserPointerManager().removeLaserPointer(uid); }
|
||||
Q_INVOKABLE void editRenderState(const QUuid& uid, const QString& renderState, const QVariant& properties) const;
|
||||
Q_INVOKABLE void setRenderState(const QUuid& uid, const QString& renderState) const { qApp->getLaserPointerManager().setRenderState(uid, renderState.toStdString()); }
|
||||
Q_INVOKABLE RayPickResult getPrevRayPickResult(QUuid uid) const { return qApp->getLaserPointerManager().getPrevRayPickResult(uid); }
|
||||
Q_INVOKABLE QVariantMap getPrevRayPickResult(QUuid uid) const { return qApp->getLaserPointerManager().getPrevRayPickResult(uid); }
|
||||
|
||||
Q_INVOKABLE void setPrecisionPicking(const QUuid& uid, bool precisionPicking) const { qApp->getLaserPointerManager().setPrecisionPicking(uid, precisionPicking); }
|
||||
Q_INVOKABLE void setLaserLength(const QUuid& uid, float laserLength) const { qApp->getLaserPointerManager().setLaserLength(uid, laserLength); }
|
||||
|
|
|
@ -8,32 +8,44 @@
|
|||
#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"
|
||||
|
||||
RayToEntityIntersectionResult RayPick::getEntityIntersection(const PickRay& pick, bool precisionPicking,
|
||||
const QVector<EntityItemID>& entitiesToInclude,
|
||||
const QVector<EntityItemID>& entitiesToIgnore,
|
||||
bool visibleOnly, bool collidableOnly) {
|
||||
return DependencyManager::get<EntityScriptingInterface>()->findRayIntersectionVector(pick, precisionPicking,
|
||||
entitiesToInclude, entitiesToIgnore, visibleOnly, collidableOnly);
|
||||
PickResultPointer RayPick::getEntityIntersection(const PickRay& pick) {
|
||||
RayToEntityIntersectionResult entityRes =
|
||||
DependencyManager::get<EntityScriptingInterface>()->findRayIntersectionVector(pick, !getFilter().doesPickCoarse(),
|
||||
getIncludeItemsAs<EntityItemID>(), getIgnoreItemsAs<EntityItemID>(), !getFilter().doesPickInvisible(), !getFilter().doesPickNonCollidable());
|
||||
if (entityRes.intersects) {
|
||||
return std::make_shared<RayPickResult>(IntersectionType::ENTITY, entityRes.entityID, entityRes.distance, entityRes.intersection, pick, entityRes.surfaceNormal);
|
||||
} else {
|
||||
return std::make_shared<RayPickResult>(pick.toVariantMap());
|
||||
}
|
||||
}
|
||||
|
||||
RayToOverlayIntersectionResult RayPick::getOverlayIntersection(const PickRay& pick, bool precisionPicking,
|
||||
const QVector<OverlayID>& overlaysToInclude,
|
||||
const QVector<OverlayID>& overlaysToIgnore,
|
||||
bool visibleOnly, bool collidableOnly) {
|
||||
return qApp->getOverlays().findRayIntersectionVector(pick, precisionPicking,
|
||||
overlaysToInclude, overlaysToIgnore, visibleOnly, collidableOnly);
|
||||
PickResultPointer RayPick::getOverlayIntersection(const PickRay& pick) {
|
||||
RayToOverlayIntersectionResult overlayRes =
|
||||
qApp->getOverlays().findRayIntersectionVector(pick, !getFilter().doesPickCoarse(),
|
||||
getIncludeItemsAs<OverlayID>(), getIgnoreItemsAs<OverlayID>(), !getFilter().doesPickInvisible(), !getFilter().doesPickNonCollidable());
|
||||
if (overlayRes.intersects) {
|
||||
return std::make_shared<RayPickResult>(IntersectionType::OVERLAY, overlayRes.overlayID, overlayRes.distance, overlayRes.intersection, pick, overlayRes.surfaceNormal);
|
||||
} else {
|
||||
return std::make_shared<RayPickResult>(pick.toVariantMap());
|
||||
}
|
||||
}
|
||||
|
||||
RayToAvatarIntersectionResult RayPick::getAvatarIntersection(const PickRay& pick,
|
||||
const QVector<EntityItemID>& avatarsToInclude,
|
||||
const QVector<EntityItemID>& avatarsToIgnore) {
|
||||
return DependencyManager::get<AvatarManager>()->findRayIntersectionVector(pick, avatarsToInclude, avatarsToIgnore);
|
||||
PickResultPointer RayPick::getAvatarIntersection(const PickRay& pick) {
|
||||
RayToAvatarIntersectionResult avatarRes = DependencyManager::get<AvatarManager>()->findRayIntersectionVector(pick, getIncludeItemsAs<EntityItemID>(), getIgnoreItemsAs<EntityItemID>());
|
||||
if (avatarRes.intersects) {
|
||||
return std::make_shared<RayPickResult>(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection, pick);
|
||||
} else {
|
||||
return std::make_shared<RayPickResult>(pick.toVariantMap());
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 RayPick::getHUDIntersection(const PickRay& pick) {
|
||||
return DependencyManager::get<HMDScriptingInterface>()->calculateRayUICollisionPoint(pick.origin, pick.direction);
|
||||
PickResultPointer RayPick::getHUDIntersection(const PickRay& pick) {
|
||||
glm::vec3 hudRes = DependencyManager::get<HMDScriptingInterface>()->calculateRayUICollisionPoint(pick.origin, pick.direction);
|
||||
return std::make_shared<RayPickResult>(IntersectionType::HUD, QUuid(), glm::distance(pick.origin, hudRes), hudRes, pick);
|
||||
}
|
|
@ -8,28 +8,72 @@
|
|||
#ifndef hifi_RayPick_h
|
||||
#define hifi_RayPick_h
|
||||
|
||||
#include "Pick.h"
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <pointers/Pick.h>
|
||||
|
||||
class EntityItemID;
|
||||
class OverlayID;
|
||||
|
||||
class RayPickResult : public PickResult {
|
||||
public:
|
||||
RayPickResult() {}
|
||||
RayPickResult(const QVariantMap& pickVariant) : PickResult(pickVariant) {}
|
||||
RayPickResult(const IntersectionType type, const QUuid& objectID, const float distance, const glm::vec3& intersection, const PickRay& searchRay, const glm::vec3& surfaceNormal = glm::vec3(NAN)) :
|
||||
PickResult(searchRay.toVariantMap()), type(type), intersects(type != NONE), objectID(objectID), distance(distance), intersection(intersection), surfaceNormal(surfaceNormal) {
|
||||
}
|
||||
|
||||
RayPickResult(const RayPickResult& rayPickResult) : PickResult(rayPickResult.pickVariant) {
|
||||
type = rayPickResult.type;
|
||||
intersects = rayPickResult.intersects;
|
||||
objectID = rayPickResult.objectID;
|
||||
distance = rayPickResult.distance;
|
||||
intersection = rayPickResult.intersection;
|
||||
surfaceNormal = rayPickResult.surfaceNormal;
|
||||
}
|
||||
|
||||
IntersectionType type { NONE };
|
||||
bool intersects { false };
|
||||
QUuid objectID;
|
||||
float distance { FLT_MAX };
|
||||
glm::vec3 intersection { NAN };
|
||||
glm::vec3 surfaceNormal { NAN };
|
||||
|
||||
virtual QVariantMap toVariantMap() const override {
|
||||
QVariantMap toReturn;
|
||||
toReturn["type"] = type;
|
||||
toReturn["intersects"] = intersects;
|
||||
toReturn["objectID"] = objectID;
|
||||
toReturn["distance"] = distance;
|
||||
toReturn["intersection"] = vec3toVariant(intersection);
|
||||
toReturn["surfaceNormal"] = vec3toVariant(surfaceNormal);
|
||||
toReturn["searchRay"] = PickResult::toVariantMap();
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
bool doesIntersect() const override { return intersects; }
|
||||
bool checkOrFilterAgainstMaxDistance(float maxDistance) override { return distance < maxDistance; }
|
||||
|
||||
PickResultPointer compareAndProcessNewResult(const PickResultPointer newRes) override {
|
||||
auto newRayRes = std::static_pointer_cast<RayPickResult>(newRes);
|
||||
if (newRayRes->distance < distance) {
|
||||
return std::make_shared<RayPickResult>(*newRayRes);
|
||||
} else {
|
||||
return std::make_shared<RayPickResult>(*this);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class RayPick : public Pick<PickRay> {
|
||||
|
||||
public:
|
||||
RayPick(const PickFilter& filter, const float maxDistance, const bool enabled) : Pick(filter, maxDistance, enabled) {}
|
||||
|
||||
RayToEntityIntersectionResult getEntityIntersection(const PickRay& pick, bool precisionPicking,
|
||||
const QVector<EntityItemID>& entitiesToInclude,
|
||||
const QVector<EntityItemID>& entitiesToIgnore,
|
||||
bool visibleOnly, bool collidableOnly) override;
|
||||
RayToOverlayIntersectionResult getOverlayIntersection(const PickRay& pick, bool precisionPicking,
|
||||
const QVector<OverlayID>& overlaysToInclude,
|
||||
const QVector<OverlayID>& overlaysToIgnore,
|
||||
bool visibleOnly, bool collidableOnly) override;
|
||||
RayToAvatarIntersectionResult getAvatarIntersection(const PickRay& pick,
|
||||
const QVector<EntityItemID>& avatarsToInclude,
|
||||
const QVector<EntityItemID>& avatarsToIgnore) override;
|
||||
glm::vec3 getHUDIntersection(const PickRay& pick) override;
|
||||
PickResultPointer getDefaultResult(const QVariantMap& pickVariant) const override { return std::make_shared<RayPickResult>(pickVariant); }
|
||||
PickResultPointer getEntityIntersection(const PickRay& pick) override;
|
||||
PickResultPointer getOverlayIntersection(const PickRay& pick) override;
|
||||
PickResultPointer getAvatarIntersection(const PickRay& pick) override;
|
||||
PickResultPointer getHUDIntersection(const PickRay& pick) override;
|
||||
};
|
||||
|
||||
#endif // hifi_RayPick_h
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
//
|
||||
// RayPickManager.cpp
|
||||
// interface/src/raypick
|
||||
//
|
||||
// Created by Sam Gondelman 7/11/2017
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
//
|
||||
// RayPickManager.h
|
||||
// interface/src/raypick
|
||||
//
|
||||
// Created by Sam Gondelman 7/11/2017
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
|
@ -11,9 +8,8 @@
|
|||
#ifndef hifi_RayPickManager_h
|
||||
#define hifi_RayPickManager_h
|
||||
|
||||
#include "PickManager.h"
|
||||
|
||||
class RayPickResult;
|
||||
#include <pointers/PickManager.h>
|
||||
#include "RegisteredMetaTypes.h"
|
||||
|
||||
class RayPickManager : public PickManager<PickRay> {
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ void RayPickScriptingInterface::removeRayPick(const QUuid& uid) {
|
|||
qApp->getRayPickManager().removePick(uid);
|
||||
}
|
||||
|
||||
RayPickResult RayPickScriptingInterface::getPrevRayPickResult(const QUuid& uid) {
|
||||
QVariantMap RayPickScriptingInterface::getPrevRayPickResult(const QUuid& uid) {
|
||||
return qApp->getRayPickManager().getPrevPickResult(uid);
|
||||
}
|
||||
|
||||
|
|
|
@ -40,26 +40,26 @@ public slots:
|
|||
Q_INVOKABLE void enableRayPick(const QUuid& uid);
|
||||
Q_INVOKABLE void disableRayPick(const QUuid& uid);
|
||||
Q_INVOKABLE void removeRayPick(const QUuid& uid);
|
||||
Q_INVOKABLE RayPickResult getPrevRayPickResult(const QUuid& uid);
|
||||
Q_INVOKABLE QVariantMap getPrevRayPickResult(const QUuid& uid);
|
||||
|
||||
Q_INVOKABLE void setPrecisionPicking(const QUuid& uid, const bool precisionPicking);
|
||||
Q_INVOKABLE void setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreEntities);
|
||||
Q_INVOKABLE void setIncludeItems(const QUuid& uid, const QScriptValue& includeEntities);
|
||||
|
||||
static unsigned int PICK_NOTHING() { return 0; }
|
||||
static unsigned int PICK_ENTITIES() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_ENTITIES); }
|
||||
static unsigned int PICK_OVERLAYS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_OVERLAYS); }
|
||||
static unsigned int PICK_AVATARS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_AVATARS); }
|
||||
static unsigned int PICK_HUD() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_HUD); }
|
||||
static unsigned int PICK_COARSE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_COARSE); }
|
||||
static unsigned int PICK_INCLUDE_INVISIBLE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_INCLUDE_INVISIBLE); }
|
||||
static unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_INCLUDE_NONCOLLIDABLE); }
|
||||
static unsigned int PICK_ALL_INTERSECTIONS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_ALL_INTERSECTIONS); }
|
||||
static unsigned int INTERSECTED_NONE() { return IntersectionType::NONE; }
|
||||
static unsigned int INTERSECTED_ENTITY() { return IntersectionType::ENTITY; }
|
||||
static unsigned int INTERSECTED_OVERLAY() { return IntersectionType::OVERLAY; }
|
||||
static unsigned int INTERSECTED_AVATAR() { return IntersectionType::AVATAR; }
|
||||
static unsigned int INTERSECTED_HUD() { return IntersectionType::HUD; }
|
||||
static constexpr unsigned int PICK_NOTHING() { return 0; }
|
||||
static constexpr unsigned int PICK_ENTITIES() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_ENTITIES); }
|
||||
static constexpr unsigned int PICK_OVERLAYS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_OVERLAYS); }
|
||||
static constexpr unsigned int PICK_AVATARS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_AVATARS); }
|
||||
static constexpr unsigned int PICK_HUD() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_HUD); }
|
||||
static constexpr unsigned int PICK_COARSE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_COARSE); }
|
||||
static constexpr unsigned int PICK_INCLUDE_INVISIBLE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_INCLUDE_INVISIBLE); }
|
||||
static constexpr unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_INCLUDE_NONCOLLIDABLE); }
|
||||
static constexpr unsigned int PICK_ALL_INTERSECTIONS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_ALL_INTERSECTIONS); }
|
||||
static constexpr unsigned int INTERSECTED_NONE() { return IntersectionType::NONE; }
|
||||
static constexpr unsigned int INTERSECTED_ENTITY() { return IntersectionType::ENTITY; }
|
||||
static constexpr unsigned int INTERSECTED_OVERLAY() { return IntersectionType::OVERLAY; }
|
||||
static constexpr unsigned int INTERSECTED_AVATAR() { return IntersectionType::AVATAR; }
|
||||
static constexpr unsigned int INTERSECTED_HUD() { return IntersectionType::HUD; }
|
||||
};
|
||||
|
||||
#endif // hifi_RayPickScriptingInterface_h
|
||||
|
|
|
@ -13,12 +13,18 @@
|
|||
#include <bitset>
|
||||
|
||||
#include <QtCore/QUuid>
|
||||
#include <QVector>
|
||||
#include <QVariant>
|
||||
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <shared/ReadWriteLockable.h>
|
||||
|
||||
#include "EntityScriptingInterface.h"
|
||||
#include "ui/overlays/Overlays.h"
|
||||
enum IntersectionType {
|
||||
NONE = 0,
|
||||
ENTITY,
|
||||
OVERLAY,
|
||||
AVATAR,
|
||||
HUD
|
||||
};
|
||||
|
||||
class PickFilter {
|
||||
public:
|
||||
|
@ -98,6 +104,31 @@ public:
|
|||
static const PickFilter NOTHING;
|
||||
};
|
||||
|
||||
class PickResult {
|
||||
public:
|
||||
PickResult() {}
|
||||
PickResult(const QVariantMap& pickVariant) : pickVariant(pickVariant) {}
|
||||
|
||||
virtual QVariantMap toVariantMap() const {
|
||||
return pickVariant;
|
||||
}
|
||||
|
||||
virtual bool doesIntersect() const = 0;
|
||||
|
||||
// for example: if we want the closest result, compare based on distance
|
||||
// if we want all results, combine them
|
||||
// must return a new pointer
|
||||
virtual std::shared_ptr<PickResult> compareAndProcessNewResult(const std::shared_ptr<PickResult> newRes) = 0;
|
||||
|
||||
// returns true if this result contains any valid results with distance < maxDistance
|
||||
// can also filter out results with distance >= maxDistance
|
||||
virtual bool checkOrFilterAgainstMaxDistance(float maxDistance) = 0;
|
||||
|
||||
QVariantMap pickVariant;
|
||||
};
|
||||
|
||||
using PickResultPointer = std::shared_ptr<PickResult>;
|
||||
|
||||
template<typename T>
|
||||
class Pick : protected ReadWriteLockable {
|
||||
|
||||
|
@ -105,18 +136,11 @@ public:
|
|||
Pick(const PickFilter& filter, const float maxDistance, const bool enabled);
|
||||
|
||||
virtual const T getMathematicalPick() const = 0;
|
||||
virtual RayToEntityIntersectionResult getEntityIntersection(const T& pick, bool precisionPicking,
|
||||
const QVector<EntityItemID>& entitiesToInclude,
|
||||
const QVector<EntityItemID>& entitiesToIgnore,
|
||||
bool visibleOnly, bool collidableOnly) = 0;
|
||||
virtual RayToOverlayIntersectionResult getOverlayIntersection(const T& pick, bool precisionPicking,
|
||||
const QVector<OverlayID>& overlaysToInclude,
|
||||
const QVector<OverlayID>& overlaysToIgnore,
|
||||
bool visibleOnly, bool collidableOnly) = 0;
|
||||
virtual RayToAvatarIntersectionResult getAvatarIntersection(const T& pick,
|
||||
const QVector<EntityItemID>& avatarsToInclude,
|
||||
const QVector<EntityItemID>& avatarsToIgnore) = 0;
|
||||
virtual glm::vec3 getHUDIntersection(const T& pick) = 0;
|
||||
virtual PickResultPointer getDefaultResult(const QVariantMap& pickVariant) const = 0;
|
||||
virtual PickResultPointer getEntityIntersection(const T& pick) = 0;
|
||||
virtual PickResultPointer getOverlayIntersection(const T& pick) = 0;
|
||||
virtual PickResultPointer getAvatarIntersection(const T& pick) = 0;
|
||||
virtual PickResultPointer getHUDIntersection(const T& pick) = 0;
|
||||
|
||||
void enable(bool enabled = true);
|
||||
void disable() { enable(false); }
|
||||
|
@ -124,11 +148,11 @@ public:
|
|||
PickFilter getFilter() const;
|
||||
float getMaxDistance() const;
|
||||
bool isEnabled() const;
|
||||
RayPickResult getPrevPickResult() const;
|
||||
|
||||
void setPrecisionPicking(bool precisionPicking);
|
||||
|
||||
void setPickResult(const RayPickResult& rayPickResult);
|
||||
PickResultPointer getPrevPickResult() const;
|
||||
void setPickResult(const PickResultPointer& pickResult);
|
||||
|
||||
QVector<QUuid> getIgnoreItems() const;
|
||||
QVector<QUuid> getIncludeItems() const;
|
||||
|
@ -162,7 +186,7 @@ private:
|
|||
PickFilter _filter;
|
||||
const float _maxDistance;
|
||||
bool _enabled;
|
||||
RayPickResult _prevResult;
|
||||
PickResultPointer _prevResult;
|
||||
|
||||
QVector<QUuid> _ignoreItems;
|
||||
QVector<QUuid> _includeItems;
|
||||
|
@ -209,9 +233,9 @@ void Pick<T>::setPrecisionPicking(bool precisionPicking) {
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
void Pick<T>::setPickResult(const RayPickResult& PickResult) {
|
||||
void Pick<T>::setPickResult(const PickResultPointer& pickResult) {
|
||||
withWriteLock([&] {
|
||||
_prevResult = PickResult;
|
||||
_prevResult = pickResult;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -230,8 +254,8 @@ QVector<QUuid> Pick<T>::getIncludeItems() const {
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
RayPickResult Pick<T>::getPrevPickResult() const {
|
||||
return resultWithReadLock<RayPickResult>([&] {
|
||||
PickResultPointer Pick<T>::getPrevPickResult() const {
|
||||
return resultWithReadLock<PickResultPointer>([&] {
|
||||
return _prevResult;
|
||||
});
|
||||
}
|
|
@ -1,7 +1,4 @@
|
|||
//
|
||||
// PickManager.h
|
||||
// interface/src/raypick
|
||||
//
|
||||
// Created by Sam Gondelman 10/16/2017
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
|
@ -36,16 +33,20 @@ namespace std {
|
|||
};
|
||||
}
|
||||
|
||||
// T is a mathematical representation of a Pick.
|
||||
// For example: PickRay for RayPick
|
||||
// TODO: add another template type to replace RayPickResult with a generalized PickResult
|
||||
// T is a mathematical representation of a Pick
|
||||
// For example: RayPicks use T = PickRay
|
||||
// T needs have the following functions defined:
|
||||
// - operator bool() const
|
||||
// - bool operator==(const T& other) const
|
||||
// - QVariantMap toVariantMap() const
|
||||
// - an std::hash size_t operator()(const T& a) const
|
||||
template<typename T>
|
||||
class PickManager : protected ReadWriteLockable {
|
||||
|
||||
public:
|
||||
virtual void update();
|
||||
|
||||
RayPickResult getPrevPickResult(const QUuid& uid) const;
|
||||
QVariantMap getPrevPickResult(const QUuid& uid) const;
|
||||
|
||||
QUuid addPick(const std::shared_ptr<Pick<T>> pick);
|
||||
void removePick(const QUuid& uid);
|
||||
|
@ -60,11 +61,11 @@ protected:
|
|||
std::shared_ptr<Pick<T>> findPick(const QUuid& uid) const;
|
||||
QHash<QUuid, std::shared_ptr<Pick<T>>> _picks;
|
||||
|
||||
typedef std::unordered_map<T, std::unordered_map<PickCacheKey, RayPickResult>> PickCache;
|
||||
typedef std::unordered_map<T, std::unordered_map<PickCacheKey, PickResultPointer>> PickCache;
|
||||
|
||||
// Returns true if this ray exists in the cache, and if it does, update res if the cached result is closer
|
||||
bool checkAndCompareCachedResults(T& pick, PickCache& cache, RayPickResult& res, const PickCacheKey& key);
|
||||
void cacheResult(const bool intersects, const RayPickResult& resTemp, const PickCacheKey& key, RayPickResult& res, T& pick, PickCache& cache);
|
||||
// Returns true if this pick exists in the cache, and if it does, update res if the cached result is closer
|
||||
bool checkAndCompareCachedResults(T& pick, PickCache& cache, PickResultPointer& res, const PickCacheKey& key);
|
||||
void cacheResult(const bool intersects, const PickResultPointer& resTemp, const PickCacheKey& key, PickResultPointer& res, T& mathPick, PickCache& cache, const std::shared_ptr<Pick<T>> pick);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
@ -78,25 +79,21 @@ std::shared_ptr<Pick<T>> PickManager<T>::findPick(const QUuid& uid) const {
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
bool PickManager<T>::checkAndCompareCachedResults(T& pick, PickCache& cache, RayPickResult& res, const PickCacheKey& key) {
|
||||
bool PickManager<T>::checkAndCompareCachedResults(T& pick, PickCache& cache, PickResultPointer& res, const PickCacheKey& key) {
|
||||
if (cache.find(pick) != cache.end() && cache[pick].find(key) != cache[pick].end()) {
|
||||
if (cache[pick][key].distance < res.distance) {
|
||||
res = cache[pick][key];
|
||||
}
|
||||
res = res->compareAndProcessNewResult(cache[pick][key]);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void PickManager<T>::cacheResult(const bool intersects, const RayPickResult& resTemp, const PickCacheKey& key, RayPickResult& res, T& pick, PickCache& cache) {
|
||||
void PickManager<T>::cacheResult(const bool intersects, const PickResultPointer& resTemp, const PickCacheKey& key, PickResultPointer& res, T& mathPick, PickCache& cache, const std::shared_ptr<Pick<T>> pick) {
|
||||
if (intersects) {
|
||||
cache[pick][key] = resTemp;
|
||||
if (resTemp.distance < res.distance) {
|
||||
res = resTemp;
|
||||
}
|
||||
cache[mathPick][key] = resTemp;
|
||||
res = res->compareAndProcessNewResult(resTemp);
|
||||
} else {
|
||||
cache[pick][key] = RayPickResult(res.searchRay);
|
||||
cache[mathPick][key] = pick->getDefaultResult(mathPick.toVariantMap());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,50 +117,29 @@ void PickManager<T>::update() {
|
|||
continue;
|
||||
}
|
||||
|
||||
RayPickResult res = RayPickResult(mathematicalPick);
|
||||
PickResultPointer res = pick->getDefaultResult(mathematicalPick.toVariantMap());
|
||||
|
||||
if (pick->getFilter().doesPickEntities()) {
|
||||
RayToEntityIntersectionResult entityRes;
|
||||
bool fromCache = true;
|
||||
bool invisible = pick->getFilter().doesPickInvisible();
|
||||
bool nonCollidable = pick->getFilter().doesPickNonCollidable();
|
||||
PickCacheKey entityKey = { pick->getFilter().getEntityFlags(), pick->getIncludeItems(), pick->getIgnoreItems() };
|
||||
if (!checkAndCompareCachedResults(mathematicalPick, results, res, entityKey)) {
|
||||
entityRes = pick->getEntityIntersection(mathematicalPick, !pick->getFilter().doesPickCoarse(),
|
||||
pick->(template getIncludeItemsAs<EntityItemID>()), (template pick->getIgnoreItemsAs<EntityItemID>()), !invisible, !nonCollidable);
|
||||
fromCache = false;
|
||||
}
|
||||
|
||||
if (!fromCache) {
|
||||
cacheResult(entityRes.intersects, RayPickResult(IntersectionType::ENTITY, entityRes.entityID, entityRes.distance, entityRes.intersection, mathematicalPick, entityRes.surfaceNormal),
|
||||
entityKey, res, mathematicalPick, results);
|
||||
PickResultPointer entityRes = pick->getEntityIntersection(mathematicalPick);
|
||||
cacheResult(entityRes->doesIntersect(), entityRes, entityKey, res, mathematicalPick, results, pick);
|
||||
}
|
||||
}
|
||||
|
||||
if (pick->getFilter().doesPickOverlays()) {
|
||||
RayToOverlayIntersectionResult overlayRes;
|
||||
bool fromCache = true;
|
||||
bool invisible = pick->getFilter().doesPickInvisible();
|
||||
bool nonCollidable = pick->getFilter().doesPickNonCollidable();
|
||||
PickCacheKey overlayKey = { pick->getFilter().getOverlayFlags(), pick->getIncludeItems(), pick->getIgnoreItems() };
|
||||
if (!checkAndCompareCachedResults(mathematicalPick, results, res, overlayKey)) {
|
||||
overlayRes = pick->getOverlayIntersection(mathematicalPick, !pick->getFilter().doesPickCoarse(),
|
||||
pick->(template getIncludeItemsAs<OverlayID>()), pick->(template getIgnoreItemsAs<OverlayID>()), !invisible, !nonCollidable);
|
||||
fromCache = false;
|
||||
}
|
||||
|
||||
if (!fromCache) {
|
||||
cacheResult(overlayRes.intersects, RayPickResult(IntersectionType::OVERLAY, overlayRes.overlayID, overlayRes.distance, overlayRes.intersection, mathematicalPick, overlayRes.surfaceNormal),
|
||||
overlayKey, res, mathematicalPick, results);
|
||||
PickResultPointer overlayRes = pick->getOverlayIntersection(mathematicalPick);
|
||||
cacheResult(overlayRes->doesIntersect(), overlayRes, overlayKey, res, mathematicalPick, results, pick);
|
||||
}
|
||||
}
|
||||
|
||||
if (pick->getFilter().doesPickAvatars()) {
|
||||
PickCacheKey avatarKey = { pick->getFilter().getAvatarFlags(), pick->getIncludeItems(), pick->getIgnoreItems() };
|
||||
if (!checkAndCompareCachedResults(mathematicalPick, results, res, avatarKey)) {
|
||||
RayToAvatarIntersectionResult avatarRes = pick->getAvatarIntersection(mathematicalPick,
|
||||
pick->(template getIncludeItemsAs<EntityItemID>()), pick->(template getIgnoreItemsAs<EntityItemID>()));
|
||||
cacheResult(avatarRes.intersects, RayPickResult(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection, mathematicalPick), avatarKey, res, mathematicalPick, results);
|
||||
PickResultPointer avatarRes = pick->getAvatarIntersection(mathematicalPick);
|
||||
cacheResult(avatarRes->doesIntersect(), avatarRes, avatarKey, res, mathematicalPick, results, pick);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,26 +147,26 @@ void PickManager<T>::update() {
|
|||
if (pick->getFilter().doesPickHUD() && DependencyManager::get<HMDScriptingInterface>()->isHMDMode()) {
|
||||
PickCacheKey hudKey = { pick->getFilter().getHUDFlags(), QVector<QUuid>(), QVector<QUuid>() };
|
||||
if (!checkAndCompareCachedResults(mathematicalPick, results, res, hudKey)) {
|
||||
glm::vec3 hudRes = pick->getHUDIntersection(mathematicalPick);
|
||||
cacheResult(true, RayPickResult(IntersectionType::HUD, 0, glm::distance(mathematicalPick.origin, hudRes), hudRes, mathematicalPick), hudKey, res, mathematicalPick, results);
|
||||
PickResultPointer hudRes = pick->getHUDIntersection(mathematicalPick);
|
||||
cacheResult(true, hudRes, hudKey, res, mathematicalPick, results, pick);
|
||||
}
|
||||
}
|
||||
|
||||
if (pick->getMaxDistance() == 0.0f || (pick->getMaxDistance() > 0.0f && res.distance < pick->getMaxDistance())) {
|
||||
if (pick->getMaxDistance() == 0.0f || (pick->getMaxDistance() > 0.0f && res->checkOrFilterAgainstMaxDistance(pick->getMaxDistance()))) {
|
||||
pick->setPickResult(res);
|
||||
} else {
|
||||
pick->setPickResult(RayPickResult(mathematicalPick));
|
||||
pick->setPickResult(pick->getDefaultResult(mathematicalPick.toVariantMap()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
RayPickResult PickManager<T>::getPrevPickResult(const QUuid& uid) const {
|
||||
QVariantMap PickManager<T>::getPrevPickResult(const QUuid& uid) const {
|
||||
auto pick = findPick(uid);
|
||||
if (pick) {
|
||||
return pick->getPrevPickResult();
|
||||
if (pick && pick->getPrevPickResult()) {
|
||||
return pick->getPrevPickResult()->toVariantMap();
|
||||
}
|
||||
return RayPickResult();
|
||||
return QVariantMap();
|
||||
}
|
||||
|
||||
template<typename T>
|
|
@ -34,7 +34,6 @@ int vec2MetaTypeId = qRegisterMetaType<glm::vec2>();
|
|||
int quatMetaTypeId = qRegisterMetaType<glm::quat>();
|
||||
int xColorMetaTypeId = qRegisterMetaType<xColor>();
|
||||
int pickRayMetaTypeId = qRegisterMetaType<PickRay>();
|
||||
int rayPickResultMetaTypeId = qRegisterMetaType<RayPickResult>();
|
||||
int collisionMetaTypeId = qRegisterMetaType<Collision>();
|
||||
int qMapURLStringMetaTypeId = qRegisterMetaType<QMap<QUrl,QString>>();
|
||||
int socketErrorMetaTypeId = qRegisterMetaType<QAbstractSocket::SocketError>();
|
||||
|
@ -57,7 +56,6 @@ 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);
|
||||
|
@ -753,26 +751,6 @@ 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);
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
|
@ -128,6 +128,7 @@ void aaCubeFromScriptValue(const QScriptValue &object, AACube& aaCube);
|
|||
class PickRay {
|
||||
public:
|
||||
PickRay() : origin(NAN), direction(NAN) { }
|
||||
PickRay(const QVariantMap& pickVariant) : origin(vec3FromVariant(pickVariant["origin"])), direction(vec3FromVariant(pickVariant["direction"])) {}
|
||||
PickRay(const glm::vec3& origin, const glm::vec3 direction) : origin(origin), direction(direction) {}
|
||||
glm::vec3 origin;
|
||||
glm::vec3 direction;
|
||||
|
@ -138,6 +139,12 @@ public:
|
|||
bool operator==(const PickRay& other) const {
|
||||
return (origin == other.origin && direction == other.direction);
|
||||
}
|
||||
QVariantMap toVariantMap() const {
|
||||
QVariantMap pickRay;
|
||||
pickRay["origin"] = vec3toVariant(origin);
|
||||
pickRay["direction"] = vec3toVariant(direction);
|
||||
return pickRay;
|
||||
}
|
||||
};
|
||||
namespace std {
|
||||
template <>
|
||||
|
@ -157,31 +164,6 @@ Q_DECLARE_METATYPE(PickRay)
|
|||
QScriptValue pickRayToScriptValue(QScriptEngine* engine, const PickRay& pickRay);
|
||||
void pickRayFromScriptValue(const QScriptValue& object, PickRay& pickRay);
|
||||
|
||||
enum IntersectionType {
|
||||
NONE = 0,
|
||||
ENTITY,
|
||||
OVERLAY,
|
||||
AVATAR,
|
||||
HUD
|
||||
};
|
||||
|
||||
class RayPickResult {
|
||||
public:
|
||||
RayPickResult() {}
|
||||
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;
|
||||
float distance { FLT_MAX };
|
||||
glm::vec3 intersection { NAN };
|
||||
PickRay searchRay;
|
||||
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,
|
||||
|
|
Loading…
Reference in a new issue