mirror of
https://github.com/JulianGro/overte.git
synced 2025-08-12 19:55:13 +02:00
pickmanager wip
This commit is contained in:
parent
429905de51
commit
596be8ec27
15 changed files with 487 additions and 345 deletions
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
#include "avatar/AvatarManager.h"
|
#include "avatar/AvatarManager.h"
|
||||||
|
|
||||||
JointRayPick::JointRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const RayPickFilter& filter, const float maxDistance, const bool enabled) :
|
JointRayPick::JointRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const PickFilter& filter, const float maxDistance, const bool enabled) :
|
||||||
RayPick(filter, maxDistance, enabled),
|
RayPick(filter, maxDistance, enabled),
|
||||||
_jointName(jointName),
|
_jointName(jointName),
|
||||||
_posOffset(posOffset),
|
_posOffset(posOffset),
|
||||||
|
@ -20,7 +20,7 @@ JointRayPick::JointRayPick(const std::string& jointName, const glm::vec3& posOff
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
const PickRay JointRayPick::getPickRay(bool& valid) const {
|
const PickRay JointRayPick::getMathematicalPick(bool& valid) const {
|
||||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||||
int jointIndex = myAvatar->getJointIndex(QString::fromStdString(_jointName));
|
int jointIndex = myAvatar->getJointIndex(QString::fromStdString(_jointName));
|
||||||
bool useAvatarHead = _jointName == "Avatar";
|
bool useAvatarHead = _jointName == "Avatar";
|
||||||
|
|
|
@ -11,14 +11,14 @@
|
||||||
#ifndef hifi_JointRayPick_h
|
#ifndef hifi_JointRayPick_h
|
||||||
#define hifi_JointRayPick_h
|
#define hifi_JointRayPick_h
|
||||||
|
|
||||||
#include <pointers/rays/RayPick.h>
|
#include "RayPick.h"
|
||||||
|
|
||||||
class JointRayPick : public RayPick {
|
class JointRayPick : public RayPick {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
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);
|
JointRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const PickFilter& filter, const float maxDistance = 0.0f, const bool enabled = false);
|
||||||
|
|
||||||
const PickRay getPickRay(bool& valid) const override;
|
const PickRay getMathematicalPick(bool& valid) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string _jointName;
|
std::string _jointName;
|
||||||
|
|
|
@ -10,16 +10,15 @@
|
||||||
//
|
//
|
||||||
#include "MouseRayPick.h"
|
#include "MouseRayPick.h"
|
||||||
|
|
||||||
#include "DependencyManager.h"
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "display-plugins/CompositorHelper.h"
|
#include "display-plugins/CompositorHelper.h"
|
||||||
|
|
||||||
MouseRayPick::MouseRayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled) :
|
MouseRayPick::MouseRayPick(const PickFilter& filter, const float maxDistance, const bool enabled) :
|
||||||
RayPick(filter, maxDistance, enabled)
|
RayPick(filter, maxDistance, enabled)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
const PickRay MouseRayPick::getPickRay(bool& valid) const {
|
const PickRay MouseRayPick::getMathematicalPick(bool& valid) const {
|
||||||
QVariant position = qApp->getApplicationCompositor().getReticleInterface()->getPosition();
|
QVariant position = qApp->getApplicationCompositor().getReticleInterface()->getPosition();
|
||||||
if (position.isValid()) {
|
if (position.isValid()) {
|
||||||
QVariantMap posMap = position.toMap();
|
QVariantMap posMap = position.toMap();
|
||||||
|
|
|
@ -11,14 +11,14 @@
|
||||||
#ifndef hifi_MouseRayPick_h
|
#ifndef hifi_MouseRayPick_h
|
||||||
#define hifi_MouseRayPick_h
|
#define hifi_MouseRayPick_h
|
||||||
|
|
||||||
#include <pointers/rays/RayPick.h>
|
#include "RayPick.h"
|
||||||
|
|
||||||
class MouseRayPick : public RayPick {
|
class MouseRayPick : public RayPick {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MouseRayPick(const RayPickFilter& filter, const float maxDistance = 0.0f, const bool enabled = false);
|
MouseRayPick(const PickFilter& filter, const float maxDistance = 0.0f, const bool enabled = false);
|
||||||
|
|
||||||
const PickRay getPickRay(bool& valid) const override;
|
const PickRay getMathematicalPick(bool& valid) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_MouseRayPick_h
|
#endif // hifi_MouseRayPick_h
|
||||||
|
|
10
interface/src/raypick/Pick.cpp
Normal file
10
interface/src/raypick/Pick.cpp
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
//
|
||||||
|
// Created by Sam Gondelman 10/17/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 "Pick.h"
|
||||||
|
|
||||||
|
const PickFilter PickFilter::NOTHING;
|
|
@ -1,12 +1,12 @@
|
||||||
//
|
//
|
||||||
// Created by Sam Gondelman 7/11/2017
|
// Created by Sam Gondelman 10/17/2017
|
||||||
// Copyright 2017 High Fidelity, Inc.
|
// Copyright 2017 High Fidelity, Inc.
|
||||||
//
|
//
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
#ifndef hifi_RayPick_h
|
#ifndef hifi_Pick_h
|
||||||
#define hifi_RayPick_h
|
#define hifi_Pick_h
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
@ -16,7 +16,10 @@
|
||||||
#include <RegisteredMetaTypes.h>
|
#include <RegisteredMetaTypes.h>
|
||||||
#include <shared/ReadWriteLockable.h>
|
#include <shared/ReadWriteLockable.h>
|
||||||
|
|
||||||
class RayPickFilter {
|
#include "EntityScriptingInterface.h"
|
||||||
|
#include "ui/overlays/Overlays.h"
|
||||||
|
|
||||||
|
class PickFilter {
|
||||||
public:
|
public:
|
||||||
enum FlagBit {
|
enum FlagBit {
|
||||||
PICK_ENTITIES = 0,
|
PICK_ENTITIES = 0,
|
||||||
|
@ -39,11 +42,11 @@ public:
|
||||||
// The key is the Flags
|
// The key is the Flags
|
||||||
Flags _flags;
|
Flags _flags;
|
||||||
|
|
||||||
RayPickFilter() {}
|
PickFilter() {}
|
||||||
RayPickFilter(const Flags& flags) : _flags(flags) {}
|
PickFilter(const Flags& flags) : _flags(flags) {}
|
||||||
|
|
||||||
bool operator== (const RayPickFilter& rhs) const { return _flags == rhs._flags; }
|
bool operator== (const PickFilter& rhs) const { return _flags == rhs._flags; }
|
||||||
bool operator!= (const RayPickFilter& rhs) const { return _flags != rhs._flags; }
|
bool operator!= (const PickFilter& rhs) const { return _flags != rhs._flags; }
|
||||||
|
|
||||||
void setFlag(FlagBit flag, bool value) { _flags[flag] = value; }
|
void setFlag(FlagBit flag, bool value) { _flags[flag] = value; }
|
||||||
|
|
||||||
|
@ -91,29 +94,42 @@ public:
|
||||||
|
|
||||||
static constexpr unsigned int getBitMask(FlagBit bit) { return 1 << bit; }
|
static constexpr unsigned int getBitMask(FlagBit bit) { return 1 << bit; }
|
||||||
|
|
||||||
static const RayPickFilter NOTHING;
|
static const PickFilter NOTHING;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RayPick : protected ReadWriteLockable {
|
template<typename T>
|
||||||
|
class Pick : protected ReadWriteLockable {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using Pointer = std::shared_ptr<RayPick>;
|
using Pointer = std::shared_ptr<Pick<T>>;
|
||||||
|
|
||||||
RayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled);
|
Pick(const PickFilter& filter, const float maxDistance, const bool enabled);
|
||||||
|
|
||||||
virtual const PickRay getPickRay(bool& valid) const = 0;
|
virtual const T getMathematicalPick(bool& valid) 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;
|
||||||
|
|
||||||
void enable(bool enabled = true);
|
void enable(bool enabled = true);
|
||||||
void disable() { enable(false); }
|
void disable() { enable(false); }
|
||||||
|
|
||||||
RayPickFilter getFilter() const;
|
PickFilter getFilter() const;
|
||||||
float getMaxDistance() const;
|
float getMaxDistance() const;
|
||||||
bool isEnabled() const;
|
bool isEnabled() const;
|
||||||
RayPickResult getPrevRayPickResult() const;
|
RayPickResult getPrevPickResult() const;
|
||||||
|
|
||||||
void setPrecisionPicking(bool precisionPicking);
|
void setPrecisionPicking(bool precisionPicking);
|
||||||
|
|
||||||
void setRayPickResult(const RayPickResult& rayPickResult);
|
void setPickResult(const RayPickResult& rayPickResult);
|
||||||
|
|
||||||
QVector<QUuid> getIgnoreItems() const;
|
QVector<QUuid> getIgnoreItems() const;
|
||||||
QVector<QUuid> getIncludeItems() const;
|
QVector<QUuid> getIncludeItems() const;
|
||||||
|
@ -144,7 +160,7 @@ public:
|
||||||
void setIncludeItems(const QVector<QUuid>& items);
|
void setIncludeItems(const QVector<QUuid>& items);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RayPickFilter _filter;
|
PickFilter _filter;
|
||||||
const float _maxDistance;
|
const float _maxDistance;
|
||||||
bool _enabled;
|
bool _enabled;
|
||||||
RayPickResult _prevResult;
|
RayPickResult _prevResult;
|
||||||
|
@ -153,4 +169,87 @@ private:
|
||||||
QVector<QUuid> _includeItems;
|
QVector<QUuid> _includeItems;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_RayPick_h
|
|
||||||
|
template<typename T>
|
||||||
|
Pick<T>::Pick(const PickFilter& filter, const float maxDistance, const bool enabled) :
|
||||||
|
_filter(filter),
|
||||||
|
_maxDistance(maxDistance),
|
||||||
|
_enabled(enabled) {
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void Pick<T>::enable(bool enabled) {
|
||||||
|
withWriteLock([&] {
|
||||||
|
_enabled = enabled;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
PickFilter Pick<T>::getFilter() const {
|
||||||
|
return resultWithReadLock<PickFilter>([&] {
|
||||||
|
return _filter;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
float Pick<T>::getMaxDistance() const {
|
||||||
|
return _maxDistance;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
bool Pick<T>::isEnabled() const {
|
||||||
|
withReadLock([&]) {
|
||||||
|
return _enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void Pick<T>::setPrecisionPicking(bool precisionPicking) {
|
||||||
|
withWriteLock([&] {
|
||||||
|
_filter.setFlag(PickFilter::PICK_COARSE, !precisionPicking);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void Pick<T>::setPickResult(const RayPickResult& PickResult) {
|
||||||
|
withWriteLock([&] {
|
||||||
|
_prevResult = PickResult;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
QVector<QUuid> Pick<T>::getIgnoreItems() const {
|
||||||
|
withReadLock([&]) {
|
||||||
|
return _ignoreItems;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
QVector<QUuid> Pick<T>::getIncludeItems() const {
|
||||||
|
withReadLock([&]) {
|
||||||
|
return _includeItems;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
RayPickResult Pick<T>::getPrevPickResult() const {
|
||||||
|
return resultWithReadLock<RayPickResult>([&] {
|
||||||
|
return _prevResult;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void Pick<T>::setIgnoreItems(const QVector<QUuid>& ignoreItems) {
|
||||||
|
withWriteLock([&] {
|
||||||
|
_ignoreItems = ignoreItems;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void Pick<T>::setIncludeItems(const QVector<QUuid>& includeItems) {
|
||||||
|
withWriteLock([&] {
|
||||||
|
_includeItems = includeItems;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // hifi_Pick_h
|
244
interface/src/raypick/PickManager.h
Normal file
244
interface/src/raypick/PickManager.h
Normal file
|
@ -0,0 +1,244 @@
|
||||||
|
//
|
||||||
|
// PickManager.h
|
||||||
|
// interface/src/raypick
|
||||||
|
//
|
||||||
|
// Created by Sam Gondelman 10/16/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_PickManager_h
|
||||||
|
#define hifi_PickManager_h
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "Pick.h"
|
||||||
|
|
||||||
|
typedef struct RayCacheKey {
|
||||||
|
PickFilter::Flags mask;
|
||||||
|
QVector<QUuid> include;
|
||||||
|
QVector<QUuid> ignore;
|
||||||
|
|
||||||
|
bool operator==(const RayCacheKey& other) const {
|
||||||
|
return (mask == other.mask && include == other.include && ignore == other.ignore);
|
||||||
|
}
|
||||||
|
} RayCacheKey;
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
template <>
|
||||||
|
struct hash<RayCacheKey> {
|
||||||
|
size_t operator()(const RayCacheKey& k) const {
|
||||||
|
return ((hash<PickFilter::Flags>()(k.mask) ^ (qHash(k.include) << 1)) >> 1) ^ (qHash(k.ignore) << 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// T is a mathematical representation of a Pick.
|
||||||
|
// For example: origin and direction for RayPick
|
||||||
|
template<typename T>
|
||||||
|
class PickManager : protected ReadWriteLockable {
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void update();
|
||||||
|
|
||||||
|
RayPickResult getPrevPickResult(const QUuid& uid) const;
|
||||||
|
|
||||||
|
void removePick(const QUuid& uid);
|
||||||
|
void enablePick(const QUuid& uid) const;
|
||||||
|
void disablePick(const QUuid& uid) const;
|
||||||
|
|
||||||
|
void setPrecisionPicking(const QUuid& uid, bool precisionPicking) const;
|
||||||
|
void setIgnoreItems(const QUuid& uid, const QVector<QUuid>& ignore) const;
|
||||||
|
void setIncludeItems(const QUuid& uid, const QVector<QUuid>& include) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Pick<T>::Pointer findPick(const QUuid& uid) const;
|
||||||
|
QHash<QUuid, Pick<T>::Pointer> _picks;
|
||||||
|
|
||||||
|
typedef QHash<T, std::unordered_map<RayCacheKey, RayPickResult>> RayPickCache;
|
||||||
|
|
||||||
|
// 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, RayPickCache& cache, RayPickResult& res, const RayCacheKey& key);
|
||||||
|
void cacheResult(const bool intersects, const RayPickResult& resTemp, const RayCacheKey& key, RayPickResult& res, T& pick, RayPickCache& cache);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
RayPick::Pointer PickManager<T>::findPick(const QUuid& uid) const {
|
||||||
|
return resultWithReadLock<RayPick::Pointer>([&] {
|
||||||
|
if (_picks.contains(uid)) {
|
||||||
|
return _picks[uid];
|
||||||
|
}
|
||||||
|
return RayPick::Pointer();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
bool PickManager<T>::checkAndCompareCachedResults(T& pick, RayPickCache& cache, RayPickResult& res, const RayCacheKey& key) {
|
||||||
|
if (cache.contains(pick) && cache[pick].find(key) != cache[pick].end()) {
|
||||||
|
if (cache[pick][key].distance < res.distance) {
|
||||||
|
res = cache[pick][key];
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void PickManager<T>::cacheResult(const bool intersects, const RayPickResult& resTemp, const RayCacheKey& key, RayPickResult& res, T& pick, RayPickCache& cache) {
|
||||||
|
if (intersects) {
|
||||||
|
cache[pick][key] = resTemp;
|
||||||
|
if (resTemp.distance < res.distance) {
|
||||||
|
res = resTemp;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cache[pick][key] = RayPickResult(res.searchRay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void PickManager<T>::update() {
|
||||||
|
RayPickCache results;
|
||||||
|
QHash<QUuid, Pick<T>::Pointer> cachedPicks;
|
||||||
|
withReadLock([&] {
|
||||||
|
cachedPicks = _picks;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const auto& uid : cachedPicks.keys()) {
|
||||||
|
Pick<T>::Pointer pick = cachedPicks[uid];
|
||||||
|
if (!pick->isEnabled() || pick->getFilter().doesPickNothing() || pick->getMaxDistance() < 0.0f) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
T mathematicalPick;
|
||||||
|
|
||||||
|
{
|
||||||
|
bool valid;
|
||||||
|
mathematicalPick = pick->getPickRay(valid);
|
||||||
|
if (!valid) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RayPickResult res = RayPickResult(mathematicalPick);
|
||||||
|
|
||||||
|
if (pick->getFilter().doesPickEntities()) {
|
||||||
|
RayToEntityIntersectionResult entityRes;
|
||||||
|
bool fromCache = true;
|
||||||
|
bool invisible = pick->getFilter().doesPickInvisible();
|
||||||
|
bool nonCollidable = pick->getFilter().doesPickNonCollidable();
|
||||||
|
RayCacheKey entityKey = { pick->getFilter().getEntityFlags(), pick->getIncludeItems(), pick->getIgnoreItems() };
|
||||||
|
if (!checkAndCompareCachedResults(mathematicalPick, results, res, entityKey)) {
|
||||||
|
entityRes = pick->getEntityIntersection(mathematicalPick, !pick->getFilter().doesPickCoarse(),
|
||||||
|
pick->getIncludeItemsAs<EntityItemID>(), 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pick->getFilter().doesPickOverlays()) {
|
||||||
|
RayToOverlayIntersectionResult overlayRes;
|
||||||
|
bool fromCache = true;
|
||||||
|
bool invisible = pick->getFilter().doesPickInvisible();
|
||||||
|
bool nonCollidable = pick->getFilter().doesPickNonCollidable();
|
||||||
|
RayCacheKey overlayKey = { pick->getFilter().getOverlayFlags(), pick->getIncludeItems(), pick->getIgnoreItems() };
|
||||||
|
if (!checkAndCompareCachedResults(mathematicalPick, results, res, overlayKey)) {
|
||||||
|
overlayRes = pick->getOverlayIntersection(mathematicalPick, !pick->getFilter().doesPickCoarse(),
|
||||||
|
pick->getIncludeItemsAs<OverlayID>(), pick->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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pick->getFilter().doesPickAvatars()) {
|
||||||
|
RayCacheKey avatarKey = { pick->getFilter().getAvatarFlags(), pick->getIncludeItems(), pick->getIgnoreItems() };
|
||||||
|
if (!checkAndCompareCachedResults(mathematicalPick, results, res, avatarKey)) {
|
||||||
|
RayToAvatarIntersectionResult avatarRes = pick->getAvatarIntersection(mathematicalPick,
|
||||||
|
pick->getIncludeItemsAs<EntityItemID>(), pick->getIgnoreItemsAs<EntityItemID>());
|
||||||
|
cacheResult(avatarRes.intersects, RayPickResult(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection, mathematicalPick), avatarKey, res, mathematicalPick, results);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can't intersect with HUD in desktop mode
|
||||||
|
if (pick->getFilter().doesPickHUD() && DependencyManager::get<HMDScriptingInterface>()->isHMDMode()) {
|
||||||
|
RayCacheKey hudKey = { pick->getFilter().getHUDFlags(), QVector<QUuid>(), QVector<QUuid>() };
|
||||||
|
if (!checkAndCompareCachedResults(mathematicalPick, results, res, hudKey)) {
|
||||||
|
glm::vec3 hudRes = pick->getHUDIntersection(mathematicalPick.origin, mathematicalPick.direction);
|
||||||
|
cacheResult(true, RayPickResult(IntersectionType::HUD, 0, glm::distance(mathematicalPick.origin, hudRes), hudRes, mathematicalPick), hudKey, res, mathematicalPick, results);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pick->getMaxDistance() == 0.0f || (pick->getMaxDistance() > 0.0f && res.distance < pick->getMaxDistance())) {
|
||||||
|
pick->setPickResult(res);
|
||||||
|
} else {
|
||||||
|
pick->setPickResult(RayPickResult(mathematicalPick));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
RayPickResult PickManager<T>::getPrevPickResult(const QUuid& uid) const {
|
||||||
|
auto rayPick = findPick(uid);
|
||||||
|
if (rayPick) {
|
||||||
|
return rayPick->getPrevPickResult();
|
||||||
|
}
|
||||||
|
return RayPickResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void PickManager<T>::removePick(const QUuid& uid) {
|
||||||
|
withWriteLock([&] {
|
||||||
|
_picks.remove(uid);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void PickManager<T>::enablePick(const QUuid& uid) const {
|
||||||
|
auto rayPick = findPick(uid);
|
||||||
|
if (rayPick) {
|
||||||
|
rayPick->enable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void PickManager<T>::disablePick(const QUuid& uid) const {
|
||||||
|
auto rayPick = findPick(uid);
|
||||||
|
if (rayPick) {
|
||||||
|
rayPick->disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void PickManager<T>::setPrecisionPicking(const QUuid& uid, bool precisionPicking) const {
|
||||||
|
auto rayPick = findPick(uid);
|
||||||
|
if (rayPick) {
|
||||||
|
rayPick->setPrecisionPicking(precisionPicking);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void PickManager<T>::setIgnoreItems(const QUuid& uid, const QVector<QUuid>& ignore) const {
|
||||||
|
auto rayPick = findPick(uid);
|
||||||
|
if (rayPick) {
|
||||||
|
rayPick->setIgnoreItems(ignore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void PickManager<T>::setIncludeItems(const QUuid& uid, const QVector<QUuid>& include) const {
|
||||||
|
auto rayPick = findPick(uid);
|
||||||
|
if (rayPick) {
|
||||||
|
rayPick->setIncludeItems(include);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // hifi_PickManager_h
|
39
interface/src/raypick/RayPick.cpp
Normal file
39
interface/src/raypick/RayPick.cpp
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
//
|
||||||
|
// 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"
|
||||||
|
|
||||||
|
#include "Application.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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
RayToAvatarIntersectionResult RayPick::getAvatarIntersection(const PickRay& pick,
|
||||||
|
const QVector<EntityItemID>& avatarsToInclude,
|
||||||
|
const QVector<EntityItemID>& avatarsToIgnore) {
|
||||||
|
return DependencyManager::get<AvatarManager>()->findRayIntersectionVector(pick, avatarsToInclude, avatarsToIgnore);
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 RayPick::getHUDIntersection(const PickRay& pick) {
|
||||||
|
return DependencyManager::get<HMDScriptingInterface>()->calculateRayUICollisionPoint(pick.origin, pick.direction);
|
||||||
|
}
|
35
interface/src/raypick/RayPick.h
Normal file
35
interface/src/raypick/RayPick.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
//
|
||||||
|
// 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 "Pick.h"
|
||||||
|
|
||||||
|
class EntityItemID;
|
||||||
|
class OverlayID;
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi_RayPick_h
|
|
@ -10,209 +10,33 @@
|
||||||
//
|
//
|
||||||
#include "RayPickManager.h"
|
#include "RayPickManager.h"
|
||||||
|
|
||||||
#include <pointers/rays/StaticRayPick.h>
|
#include "StaticRayPick.h"
|
||||||
|
|
||||||
#include "Application.h"
|
|
||||||
#include "EntityScriptingInterface.h"
|
|
||||||
#include "ui/overlays/Overlays.h"
|
|
||||||
#include "avatar/AvatarManager.h"
|
|
||||||
#include "scripting/HMDScriptingInterface.h"
|
|
||||||
#include "DependencyManager.h"
|
|
||||||
|
|
||||||
#include "JointRayPick.h"
|
#include "JointRayPick.h"
|
||||||
#include "MouseRayPick.h"
|
#include "MouseRayPick.h"
|
||||||
|
|
||||||
bool RayPickManager::checkAndCompareCachedResults(QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache, RayPickResult& res, const RayCacheKey& key) {
|
QUuid RayPickManager::createRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const PickFilter& filter, float maxDistance, bool enabled) {
|
||||||
if (cache.contains(ray) && cache[ray].find(key) != cache[ray].end()) {
|
|
||||||
if (cache[ray][key].distance < res.distance) {
|
|
||||||
res = cache[ray][key];
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RayPickManager::cacheResult(const bool intersects, const RayPickResult& resTemp, const RayCacheKey& key, RayPickResult& res, QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache) {
|
|
||||||
if (intersects) {
|
|
||||||
cache[ray][key] = resTemp;
|
|
||||||
if (resTemp.distance < res.distance) {
|
|
||||||
res = resTemp;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cache[ray][key] = RayPickResult(res.searchRay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RayPickManager::update() {
|
|
||||||
RayPickCache results;
|
|
||||||
QHash<QUuid, RayPick::Pointer> cachedRayPicks;
|
|
||||||
withReadLock([&] {
|
|
||||||
cachedRayPicks = _rayPicks;
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const auto& uid : cachedRayPicks.keys()) {
|
|
||||||
std::shared_ptr<RayPick> rayPick = cachedRayPicks[uid];
|
|
||||||
if (!rayPick->isEnabled() || rayPick->getFilter().doesPickNothing() || rayPick->getMaxDistance() < 0.0f) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
PickRay ray;
|
|
||||||
|
|
||||||
{
|
|
||||||
bool valid;
|
|
||||||
ray = rayPick->getPickRay(valid);
|
|
||||||
if (!valid) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QPair<glm::vec3, glm::vec3> rayKey = QPair<glm::vec3, glm::vec3>(ray.origin, ray.direction);
|
|
||||||
RayPickResult res = RayPickResult(ray);
|
|
||||||
|
|
||||||
if (rayPick->getFilter().doesPickEntities()) {
|
|
||||||
RayToEntityIntersectionResult entityRes;
|
|
||||||
bool fromCache = true;
|
|
||||||
bool invisible = rayPick->getFilter().doesPickInvisible();
|
|
||||||
bool nonCollidable = rayPick->getFilter().doesPickNonCollidable();
|
|
||||||
RayCacheKey entityKey = { rayPick->getFilter().getEntityFlags(), rayPick->getIncludeItems(), rayPick->getIgnoreItems() };
|
|
||||||
if (!checkAndCompareCachedResults(rayKey, results, res, entityKey)) {
|
|
||||||
entityRes = DependencyManager::get<EntityScriptingInterface>()->findRayIntersectionVector(ray, !rayPick->getFilter().doesPickCoarse(),
|
|
||||||
rayPick->getIncludeItemsAs<EntityItemID>(), rayPick->getIgnoreItemsAs<EntityItemID>(), !invisible, !nonCollidable);
|
|
||||||
fromCache = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fromCache) {
|
|
||||||
cacheResult(entityRes.intersects, RayPickResult(IntersectionType::ENTITY, entityRes.entityID, entityRes.distance, entityRes.intersection, ray, entityRes.surfaceNormal),
|
|
||||||
entityKey, res, rayKey, results);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rayPick->getFilter().doesPickOverlays()) {
|
|
||||||
RayToOverlayIntersectionResult overlayRes;
|
|
||||||
bool fromCache = true;
|
|
||||||
bool invisible = rayPick->getFilter().doesPickInvisible();
|
|
||||||
bool nonCollidable = rayPick->getFilter().doesPickNonCollidable();
|
|
||||||
RayCacheKey overlayKey = { rayPick->getFilter().getOverlayFlags(), rayPick->getIncludeItems(), rayPick->getIgnoreItems() };
|
|
||||||
if (!checkAndCompareCachedResults(rayKey, results, res, overlayKey)) {
|
|
||||||
overlayRes = qApp->getOverlays().findRayIntersectionVector(ray, !rayPick->getFilter().doesPickCoarse(),
|
|
||||||
rayPick->getIncludeItemsAs<OverlayID>(), rayPick->getIgnoreItemsAs<OverlayID>(), !invisible, !nonCollidable);
|
|
||||||
fromCache = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fromCache) {
|
|
||||||
cacheResult(overlayRes.intersects, RayPickResult(IntersectionType::OVERLAY, overlayRes.overlayID, overlayRes.distance, overlayRes.intersection, ray, overlayRes.surfaceNormal),
|
|
||||||
overlayKey, res, rayKey, results);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rayPick->getFilter().doesPickAvatars()) {
|
|
||||||
RayCacheKey avatarKey = { rayPick->getFilter().getAvatarFlags(), rayPick->getIncludeItems(), rayPick->getIgnoreItems() };
|
|
||||||
if (!checkAndCompareCachedResults(rayKey, results, res, avatarKey)) {
|
|
||||||
RayToAvatarIntersectionResult avatarRes = DependencyManager::get<AvatarManager>()->findRayIntersectionVector(ray,
|
|
||||||
rayPick->getIncludeItemsAs<EntityItemID>(), rayPick->getIgnoreItemsAs<EntityItemID>());
|
|
||||||
cacheResult(avatarRes.intersects, RayPickResult(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection, ray), avatarKey, res, rayKey, results);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can't intersect with HUD in desktop mode
|
|
||||||
if (rayPick->getFilter().doesPickHUD() && DependencyManager::get<HMDScriptingInterface>()->isHMDMode()) {
|
|
||||||
RayPickFilter::Flags hudMask = rayPick->getFilter().getHUDFlags();
|
|
||||||
RayCacheKey hudKey = { rayPick->getFilter().getHUDFlags() };
|
|
||||||
if (!checkAndCompareCachedResults(rayKey, results, res, hudKey)) {
|
|
||||||
glm::vec3 hudRes = DependencyManager::get<HMDScriptingInterface>()->calculateRayUICollisionPoint(ray.origin, ray.direction);
|
|
||||||
cacheResult(true, RayPickResult(IntersectionType::HUD, 0, glm::distance(ray.origin, hudRes), hudRes, ray), hudKey, res, rayKey, results);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rayPick->getMaxDistance() == 0.0f || (rayPick->getMaxDistance() > 0.0f && res.distance < rayPick->getMaxDistance())) {
|
|
||||||
rayPick->setRayPickResult(res);
|
|
||||||
} else {
|
|
||||||
rayPick->setRayPickResult(RayPickResult(ray));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QUuid RayPickManager::createRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const RayPickFilter& filter, float maxDistance, bool enabled) {
|
|
||||||
auto newRayPick = std::make_shared<JointRayPick>(jointName, posOffset, dirOffset, filter, maxDistance, enabled);
|
auto newRayPick = std::make_shared<JointRayPick>(jointName, posOffset, dirOffset, filter, maxDistance, enabled);
|
||||||
QUuid id = QUuid::createUuid();
|
QUuid id = QUuid::createUuid();
|
||||||
withWriteLock([&] {
|
withWriteLock([&] {
|
||||||
_rayPicks[id] = newRayPick;
|
_picks[id] = newRayPick;
|
||||||
});
|
});
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
QUuid RayPickManager::createRayPick(const RayPickFilter& filter, float maxDistance, bool enabled) {
|
QUuid RayPickManager::createRayPick(const PickFilter& filter, float maxDistance, bool enabled) {
|
||||||
QUuid id = QUuid::createUuid();
|
QUuid id = QUuid::createUuid();
|
||||||
auto newRayPick = std::make_shared<MouseRayPick>(filter, maxDistance, enabled);
|
auto newRayPick = std::make_shared<MouseRayPick>(filter, maxDistance, enabled);
|
||||||
withWriteLock([&] {
|
withWriteLock([&] {
|
||||||
_rayPicks[id] = newRayPick;
|
_picks[id] = newRayPick;
|
||||||
});
|
});
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
QUuid RayPickManager::createRayPick(const glm::vec3& position, const glm::vec3& direction, const RayPickFilter& filter, float maxDistance, bool enabled) {
|
QUuid RayPickManager::createRayPick(const glm::vec3& position, const glm::vec3& direction, const PickFilter& filter, float maxDistance, bool enabled) {
|
||||||
QUuid id = QUuid::createUuid();
|
QUuid id = QUuid::createUuid();
|
||||||
auto newRayPick = std::make_shared<StaticRayPick>(position, direction, filter, maxDistance, enabled);
|
auto newRayPick = std::make_shared<StaticRayPick>(position, direction, filter, maxDistance, enabled);
|
||||||
withWriteLock([&] {
|
withWriteLock([&] {
|
||||||
_rayPicks[id] = newRayPick;
|
_picks[id] = newRayPick;
|
||||||
});
|
});
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RayPickManager::removeRayPick(const QUuid& uid) {
|
|
||||||
withWriteLock([&] {
|
|
||||||
_rayPicks.remove(uid);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
RayPick::Pointer RayPickManager::findRayPick(const QUuid& uid) const {
|
|
||||||
return resultWithReadLock<RayPick::Pointer>([&] {
|
|
||||||
if (_rayPicks.contains(uid)) {
|
|
||||||
return _rayPicks[uid];
|
|
||||||
}
|
|
||||||
return RayPick::Pointer();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void RayPickManager::enableRayPick(const QUuid& uid) const {
|
|
||||||
auto rayPick = findRayPick(uid);
|
|
||||||
if (rayPick) {
|
|
||||||
rayPick->enable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RayPickManager::disableRayPick(const QUuid& uid) const {
|
|
||||||
auto rayPick = findRayPick(uid);
|
|
||||||
if (rayPick) {
|
|
||||||
rayPick->disable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RayPickResult RayPickManager::getPrevRayPickResult(const QUuid& uid) const {
|
|
||||||
auto rayPick = findRayPick(uid);
|
|
||||||
if (rayPick) {
|
|
||||||
return rayPick->getPrevRayPickResult();
|
|
||||||
}
|
|
||||||
return RayPickResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RayPickManager::setPrecisionPicking(const QUuid& uid, bool precisionPicking) const {
|
|
||||||
auto rayPick = findRayPick(uid);
|
|
||||||
if (rayPick) {
|
|
||||||
rayPick->setPrecisionPicking(precisionPicking);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RayPickManager::setIgnoreItems(const QUuid& uid, const QVector<QUuid>& ignore) const {
|
|
||||||
auto rayPick = findRayPick(uid);
|
|
||||||
if (rayPick) {
|
|
||||||
rayPick->setIgnoreItems(ignore);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RayPickManager::setIncludeItems(const QUuid& uid, const QVector<QUuid>& include) const {
|
|
||||||
auto rayPick = findRayPick(uid);
|
|
||||||
if (rayPick) {
|
|
||||||
rayPick->setIncludeItems(include);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -11,64 +11,16 @@
|
||||||
#ifndef hifi_RayPickManager_h
|
#ifndef hifi_RayPickManager_h
|
||||||
#define hifi_RayPickManager_h
|
#define hifi_RayPickManager_h
|
||||||
|
|
||||||
|
#include "PickManager.h"
|
||||||
#include <memory>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <queue>
|
|
||||||
|
|
||||||
#include <QtCore/QObject>
|
|
||||||
|
|
||||||
#include <RegisteredMetaTypes.h>
|
|
||||||
#include <pointers/rays/RayPick.h>
|
|
||||||
|
|
||||||
|
|
||||||
class RayPickResult;
|
class RayPickResult;
|
||||||
|
|
||||||
typedef struct RayCacheKey {
|
class RayPickManager : public PickManager<PickRay> {
|
||||||
RayPickFilter::Flags mask;
|
|
||||||
QVector<QUuid> include;
|
|
||||||
QVector<QUuid> ignore;
|
|
||||||
|
|
||||||
bool operator==(const RayCacheKey& other) const {
|
|
||||||
return (mask == other.mask && include == other.include && ignore == other.ignore);
|
|
||||||
}
|
|
||||||
} RayCacheKey;
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
template <>
|
|
||||||
struct hash<RayCacheKey> {
|
|
||||||
size_t operator()(const RayCacheKey& k) const {
|
|
||||||
return ((hash<RayPickFilter::Flags>()(k.mask) ^ (qHash(k.include) << 1)) >> 1) ^ (qHash(k.ignore) << 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
class RayPickManager : protected ReadWriteLockable {
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void update();
|
QUuid createRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const PickFilter& filter, const float maxDistance, const bool enabled);
|
||||||
|
QUuid createRayPick(const PickFilter& filter, const float maxDistance, const bool enabled);
|
||||||
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 glm::vec3& position, const glm::vec3& direction, const PickFilter& 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) const;
|
|
||||||
void disableRayPick(const QUuid& uid) const;
|
|
||||||
RayPickResult getPrevRayPickResult(const QUuid& uid) const;
|
|
||||||
|
|
||||||
void setPrecisionPicking(const QUuid& uid, bool precisionPicking) const;
|
|
||||||
void setIgnoreItems(const QUuid& uid, const QVector<QUuid>& ignore) const;
|
|
||||||
void setIncludeItems(const QUuid& uid, const QVector<QUuid>& include) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
RayPick::Pointer findRayPick(const QUuid& uid) const;
|
|
||||||
QHash<QUuid, RayPick::Pointer> _rayPicks;
|
|
||||||
|
|
||||||
typedef QHash<QPair<glm::vec3, glm::vec3>, std::unordered_map<RayCacheKey, RayPickResult>> 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<glm::vec3, glm::vec3>& ray, RayPickCache& cache, RayPickResult& res, const RayCacheKey& key);
|
|
||||||
void cacheResult(const bool intersects, const RayPickResult& resTemp, const RayCacheKey& key, RayPickResult& res, QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_RayPickManager_h
|
#endif // hifi_RayPickManager_h
|
|
@ -7,13 +7,13 @@
|
||||||
//
|
//
|
||||||
#include "StaticRayPick.h"
|
#include "StaticRayPick.h"
|
||||||
|
|
||||||
StaticRayPick::StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const RayPickFilter& filter, const float maxDistance, const bool enabled) :
|
StaticRayPick::StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const PickFilter& filter, const float maxDistance, const bool enabled) :
|
||||||
RayPick(filter, maxDistance, enabled),
|
RayPick(filter, maxDistance, enabled),
|
||||||
_pickRay(position, direction)
|
_pickRay(position, direction)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
const PickRay StaticRayPick::getPickRay(bool& valid) const {
|
const PickRay StaticRayPick::getMathematicalPick(bool& valid) const {
|
||||||
valid = true;
|
valid = true;
|
||||||
return _pickRay;
|
return _pickRay;
|
||||||
}
|
}
|
|
@ -13,9 +13,9 @@
|
||||||
class StaticRayPick : public RayPick {
|
class StaticRayPick : public RayPick {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const RayPickFilter& filter, const float maxDistance = 0.0f, const bool enabled = false);
|
StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const PickFilter& filter, const float maxDistance = 0.0f, const bool enabled = false);
|
||||||
|
|
||||||
const PickRay getPickRay(bool& valid) const override;
|
const PickRay getMathematicalPick(bool& valid) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PickRay _pickRay;
|
PickRay _pickRay;
|
|
@ -1,75 +0,0 @@
|
||||||
//
|
|
||||||
// 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"
|
|
||||||
|
|
||||||
const RayPickFilter RayPickFilter::NOTHING;
|
|
||||||
|
|
||||||
RayPick::RayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled) :
|
|
||||||
_filter(filter),
|
|
||||||
_maxDistance(maxDistance),
|
|
||||||
_enabled(enabled)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void RayPick::enable(bool enabled) {
|
|
||||||
withWriteLock([&] {
|
|
||||||
_enabled = enabled;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
RayPickFilter RayPick::getFilter() const {
|
|
||||||
return resultWithReadLock<RayPickFilter>([&] {
|
|
||||||
return _filter;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
float RayPick::getMaxDistance() const {
|
|
||||||
return _maxDistance;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RayPick::isEnabled() const {
|
|
||||||
return _enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RayPick::setPrecisionPicking(bool precisionPicking) {
|
|
||||||
withWriteLock([&]{
|
|
||||||
_filter.setFlag(RayPickFilter::PICK_COARSE, !precisionPicking);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void RayPick::setRayPickResult(const RayPickResult& rayPickResult) {
|
|
||||||
withWriteLock([&] {
|
|
||||||
_prevResult = rayPickResult;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QVector<QUuid> RayPick::getIgnoreItems() const {
|
|
||||||
return _ignoreItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVector<QUuid> RayPick::getIncludeItems() const {
|
|
||||||
return _includeItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
RayPickResult RayPick::getPrevRayPickResult() const {
|
|
||||||
return resultWithReadLock<RayPickResult>([&] {
|
|
||||||
return _prevResult;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void RayPick::setIgnoreItems(const QVector<QUuid>& ignoreItems) {
|
|
||||||
withWriteLock([&] {
|
|
||||||
_ignoreItems = ignoreItems;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void RayPick::setIncludeItems(const QVector<QUuid>& includeItems) {
|
|
||||||
withWriteLock([&] {
|
|
||||||
_includeItems = includeItems;
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -131,7 +131,22 @@ public:
|
||||||
PickRay(const glm::vec3& origin, const glm::vec3 direction) : origin(origin), direction(direction) {}
|
PickRay(const glm::vec3& origin, const glm::vec3 direction) : origin(origin), direction(direction) {}
|
||||||
glm::vec3 origin;
|
glm::vec3 origin;
|
||||||
glm::vec3 direction;
|
glm::vec3 direction;
|
||||||
|
|
||||||
|
bool operator==(const PickRay& other) const {
|
||||||
|
return (origin == other.origin && direction == other.direction);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
namespace std {
|
||||||
|
template <>
|
||||||
|
struct hash<glm::vec3> {
|
||||||
|
size_t operator()(const glm::vec3& a) const {
|
||||||
|
return ((hash<float>()(a.x) ^ (hash<float>()(a.y) << 1)) >> 1) ^ (hash<float>()(a.z) << 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
uint qHash(const PickRay& a) {
|
||||||
|
return (uint)(std::hash<glm::vec3>()(a.origin) ^ (std::hash<glm::vec3>()(a.direction) << 1));
|
||||||
|
}
|
||||||
Q_DECLARE_METATYPE(PickRay)
|
Q_DECLARE_METATYPE(PickRay)
|
||||||
QScriptValue pickRayToScriptValue(QScriptEngine* engine, const PickRay& pickRay);
|
QScriptValue pickRayToScriptValue(QScriptEngine* engine, const PickRay& pickRay);
|
||||||
void pickRayFromScriptValue(const QScriptValue& object, PickRay& pickRay);
|
void pickRayFromScriptValue(const QScriptValue& object, PickRay& pickRay);
|
||||||
|
|
Loading…
Reference in a new issue