CR improvements

This commit is contained in:
SamGondelman 2018-07-26 12:15:12 -07:00
parent 9b41cb5554
commit 6a52b7b8f3
7 changed files with 55 additions and 55 deletions

View file

@ -15,40 +15,46 @@
#include "DependencyManager.h"
PickResultPointer ParabolaPick::getEntityIntersection(const PickParabola& pick) {
ParabolaToEntityIntersectionResult entityRes =
DependencyManager::get<EntityScriptingInterface>()->findParabolaIntersectionVector(pick, !getFilter().doesPickCoarse(),
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);
} else {
return std::make_shared<ParabolaPickResult>(pick.toVariantMap());
if (glm::length2(pick.acceleration) > EPSILON && glm::length2(pick.velocity) > EPSILON) {
ParabolaToEntityIntersectionResult entityRes =
DependencyManager::get<EntityScriptingInterface>()->findParabolaIntersectionVector(pick, !getFilter().doesPickCoarse(),
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);
}
}
return std::make_shared<ParabolaPickResult>(pick.toVariantMap());
}
PickResultPointer ParabolaPick::getOverlayIntersection(const PickParabola& pick) {
ParabolaToOverlayIntersectionResult overlayRes =
qApp->getOverlays().findParabolaIntersectionVector(pick, !getFilter().doesPickCoarse(),
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);
} else {
return std::make_shared<ParabolaPickResult>(pick.toVariantMap());
if (glm::length2(pick.acceleration) > EPSILON && glm::length2(pick.velocity) > EPSILON) {
ParabolaToOverlayIntersectionResult overlayRes =
qApp->getOverlays().findParabolaIntersectionVector(pick, !getFilter().doesPickCoarse(),
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);
}
}
return std::make_shared<ParabolaPickResult>(pick.toVariantMap());
}
PickResultPointer ParabolaPick::getAvatarIntersection(const PickParabola& pick) {
ParabolaToAvatarIntersectionResult avatarRes = DependencyManager::get<AvatarManager>()->findParabolaIntersectionVector(pick, getIncludeItemsAs<EntityItemID>(), getIgnoreItemsAs<EntityItemID>());
if (avatarRes.intersects) {
return std::make_shared<ParabolaPickResult>(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.parabolicDistance, avatarRes.intersection, pick, avatarRes.surfaceNormal, avatarRes.extraInfo);
} else {
return std::make_shared<ParabolaPickResult>(pick.toVariantMap());
if (glm::length2(pick.acceleration) > EPSILON && glm::length2(pick.velocity) > EPSILON) {
ParabolaToAvatarIntersectionResult avatarRes = DependencyManager::get<AvatarManager>()->findParabolaIntersectionVector(pick, getIncludeItemsAs<EntityItemID>(), getIgnoreItemsAs<EntityItemID>());
if (avatarRes.intersects) {
return std::make_shared<ParabolaPickResult>(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.parabolicDistance, avatarRes.intersection, pick, avatarRes.surfaceNormal, avatarRes.extraInfo);
}
}
return std::make_shared<ParabolaPickResult>(pick.toVariantMap());
}
PickResultPointer ParabolaPick::getHUDIntersection(const PickParabola& pick) {
float parabolicDistance;
glm::vec3 hudRes = DependencyManager::get<HMDScriptingInterface>()->calculateParabolaUICollisionPoint(pick.origin, pick.velocity, pick.acceleration, parabolicDistance);
return std::make_shared<ParabolaPickResult>(IntersectionType::HUD, QUuid(), glm::distance(pick.origin, hudRes), parabolicDistance, hudRes, pick);
if (glm::length2(pick.acceleration) > EPSILON && glm::length2(pick.velocity) > EPSILON) {
float parabolicDistance;
glm::vec3 hudRes = DependencyManager::get<HMDScriptingInterface>()->calculateParabolaUICollisionPoint(pick.origin, pick.velocity, pick.acceleration, parabolicDistance);
return std::make_shared<ParabolaPickResult>(IntersectionType::HUD, QUuid(), glm::distance(pick.origin, hudRes), parabolicDistance, hudRes, pick);
}
return std::make_shared<ParabolaPickResult>(pick.toVariantMap());
}
float ParabolaPick::getSpeed() const {

View file

@ -88,7 +88,12 @@ bool Volume3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::ve
// we can use the AABox's ray intersection by mapping our origin and direction into the overlays frame
// and testing intersection there.
return _localBoundingBox.findRayIntersection(overlayFrameOrigin, overlayFrameDirection, distance, face, surfaceNormal);
bool hit = _localBoundingBox.findRayIntersection(overlayFrameOrigin, overlayFrameDirection, distance, face, surfaceNormal);
if (hit) {
surfaceNormal = transform.getRotation() * surfaceNormal;
}
return hit;
}
bool Volume3DOverlay::findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration,

View file

@ -316,7 +316,16 @@ EntityItemID EntityTreeElement::findParabolaIntersection(const glm::vec3& origin
// for any details inside the cube to be closer so we don't need to consider them.
QVariantMap localExtraInfo;
float distanceToElementDetails = parabolicDistance;
EntityItemID entityID = findDetailedParabolaIntersection(origin, velocity, acceleration, element, distanceToElementDetails,
// We can precompute the world-space parabola normal and reuse it for the parabola plane intersects AABox sphere check
glm::vec3 vectorOnPlane = velocity;
if (glm::dot(glm::normalize(velocity), glm::normalize(acceleration)) > 1.0f - EPSILON) {
// Handle the degenerate case where velocity is parallel to acceleration
// We pick t = 1 and calculate a second point on the plane
vectorOnPlane = velocity + 0.5f * acceleration;
}
// Get the normal of the plane, the cross product of two vectors on the plane
glm::vec3 normal = glm::normalize(glm::cross(vectorOnPlane, acceleration));
EntityItemID entityID = findDetailedParabolaIntersection(origin, velocity, acceleration, normal, element, distanceToElementDetails,
localFace, localSurfaceNormal, entityIdsToInclude, entityIdsToDiscard, visibleOnly, collidableOnly,
localExtraInfo, precisionPicking);
if (!entityID.isNull() && distanceToElementDetails < parabolicDistance) {
@ -330,7 +339,7 @@ EntityItemID EntityTreeElement::findParabolaIntersection(const glm::vec3& origin
}
EntityItemID EntityTreeElement::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration,
OctreeElementPointer& element, float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal,
const glm::vec3& normal, OctreeElementPointer& element, float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal,
const QVector<EntityItemID>& entityIdsToInclude, const QVector<EntityItemID>& entityIDsToDiscard,
bool visibleOnly, bool collidableOnly, QVariantMap& extraInfo, bool precisionPicking) {
@ -350,7 +359,7 @@ EntityItemID EntityTreeElement::findDetailedParabolaIntersection(const glm::vec3
// defined by the parabola slices the sphere. The solution to parabolaIntersectsBoundingSphere is cubic,
// the solution to which is more computationally expensive than the quadratic AABox::findParabolaIntersection
// below
if (!entityBox.parabolaPlaneIntersectsBoundingSphere(origin, velocity, acceleration)) {
if (!entityBox.parabolaPlaneIntersectsBoundingSphere(origin, velocity, acceleration, normal)) {
return;
}

View file

@ -154,7 +154,7 @@ public:
const QVector<EntityItemID>& entityIdsToDiscard, bool visibleOnly, bool collidableOnly,
QVariantMap& extraInfo, bool precisionPicking = false);
virtual EntityItemID findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity,
const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance,
const glm::vec3& normal, const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance,
BoxFace& face, glm::vec3& surfaceNormal, const QVector<EntityItemID>& entityIdsToInclude,
const QVector<EntityItemID>& entityIdsToDiscard, bool visibleOnly, bool collidableOnly,
QVariantMap& extraInfo, bool precisionPicking);

View file

@ -211,7 +211,7 @@ bool AABox::rayHitsBoundingSphere(const glm::vec3& origin, const glm::vec3& dire
|| (glm::abs(distance) > 0.0f && glm::distance2(distance * direction, localCenter) < radiusSquared));
}
bool AABox::parabolaPlaneIntersectsBoundingSphere(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration) const {
bool AABox::parabolaPlaneIntersectsBoundingSphere(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, const glm::vec3& normal) const {
glm::vec3 localCenter = calcCenter() - origin;
const float ONE_OVER_TWO_SQUARED = 0.25f;
float radiusSquared = ONE_OVER_TWO_SQUARED * glm::length2(_scale);
@ -221,24 +221,10 @@ bool AABox::parabolaPlaneIntersectsBoundingSphere(const glm::vec3& origin, const
return true;
}
float velocityLength2 = glm::length2(velocity);
if (glm::length2(acceleration) < EPSILON) {
if (velocityLength2 < EPSILON) {
// No intersection if velocity == acceleration == (0, 0, 0)
return false;
}
// Handle the degenerate case where acceleration == (0, 0, 0)
return rayHitsBoundingSphere(origin, glm::normalize(velocity));
} else {
glm::vec3 vectorOnPlane = velocity;
if (glm::dot(glm::normalize(velocity), glm::normalize(acceleration)) > 1.0f - EPSILON) {
// Handle the degenerate case where velocity is parallel to acceleration
// We pick t = 1 and calculate a second point on the plane
vectorOnPlane = velocity + 0.5f * acceleration;
}
// Get the normal of the plane, the cross product of two vectors on the plane
glm::vec3 normal = glm::normalize(glm::cross(vectorOnPlane, acceleration));
// Project vector from plane to sphere center onto the normal
float distance = glm::dot(localCenter, normal);
if (distance * distance < radiusSquared) {

View file

@ -74,7 +74,7 @@ public:
bool findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration,
float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal) const;
bool rayHitsBoundingSphere(const glm::vec3& origin, const glm::vec3& direction) const;
bool parabolaPlaneIntersectsBoundingSphere(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration) const;
bool parabolaPlaneIntersectsBoundingSphere(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, const glm::vec3& normal) const;
bool touchesSphere(const glm::vec3& center, float radius) const; // fast but may generate false positives
bool touchesAAEllipsoid(const glm::vec3& center, const glm::vec3& radials) const;
bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) const;

View file

@ -829,8 +829,8 @@ bool findParabolaRectangleIntersection(const glm::vec3& origin, const glm::vec3&
float minDistance = FLT_MAX;
if (fabsf(acceleration.z) < EPSILON) {
// Handle the degenerate case where we only have a line in the z-axis
if (fabsf(velocity.z) > EPSILON) {
// Handle the degenerate case where we only have a line in the z-axis
float possibleDistance = -origin.z / velocity.z;
checkPossibleParabolicIntersectionWithZPlane(possibleDistance, minDistance, origin, velocity, acceleration, localCorner, dimensions);
}
@ -853,19 +853,14 @@ bool findParabolaRectangleIntersection(const glm::vec3& origin, const glm::vec3&
}
bool findParabolaSphereIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration,
const glm::vec3& center, float radius, float& parabolicDistance) {
const glm::vec3& center, float radius, float& parabolicDistance) {
glm::vec3 localCenter = center - origin;
float radiusSquared = radius * radius;
float velocityLength2 = glm::length2(velocity);
float accelerationLength = glm::length(acceleration);
float minDistance = FLT_MAX;
if (accelerationLength < EPSILON) {
if (velocityLength2 < EPSILON) {
// No intersection if velocity == acceleration == (0, 0, 0)
return false;
}
// Handle the degenerate case where acceleration == (0, 0, 0)
glm::vec3 offset = origin - center;
float a = glm::dot(velocity, velocity);
@ -971,12 +966,11 @@ bool findParabolaTriangleIntersection(const glm::vec3& origin, const glm::vec3&
float minDistance = FLT_MAX;
if (fabsf(localAcceleration.z) < EPSILON) {
if (fabsf(localVelocity.z) < EPSILON) {
return false;
if (fabsf(localVelocity.z) > EPSILON) {
float possibleDistance = -localOrigin.z / localVelocity.z;
checkPossibleParabolicIntersectionWithTriangle(possibleDistance, minDistance, origin, velocity, acceleration,
localVelocity, localAcceleration, normal, v0, v1, v2, allowBackface);
}
float possibleDistance = -localOrigin.z / localVelocity.z;
checkPossibleParabolicIntersectionWithTriangle(possibleDistance, minDistance, origin, velocity, acceleration,
localVelocity, localAcceleration, normal, v0, v1, v2, allowBackface);
} else {
float a = 0.5f * localAcceleration.z;
float b = localVelocity.z;