mirror of
https://github.com/lubosz/overte.git
synced 2025-04-10 15:57:39 +02:00
force coarse picking, sort avatars
This commit is contained in:
parent
5c0b12abf6
commit
c474f38860
11 changed files with 178 additions and 108 deletions
|
@ -46,6 +46,7 @@
|
|||
#include "InterfaceLogging.h"
|
||||
#include "LocationBookmarks.h"
|
||||
#include "DeferredLightingEffect.h"
|
||||
#include "PickManager.h"
|
||||
|
||||
#include "AmbientOcclusionEffect.h"
|
||||
#include "RenderShadowTask.h"
|
||||
|
@ -688,6 +689,11 @@ Menu::Menu() {
|
|||
addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowBulletConstraints, 0, false, qApp, SLOT(setShowBulletConstraints(bool)));
|
||||
addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowBulletConstraintLimits, 0, false, qApp, SLOT(setShowBulletConstraintLimits(bool)));
|
||||
|
||||
// Developer > Picking >>>
|
||||
MenuWrapper* pickingOptionsMenu = developerMenu->addMenu("Picking");
|
||||
addCheckableActionToQMenuAndActionHash(pickingOptionsMenu, MenuOption::ForceCoarsePicking, 0, false,
|
||||
DependencyManager::get<PickManager>().data(), SLOT(setForceCoarsePicking(bool)));
|
||||
|
||||
// Developer > Display Crash Options
|
||||
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::DisplayCrashOptions, 0, true);
|
||||
// Developer > Crash >>>
|
||||
|
|
|
@ -221,6 +221,7 @@ namespace MenuOption {
|
|||
const QString NotificationSounds = "play_notification_sounds";
|
||||
const QString NotificationSoundsSnapshot = "play_notification_sounds_snapshot";
|
||||
const QString NotificationSoundsTablet = "play_notification_sounds_tablet";
|
||||
const QString ForceCoarsePicking = "Force Coarse Picking";
|
||||
}
|
||||
|
||||
#endif // hifi_Menu_h
|
||||
|
|
|
@ -553,6 +553,14 @@ RayToAvatarIntersectionResult AvatarManager::findRayIntersectionVector(const Pic
|
|||
return result;
|
||||
}
|
||||
|
||||
// It's better to intersect the ray against the avatar's actual mesh, but this is currently difficult to
|
||||
// do, because the transformed mesh data only exists over in GPU-land. As a compromise, this code
|
||||
// intersects against the avatars capsule and then against the (T-pose) mesh. The end effect is that picking
|
||||
// against the avatar is sort-of right, but you likely wont be able to pick against the arms.
|
||||
|
||||
// TODO -- find a way to extract transformed avatar mesh data from the rendering engine.
|
||||
|
||||
std::vector<SortedAvatar> sortedAvatars;
|
||||
auto avatarHashCopy = getHashCopy();
|
||||
for (auto avatarData : avatarHashCopy) {
|
||||
auto avatar = std::static_pointer_cast<Avatar>(avatarData);
|
||||
|
@ -561,47 +569,60 @@ RayToAvatarIntersectionResult AvatarManager::findRayIntersectionVector(const Pic
|
|||
continue;
|
||||
}
|
||||
|
||||
float distance;
|
||||
BoxFace face;
|
||||
glm::vec3 surfaceNormal;
|
||||
|
||||
SkeletonModelPointer avatarModel = avatar->getSkeletonModel();
|
||||
|
||||
// It's better to intersect the ray against the avatar's actual mesh, but this is currently difficult to
|
||||
// do, because the transformed mesh data only exists over in GPU-land. As a compromise, this code
|
||||
// intersects against the avatars capsule and then against the (T-pose) mesh. The end effect is that picking
|
||||
// against the avatar is sort-of right, but you likely wont be able to pick against the arms.
|
||||
|
||||
// TODO -- find a way to extract transformed avatar mesh data from the rendering engine.
|
||||
|
||||
float distance = FLT_MAX;
|
||||
#if 0
|
||||
// if we weren't picking against the capsule, we would want to pick against the avatarBounds...
|
||||
// AABox avatarBounds = avatarModel->getRenderableMeshBound();
|
||||
// if (!avatarBounds.findRayIntersection(ray.origin, normDirection, distance, face, surfaceNormal)) {
|
||||
// // ray doesn't intersect avatar's bounding-box
|
||||
// continue;
|
||||
// }
|
||||
|
||||
SkeletonModelPointer avatarModel = avatar->getSkeletonModel();
|
||||
AABox avatarBounds = avatarModel->getRenderableMeshBound();
|
||||
if (avatarBounds.contains(ray.origin)) {
|
||||
distance = 0.0f;
|
||||
} else {
|
||||
float boundDistance = FLT_MAX;
|
||||
BoxFace face;
|
||||
glm::vec3 surfaceNormal;
|
||||
if (avatarBounds.findRayIntersection(ray.origin, ray.direction, boundDistance, face, surfaceNormal)) {
|
||||
distance = boundDistance;
|
||||
}
|
||||
}
|
||||
#else
|
||||
glm::vec3 start;
|
||||
glm::vec3 end;
|
||||
float radius;
|
||||
avatar->getCapsule(start, end, radius);
|
||||
bool intersects = findRayCapsuleIntersection(ray.origin, ray.direction, start, end, radius, distance);
|
||||
if (!intersects) {
|
||||
// ray doesn't intersect avatar's capsule
|
||||
continue;
|
||||
findRayCapsuleIntersection(ray.origin, ray.direction, start, end, radius, distance);
|
||||
#endif
|
||||
|
||||
if (distance < FLT_MAX) {
|
||||
sortedAvatars.emplace_back(distance, avatar);
|
||||
}
|
||||
}
|
||||
|
||||
if (sortedAvatars.size() > 1) {
|
||||
static auto comparator = [](const SortedAvatar& left, const SortedAvatar& right) { return left.first > right.first; };
|
||||
std::sort(sortedAvatars.begin(), sortedAvatars.end(), comparator);
|
||||
}
|
||||
|
||||
for (auto it = sortedAvatars.begin(); it != sortedAvatars.end(); ++it) {
|
||||
const SortedAvatar& sortedAvatar = *it;
|
||||
// We can exit once avatarCapsuleDistance > bestDistance
|
||||
if (sortedAvatar.first > result.distance) {
|
||||
break;
|
||||
}
|
||||
|
||||
float distance = FLT_MAX;
|
||||
BoxFace face;
|
||||
glm::vec3 surfaceNormal;
|
||||
QVariantMap extraInfo;
|
||||
intersects = avatarModel->findRayIntersectionAgainstSubMeshes(ray.origin, ray.direction,
|
||||
distance, face, surfaceNormal, extraInfo, true);
|
||||
|
||||
if (intersects && (!result.intersects || distance < result.distance)) {
|
||||
result.intersects = true;
|
||||
result.avatarID = avatar->getID();
|
||||
result.distance = distance;
|
||||
result.face = face;
|
||||
result.surfaceNormal = surfaceNormal;
|
||||
result.extraInfo = extraInfo;
|
||||
SkeletonModelPointer avatarModel = sortedAvatar.second->getSkeletonModel();
|
||||
if (avatarModel->findRayIntersectionAgainstSubMeshes(ray.origin, ray.direction, distance, face, surfaceNormal, extraInfo, true)) {
|
||||
if (distance < result.distance) {
|
||||
result.intersects = true;
|
||||
result.avatarID = sortedAvatar.second->getID();
|
||||
result.distance = distance;
|
||||
result.face = face;
|
||||
result.surfaceNormal = surfaceNormal;
|
||||
result.extraInfo = extraInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -625,6 +646,14 @@ ParabolaToAvatarIntersectionResult AvatarManager::findParabolaIntersectionVector
|
|||
return result;
|
||||
}
|
||||
|
||||
// It's better to intersect the ray against the avatar's actual mesh, but this is currently difficult to
|
||||
// do, because the transformed mesh data only exists over in GPU-land. As a compromise, this code
|
||||
// intersects against the avatars capsule and then against the (T-pose) mesh. The end effect is that picking
|
||||
// against the avatar is sort-of right, but you likely wont be able to pick against the arms.
|
||||
|
||||
// TODO -- find a way to extract transformed avatar mesh data from the rendering engine.
|
||||
|
||||
std::vector<SortedAvatar> sortedAvatars;
|
||||
auto avatarHashCopy = getHashCopy();
|
||||
for (auto avatarData : avatarHashCopy) {
|
||||
auto avatar = std::static_pointer_cast<Avatar>(avatarData);
|
||||
|
@ -633,47 +662,60 @@ ParabolaToAvatarIntersectionResult AvatarManager::findParabolaIntersectionVector
|
|||
continue;
|
||||
}
|
||||
|
||||
float parabolicDistance;
|
||||
BoxFace face;
|
||||
glm::vec3 surfaceNormal;
|
||||
|
||||
SkeletonModelPointer avatarModel = avatar->getSkeletonModel();
|
||||
|
||||
// It's better to intersect the parabola against the avatar's actual mesh, but this is currently difficult to
|
||||
// do, because the transformed mesh data only exists over in GPU-land. As a compromise, this code
|
||||
// intersects against the avatars capsule and then against the (T-pose) mesh. The end effect is that picking
|
||||
// against the avatar is sort-of right, but you likely wont be able to pick against the arms.
|
||||
|
||||
// TODO -- find a way to extract transformed avatar mesh data from the rendering engine.
|
||||
|
||||
float distance = FLT_MAX;
|
||||
#if 0
|
||||
// if we weren't picking against the capsule, we would want to pick against the avatarBounds...
|
||||
// AABox avatarBounds = avatarModel->getRenderableMeshBound();
|
||||
// if (!avatarBounds.findParabolaIntersection(pick.origin, pick.velocity, pick.acceleration, parabolicDistance, face, surfaceNormal)) {
|
||||
// // parabola doesn't intersect avatar's bounding-box
|
||||
// continue;
|
||||
// }
|
||||
|
||||
SkeletonModelPointer avatarModel = avatar->getSkeletonModel();
|
||||
AABox avatarBounds = avatarModel->getRenderableMeshBound();
|
||||
if (avatarBounds.contains(pick.origin)) {
|
||||
distance = 0.0f;
|
||||
} else {
|
||||
float boundDistance = FLT_MAX;
|
||||
BoxFace face;
|
||||
glm::vec3 surfaceNormal;
|
||||
if (avatarBounds.findParabolaIntersection(pick.origin, pick.velocity, pick.acceleration, boundDistance, face, surfaceNormal)) {
|
||||
distance = boundDistance;
|
||||
}
|
||||
}
|
||||
#else
|
||||
glm::vec3 start;
|
||||
glm::vec3 end;
|
||||
float radius;
|
||||
avatar->getCapsule(start, end, radius);
|
||||
bool intersects = findParabolaCapsuleIntersection(pick.origin, pick.velocity, pick.acceleration, start, end, radius, avatar->getWorldOrientation(), parabolicDistance);
|
||||
if (!intersects) {
|
||||
// ray doesn't intersect avatar's capsule
|
||||
continue;
|
||||
findParabolaCapsuleIntersection(pick.origin, pick.velocity, pick.acceleration, start, end, radius, avatar->getWorldOrientation(), distance);
|
||||
#endif
|
||||
|
||||
if (distance < FLT_MAX) {
|
||||
sortedAvatars.emplace_back(distance, avatar);
|
||||
}
|
||||
}
|
||||
|
||||
if (sortedAvatars.size() > 1) {
|
||||
static auto comparator = [](const SortedAvatar& left, const SortedAvatar& right) { return left.first > right.first; };
|
||||
std::sort(sortedAvatars.begin(), sortedAvatars.end(), comparator);
|
||||
}
|
||||
|
||||
for (auto it = sortedAvatars.begin(); it != sortedAvatars.end(); ++it) {
|
||||
const SortedAvatar& sortedAvatar = *it;
|
||||
// We can exit once avatarCapsuleDistance > bestDistance
|
||||
if (sortedAvatar.first > result.parabolicDistance) {
|
||||
break;
|
||||
}
|
||||
|
||||
float parabolicDistance = FLT_MAX;
|
||||
BoxFace face;
|
||||
glm::vec3 surfaceNormal;
|
||||
QVariantMap extraInfo;
|
||||
intersects = avatarModel->findParabolaIntersectionAgainstSubMeshes(pick.origin, pick.velocity, pick.acceleration,
|
||||
parabolicDistance, face, surfaceNormal, extraInfo, true);
|
||||
|
||||
if (intersects && (!result.intersects || parabolicDistance < result.parabolicDistance)) {
|
||||
result.intersects = true;
|
||||
result.avatarID = avatar->getID();
|
||||
result.parabolicDistance = parabolicDistance;
|
||||
result.face = face;
|
||||
result.surfaceNormal = surfaceNormal;
|
||||
result.extraInfo = extraInfo;
|
||||
SkeletonModelPointer avatarModel = sortedAvatar.second->getSkeletonModel();
|
||||
if (avatarModel->findParabolaIntersectionAgainstSubMeshes(pick.origin, pick.velocity, pick.acceleration, parabolicDistance, face, surfaceNormal, extraInfo, true)) {
|
||||
if (parabolicDistance < result.parabolicDistance) {
|
||||
result.intersects = true;
|
||||
result.avatarID = sortedAvatar.second->getID();
|
||||
result.parabolicDistance = parabolicDistance;
|
||||
result.face = face;
|
||||
result.surfaceNormal = surfaceNormal;
|
||||
result.extraInfo = extraInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include "AvatarMotionState.h"
|
||||
#include "MyAvatar.h"
|
||||
|
||||
using SortedAvatar = std::pair<float, std::shared_ptr<Avatar>>;
|
||||
|
||||
/**jsdoc
|
||||
* The AvatarManager API has properties and methods which manage Avatars within the same domain.
|
||||
*
|
||||
|
|
|
@ -13,11 +13,13 @@
|
|||
#include "avatar/AvatarManager.h"
|
||||
#include "scripting/HMDScriptingInterface.h"
|
||||
#include "DependencyManager.h"
|
||||
#include "PickManager.h"
|
||||
|
||||
PickResultPointer ParabolaPick::getEntityIntersection(const PickParabola& pick) {
|
||||
if (glm::length2(pick.acceleration) > EPSILON && glm::length2(pick.velocity) > EPSILON) {
|
||||
bool precisionPicking = !(getFilter().doesPickCoarse() || DependencyManager::get<PickManager>()->getForceCoarsePicking());
|
||||
ParabolaToEntityIntersectionResult entityRes =
|
||||
DependencyManager::get<EntityScriptingInterface>()->findParabolaIntersectionVector(pick, !getFilter().doesPickCoarse(),
|
||||
DependencyManager::get<EntityScriptingInterface>()->findParabolaIntersectionVector(pick, precisionPicking,
|
||||
getIncludeItemsAs<EntityItemID>(), getIgnoreItemsAs<EntityItemID>(), !getFilter().doesPickInvisible(), !getFilter().doesPickNonCollidable());
|
||||
if (entityRes.intersects) {
|
||||
return std::make_shared<ParabolaPickResult>(IntersectionType::ENTITY, entityRes.entityID, entityRes.distance, entityRes.parabolicDistance, entityRes.intersection, pick, entityRes.surfaceNormal, entityRes.extraInfo);
|
||||
|
@ -28,8 +30,9 @@ PickResultPointer ParabolaPick::getEntityIntersection(const PickParabola& pick)
|
|||
|
||||
PickResultPointer ParabolaPick::getOverlayIntersection(const PickParabola& pick) {
|
||||
if (glm::length2(pick.acceleration) > EPSILON && glm::length2(pick.velocity) > EPSILON) {
|
||||
bool precisionPicking = !(getFilter().doesPickCoarse() || DependencyManager::get<PickManager>()->getForceCoarsePicking());
|
||||
ParabolaToOverlayIntersectionResult overlayRes =
|
||||
qApp->getOverlays().findParabolaIntersectionVector(pick, !getFilter().doesPickCoarse(),
|
||||
qApp->getOverlays().findParabolaIntersectionVector(pick, precisionPicking,
|
||||
getIncludeItemsAs<OverlayID>(), getIgnoreItemsAs<OverlayID>(), !getFilter().doesPickInvisible(), !getFilter().doesPickNonCollidable());
|
||||
if (overlayRes.intersects) {
|
||||
return std::make_shared<ParabolaPickResult>(IntersectionType::OVERLAY, overlayRes.overlayID, overlayRes.distance, overlayRes.parabolicDistance, overlayRes.intersection, pick, overlayRes.surfaceNormal, overlayRes.extraInfo);
|
||||
|
|
|
@ -13,10 +13,12 @@
|
|||
#include "avatar/AvatarManager.h"
|
||||
#include "scripting/HMDScriptingInterface.h"
|
||||
#include "DependencyManager.h"
|
||||
#include "PickManager.h"
|
||||
|
||||
PickResultPointer RayPick::getEntityIntersection(const PickRay& pick) {
|
||||
bool precisionPicking = !(getFilter().doesPickCoarse() || DependencyManager::get<PickManager>()->getForceCoarsePicking());
|
||||
RayToEntityIntersectionResult entityRes =
|
||||
DependencyManager::get<EntityScriptingInterface>()->findRayIntersectionVector(pick, !getFilter().doesPickCoarse(),
|
||||
DependencyManager::get<EntityScriptingInterface>()->findRayIntersectionVector(pick, precisionPicking,
|
||||
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, entityRes.extraInfo);
|
||||
|
@ -26,8 +28,9 @@ PickResultPointer RayPick::getEntityIntersection(const PickRay& pick) {
|
|||
}
|
||||
|
||||
PickResultPointer RayPick::getOverlayIntersection(const PickRay& pick) {
|
||||
bool precisionPicking = !(getFilter().doesPickCoarse() || DependencyManager::get<PickManager>()->getForceCoarsePicking());
|
||||
RayToOverlayIntersectionResult overlayRes =
|
||||
qApp->getOverlays().findRayIntersectionVector(pick, !getFilter().doesPickCoarse(),
|
||||
qApp->getOverlays().findRayIntersectionVector(pick, precisionPicking,
|
||||
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, overlayRes.extraInfo);
|
||||
|
|
|
@ -1559,7 +1559,7 @@ class RayToAvatarIntersectionResult {
|
|||
public:
|
||||
bool intersects { false };
|
||||
QUuid avatarID;
|
||||
float distance { 0.0f };
|
||||
float distance { FLT_MAX };
|
||||
BoxFace face;
|
||||
glm::vec3 intersection;
|
||||
glm::vec3 surfaceNormal;
|
||||
|
|
|
@ -72,11 +72,15 @@ PickResultPointer PickQuery::getPrevPickResult() const {
|
|||
void PickQuery::setIgnoreItems(const QVector<QUuid>& ignoreItems) {
|
||||
withWriteLock([&] {
|
||||
_ignoreItems = ignoreItems;
|
||||
// We sort these items here so the PickCacheOptimizer can catch cases where two picks have the same ignoreItems in a different order
|
||||
std::sort(_ignoreItems.begin(), _ignoreItems.end(), std::less<QUuid>());
|
||||
});
|
||||
}
|
||||
|
||||
void PickQuery::setIncludeItems(const QVector<QUuid>& includeItems) {
|
||||
withWriteLock([&] {
|
||||
_includeItems = includeItems;
|
||||
// We sort these items here so the PickCacheOptimizer can catch cases where two picks have the same includeItems in a different order
|
||||
std::sort(_includeItems.begin(), _includeItems.end(), std::less<QUuid>());
|
||||
});
|
||||
}
|
|
@ -16,7 +16,10 @@
|
|||
|
||||
#include <NumericalConstants.h>
|
||||
|
||||
class PickManager : public Dependency, protected ReadWriteLockable {
|
||||
#include <QObject>
|
||||
|
||||
class PickManager : public QObject, public Dependency, protected ReadWriteLockable {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
||||
public:
|
||||
|
@ -53,7 +56,13 @@ public:
|
|||
unsigned int getPerFrameTimeBudget() const { return _perFrameTimeBudget; }
|
||||
void setPerFrameTimeBudget(unsigned int numUsecs) { _perFrameTimeBudget = numUsecs; }
|
||||
|
||||
bool getForceCoarsePicking() { return _forceCoarsePicking; }
|
||||
|
||||
public slots:
|
||||
void setForceCoarsePicking(bool forceCoarsePicking) { _forceCoarsePicking = forceCoarsePicking; }
|
||||
|
||||
protected:
|
||||
bool _forceCoarsePicking { false };
|
||||
std::function<bool()> _shouldPickHUDOperator;
|
||||
std::function<glm::vec2(const glm::vec3&)> _calculatePos2DFromHUDOperator;
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ void TriangleSet::clear() {
|
|||
_bounds.clear();
|
||||
_isBalanced = false;
|
||||
|
||||
_triangleOctree.clear();
|
||||
_triangleTree.clear();
|
||||
}
|
||||
|
||||
bool TriangleSet::convexHullContains(const glm::vec3& point) const {
|
||||
|
@ -53,16 +53,16 @@ void TriangleSet::debugDump() {
|
|||
qDebug() << __FUNCTION__;
|
||||
qDebug() << "bounds:" << getBounds();
|
||||
qDebug() << "triangles:" << size() << "at top level....";
|
||||
qDebug() << "----- _triangleOctree -----";
|
||||
_triangleOctree.debugDump();
|
||||
qDebug() << "----- _triangleTree -----";
|
||||
_triangleTree.debugDump();
|
||||
}
|
||||
|
||||
void TriangleSet::balanceOctree() {
|
||||
_triangleOctree.reset(_bounds);
|
||||
void TriangleSet::balanceTree() {
|
||||
_triangleTree.reset(_bounds);
|
||||
|
||||
// insert all the triangles
|
||||
for (size_t i = 0; i < _triangles.size(); i++) {
|
||||
_triangleOctree.insert(i);
|
||||
_triangleTree.insert(i);
|
||||
}
|
||||
|
||||
_isBalanced = true;
|
||||
|
@ -77,13 +77,13 @@ void TriangleSet::balanceOctree() {
|
|||
// With a k-d tree: 2 ^ MAX_DEPTH = 4096 leaves
|
||||
static const int MAX_DEPTH = 12;
|
||||
|
||||
TriangleSet::TriangleOctreeCell::TriangleOctreeCell(std::vector<Triangle>& allTriangles, const AABox& bounds, int depth) :
|
||||
TriangleSet::TriangleTreeCell::TriangleTreeCell(std::vector<Triangle>& allTriangles, const AABox& bounds, int depth) :
|
||||
_allTriangles(allTriangles)
|
||||
{
|
||||
reset(bounds, depth);
|
||||
}
|
||||
|
||||
void TriangleSet::TriangleOctreeCell::clear() {
|
||||
void TriangleSet::TriangleTreeCell::clear() {
|
||||
_population = 0;
|
||||
_triangleIndices.clear();
|
||||
_bounds.clear();
|
||||
|
@ -91,13 +91,13 @@ void TriangleSet::TriangleOctreeCell::clear() {
|
|||
_children.second.reset();
|
||||
}
|
||||
|
||||
void TriangleSet::TriangleOctreeCell::reset(const AABox& bounds, int depth) {
|
||||
void TriangleSet::TriangleTreeCell::reset(const AABox& bounds, int depth) {
|
||||
clear();
|
||||
_bounds = bounds;
|
||||
_depth = depth;
|
||||
}
|
||||
|
||||
void TriangleSet::TriangleOctreeCell::debugDump() {
|
||||
void TriangleSet::TriangleTreeCell::debugDump() {
|
||||
qDebug() << __FUNCTION__;
|
||||
qDebug() << " bounds:" << getBounds();
|
||||
qDebug() << " depth:" << _depth;
|
||||
|
@ -123,7 +123,7 @@ void TriangleSet::TriangleOctreeCell::debugDump() {
|
|||
}
|
||||
}
|
||||
|
||||
std::pair<AABox, AABox> TriangleSet::TriangleOctreeCell::getTriangleOctreeCellChildBounds() {
|
||||
std::pair<AABox, AABox> TriangleSet::TriangleTreeCell::getTriangleTreeCellChildBounds() {
|
||||
std::pair<AABox, AABox> toReturn;
|
||||
int axis = 0;
|
||||
// find biggest axis
|
||||
|
@ -145,20 +145,20 @@ std::pair<AABox, AABox> TriangleSet::TriangleOctreeCell::getTriangleOctreeCellCh
|
|||
return toReturn;
|
||||
}
|
||||
|
||||
void TriangleSet::TriangleOctreeCell::insert(size_t triangleIndex) {
|
||||
void TriangleSet::TriangleTreeCell::insert(size_t triangleIndex) {
|
||||
_population++;
|
||||
|
||||
// if we're not yet at the max depth, then check which child the triangle fits in
|
||||
if (_depth < MAX_DEPTH) {
|
||||
const Triangle& triangle = _allTriangles[triangleIndex];
|
||||
auto childBounds = getTriangleOctreeCellChildBounds();
|
||||
auto childBounds = getTriangleTreeCellChildBounds();
|
||||
|
||||
auto insertOperator = [&](const AABox& childBound, std::shared_ptr<TriangleOctreeCell>& child) {
|
||||
auto insertOperator = [&](const AABox& childBound, std::shared_ptr<TriangleTreeCell>& child) {
|
||||
// if the child AABox would contain the triangle...
|
||||
if (childBound.contains(triangle)) {
|
||||
// if the child cell doesn't yet exist, create it...
|
||||
if (!child) {
|
||||
child = std::make_shared<TriangleOctreeCell>(_allTriangles, childBound, _depth + 1);
|
||||
child = std::make_shared<TriangleTreeCell>(_allTriangles, childBound, _depth + 1);
|
||||
}
|
||||
|
||||
// insert the triangleIndex in the child cell
|
||||
|
@ -179,19 +179,19 @@ void TriangleSet::TriangleOctreeCell::insert(size_t triangleIndex) {
|
|||
bool TriangleSet::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||
BoxFace& face, Triangle& triangle, bool precision, bool allowBackface) {
|
||||
if (!_isBalanced) {
|
||||
balanceOctree();
|
||||
balanceTree();
|
||||
}
|
||||
|
||||
float localDistance = distance;
|
||||
int trianglesTouched = 0;
|
||||
bool hit = _triangleOctree.findRayIntersection(origin, direction, localDistance, face, triangle, precision, trianglesTouched, allowBackface);
|
||||
bool hit = _triangleTree.findRayIntersection(origin, direction, localDistance, face, triangle, precision, trianglesTouched, allowBackface);
|
||||
if (hit) {
|
||||
distance = localDistance;
|
||||
}
|
||||
|
||||
#if WANT_DEBUGGING
|
||||
if (precision) {
|
||||
qDebug() << "trianglesTouched :" << trianglesTouched << "out of:" << _triangleOctree._population << "_triangles.size:" << _triangles.size();
|
||||
qDebug() << "trianglesTouched :" << trianglesTouched << "out of:" << _triangleTree._population << "_triangles.size:" << _triangles.size();
|
||||
}
|
||||
#endif
|
||||
return hit;
|
||||
|
@ -199,7 +199,7 @@ bool TriangleSet::findRayIntersection(const glm::vec3& origin, const glm::vec3&
|
|||
|
||||
// Determine of the given ray (origin/direction) in model space intersects with any triangles
|
||||
// in the set. If an intersection occurs, the distance and surface normal will be provided.
|
||||
bool TriangleSet::TriangleOctreeCell::findRayIntersectionInternal(const glm::vec3& origin, const glm::vec3& direction,
|
||||
bool TriangleSet::TriangleTreeCell::findRayIntersectionInternal(const glm::vec3& origin, const glm::vec3& direction,
|
||||
float& distance, BoxFace& face, Triangle& triangle, bool precision,
|
||||
int& trianglesTouched, bool allowBackface) {
|
||||
bool intersectedSomething = false;
|
||||
|
@ -232,7 +232,7 @@ bool TriangleSet::TriangleOctreeCell::findRayIntersectionInternal(const glm::vec
|
|||
return intersectedSomething;
|
||||
}
|
||||
|
||||
bool TriangleSet::TriangleOctreeCell::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||
bool TriangleSet::TriangleTreeCell::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||
BoxFace& face, Triangle& triangle, bool precision, int& trianglesTouched,
|
||||
bool allowBackface) {
|
||||
if (_population < 1) {
|
||||
|
@ -261,7 +261,7 @@ bool TriangleSet::TriangleOctreeCell::findRayIntersection(const glm::vec3& origi
|
|||
// if we're not yet at the max depth, then check our children
|
||||
if (_depth < MAX_DEPTH) {
|
||||
std::list<SortedTriangleCell> sortedTriangleCells;
|
||||
auto sortingOperator = [&](std::shared_ptr<TriangleOctreeCell>& child) {
|
||||
auto sortingOperator = [&](std::shared_ptr<TriangleTreeCell>& child) {
|
||||
if (child) {
|
||||
float priority = FLT_MAX;
|
||||
if (child->getBounds().contains(origin)) {
|
||||
|
@ -328,25 +328,25 @@ bool TriangleSet::TriangleOctreeCell::findRayIntersection(const glm::vec3& origi
|
|||
bool TriangleSet::findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration,
|
||||
float& parabolicDistance, BoxFace& face, Triangle& triangle, bool precision, bool allowBackface) {
|
||||
if (!_isBalanced) {
|
||||
balanceOctree();
|
||||
balanceTree();
|
||||
}
|
||||
|
||||
float localDistance = parabolicDistance;
|
||||
int trianglesTouched = 0;
|
||||
bool hit = _triangleOctree.findParabolaIntersection(origin, velocity, acceleration, localDistance, face, triangle, precision, trianglesTouched, allowBackface);
|
||||
bool hit = _triangleTree.findParabolaIntersection(origin, velocity, acceleration, localDistance, face, triangle, precision, trianglesTouched, allowBackface);
|
||||
if (hit) {
|
||||
parabolicDistance = localDistance;
|
||||
}
|
||||
|
||||
#if WANT_DEBUGGING
|
||||
if (precision) {
|
||||
qDebug() << "trianglesTouched :" << trianglesTouched << "out of:" << _triangleOctree._population << "_triangles.size:" << _triangles.size();
|
||||
qDebug() << "trianglesTouched :" << trianglesTouched << "out of:" << _triangleTree._population << "_triangles.size:" << _triangles.size();
|
||||
}
|
||||
#endif
|
||||
return hit;
|
||||
}
|
||||
|
||||
bool TriangleSet::TriangleOctreeCell::findParabolaIntersectionInternal(const glm::vec3& origin, const glm::vec3& velocity,
|
||||
bool TriangleSet::TriangleTreeCell::findParabolaIntersectionInternal(const glm::vec3& origin, const glm::vec3& velocity,
|
||||
const glm::vec3& acceleration, float& parabolicDistance,
|
||||
BoxFace& face, Triangle& triangle, bool precision,
|
||||
int& trianglesTouched, bool allowBackface) {
|
||||
|
@ -380,7 +380,7 @@ bool TriangleSet::TriangleOctreeCell::findParabolaIntersectionInternal(const glm
|
|||
return intersectedSomething;
|
||||
}
|
||||
|
||||
bool TriangleSet::TriangleOctreeCell::findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity,
|
||||
bool TriangleSet::TriangleTreeCell::findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity,
|
||||
const glm::vec3& acceleration, float& parabolicDistance,
|
||||
BoxFace& face, Triangle& triangle, bool precision,
|
||||
int& trianglesTouched, bool allowBackface) {
|
||||
|
@ -410,7 +410,7 @@ bool TriangleSet::TriangleOctreeCell::findParabolaIntersection(const glm::vec3&
|
|||
// if we're not yet at the max depth, then check our children
|
||||
if (_depth < MAX_DEPTH) {
|
||||
std::list<SortedTriangleCell> sortedTriangleCells;
|
||||
auto sortingOperator = [&](std::shared_ptr<TriangleOctreeCell>& child) {
|
||||
auto sortingOperator = [&](std::shared_ptr<TriangleTreeCell>& child) {
|
||||
if (child) {
|
||||
float priority = FLT_MAX;
|
||||
if (child->getBounds().contains(origin)) {
|
||||
|
|
|
@ -19,10 +19,10 @@
|
|||
|
||||
class TriangleSet {
|
||||
|
||||
class TriangleOctreeCell {
|
||||
class TriangleTreeCell {
|
||||
public:
|
||||
TriangleOctreeCell(std::vector<Triangle>& allTriangles) : _allTriangles(allTriangles) {}
|
||||
TriangleOctreeCell(std::vector<Triangle>& allTriangles, const AABox& bounds, int depth);
|
||||
TriangleTreeCell(std::vector<Triangle>& allTriangles) : _allTriangles(allTriangles) {}
|
||||
TriangleTreeCell(std::vector<Triangle>& allTriangles, const AABox& bounds, int depth);
|
||||
|
||||
void insert(size_t triangleIndex);
|
||||
void reset(const AABox& bounds, int depth = 0);
|
||||
|
@ -48,10 +48,10 @@ class TriangleSet {
|
|||
float& parabolicDistance, BoxFace& face, Triangle& triangle, bool precision, int& trianglesTouched,
|
||||
bool allowBackface = false);
|
||||
|
||||
std::pair<AABox, AABox> getTriangleOctreeCellChildBounds();
|
||||
std::pair<AABox, AABox> getTriangleTreeCellChildBounds();
|
||||
|
||||
std::vector<Triangle>& _allTriangles;
|
||||
std::pair<std::shared_ptr<TriangleOctreeCell>, std::shared_ptr<TriangleOctreeCell>> _children;
|
||||
std::pair<std::shared_ptr<TriangleTreeCell>, std::shared_ptr<TriangleTreeCell>> _children;
|
||||
int _depth { 0 };
|
||||
int _population { 0 };
|
||||
AABox _bounds;
|
||||
|
@ -60,10 +60,10 @@ class TriangleSet {
|
|||
friend class TriangleSet;
|
||||
};
|
||||
|
||||
using SortedTriangleCell = std::pair<float, std::shared_ptr<TriangleOctreeCell>>;
|
||||
using SortedTriangleCell = std::pair<float, std::shared_ptr<TriangleTreeCell>>;
|
||||
|
||||
public:
|
||||
TriangleSet() : _triangleOctree(_triangles) {}
|
||||
TriangleSet() : _triangleTree(_triangles) {}
|
||||
|
||||
void debugDump();
|
||||
|
||||
|
@ -74,7 +74,7 @@ public:
|
|||
bool findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration,
|
||||
float& parabolicDistance, BoxFace& face, Triangle& triangle, bool precision, bool allowBackface = false);
|
||||
|
||||
void balanceOctree();
|
||||
void balanceTree();
|
||||
|
||||
void reserve(size_t size) { _triangles.reserve(size); } // reserve space in the datastructure for size number of triangles
|
||||
size_t size() const { return _triangles.size(); }
|
||||
|
@ -89,6 +89,6 @@ public:
|
|||
protected:
|
||||
bool _isBalanced { false };
|
||||
std::vector<Triangle> _triangles;
|
||||
TriangleOctreeCell _triangleOctree;
|
||||
TriangleTreeCell _triangleTree;
|
||||
AABox _bounds;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue