mirror of
https://github.com/lubosz/overte.git
synced 2025-08-28 07:36:24 +02:00
Add RayIntersectionInfo and use for shape-vs-ray
This commit is contained in:
parent
c9d5508f16
commit
4da1ca22ba
19 changed files with 222 additions and 197 deletions
|
@ -2468,9 +2468,9 @@ void StaticModelRenderer::renderUnclipped(float alpha, Mode mode) {
|
|||
_model->render(alpha);
|
||||
}
|
||||
|
||||
bool StaticModelRenderer::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const glm::vec3& clipMinimum, float clipSize, float& distance) const {
|
||||
return _model->findRayIntersection(origin, direction, distance);
|
||||
bool StaticModelRenderer::findRayIntersection(RayIntersectionInfo& intersection,
|
||||
const glm::vec3& clipMinimum, float clipSize) const {
|
||||
return _model->findRayIntersection(intersection);
|
||||
}
|
||||
|
||||
void StaticModelRenderer::applyTranslation(const glm::vec3& translation) {
|
||||
|
|
|
@ -392,8 +392,8 @@ public:
|
|||
|
||||
virtual void init(Spanner* spanner);
|
||||
virtual void simulate(float deltaTime);
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const glm::vec3& clipMinimum, float clipSize, float& distance) const;
|
||||
virtual bool findRayIntersection(RayIntersectionInfo& intersection,
|
||||
const glm::vec3& clipMinimum, float clipSize) const;
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
@ -708,20 +708,10 @@ void Avatar::renderDisplayName() {
|
|||
glEnable(GL_LIGHTING);
|
||||
}
|
||||
|
||||
bool Avatar::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const {
|
||||
float minDistance = FLT_MAX;
|
||||
float modelDistance;
|
||||
if (_skeletonModel.findRayIntersection(origin, direction, modelDistance)) {
|
||||
minDistance = qMin(minDistance, modelDistance);
|
||||
}
|
||||
if (getHead()->getFaceModel().findRayIntersection(origin, direction, modelDistance)) {
|
||||
minDistance = qMin(minDistance, modelDistance);
|
||||
}
|
||||
if (minDistance < FLT_MAX) {
|
||||
distance = minDistance;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
bool Avatar::findRayIntersection(RayIntersectionInfo& intersection) const {
|
||||
bool hit = _skeletonModel.findRayIntersection(intersection);
|
||||
hit = getHead()->getFaceModel().findRayIntersection(intersection) || hit;
|
||||
return hit;
|
||||
}
|
||||
|
||||
bool Avatar::findSphereCollisions(const glm::vec3& penetratorCenter, float penetratorRadius, CollisionList& collisions) {
|
||||
|
|
|
@ -99,7 +99,7 @@ public:
|
|||
/// Returns the distance to use as a LOD parameter.
|
||||
float getLODDistance() const;
|
||||
|
||||
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
|
||||
bool findRayIntersection(RayIntersectionInfo& intersection) const;
|
||||
|
||||
/// \param shapes list of shapes to collide against avatar
|
||||
/// \param collisions list to store collision results
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "AACubeShape.h"
|
||||
|
||||
bool AACubeShape::findRayIntersection(const glm::vec3& rayStart, const glm::vec3& rayDirection, float& distance) const {
|
||||
bool AACubeShape::findRayIntersection(RayIntersectionInfo& intersection) const {
|
||||
// TODO: Andrew to implement this
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ public:
|
|||
float getScale() const { return _scale; }
|
||||
void setScale(float scale) { _scale = scale; }
|
||||
|
||||
bool findRayIntersection(const glm::vec3& rayStart, const glm::vec3& rayDirection, float& distance) const;
|
||||
bool findRayIntersection(RayIntersectionInfo& intersection) const;
|
||||
|
||||
float getVolume() const { return _scale * _scale * _scale; }
|
||||
|
||||
|
|
|
@ -78,13 +78,9 @@ void CapsuleShape::setEndPoints(const glm::vec3& startPoint, const glm::vec3& en
|
|||
updateBoundingRadius();
|
||||
}
|
||||
|
||||
bool CapsuleShape::findRayIntersection(const glm::vec3& rayStart, const glm::vec3& rayDirection, float& distance) const {
|
||||
glm::vec3 capsuleStart, capsuleEnd;
|
||||
getStartPoint(capsuleStart);
|
||||
getEndPoint(capsuleEnd);
|
||||
// NOTE: findRayCapsuleIntersection returns 'true' with distance = 0 when rayStart is inside capsule.
|
||||
// TODO: implement the raycast to return inside surface intersection for the internal rayStart.
|
||||
return findRayCapsuleIntersection(rayStart, rayDirection, capsuleStart, capsuleEnd, _radius, distance);
|
||||
bool CapsuleShape::findRayIntersection(RayIntersectionInfo& intersection) const {
|
||||
// TODO: Andrew to implement this
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -47,7 +47,7 @@ public:
|
|||
/// Sets the endpoints and updates center, rotation, and halfHeight to agree.
|
||||
virtual void setEndPoints(const glm::vec3& startPoint, const glm::vec3& endPoint);
|
||||
|
||||
bool findRayIntersection(const glm::vec3& rayStart, const glm::vec3& rayDirection, float& distance) const;
|
||||
bool findRayIntersection(RayIntersectionInfo& intersection) const;
|
||||
|
||||
virtual float getVolume() const { return (PI * _radius * _radius) * (1.3333333333f * _radius + getHalfHeight()); }
|
||||
|
||||
|
|
|
@ -76,23 +76,8 @@ void PhysicsEntity::clearShapes() {
|
|||
_shapes.clear();
|
||||
}
|
||||
|
||||
bool PhysicsEntity::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const {
|
||||
int numShapes = _shapes.size();
|
||||
float minDistance = FLT_MAX;
|
||||
for (int j = 0; j < numShapes; ++j) {
|
||||
const Shape* shape = _shapes[j];
|
||||
float thisDistance = FLT_MAX;
|
||||
if (shape && shape->findRayIntersection(origin, direction, thisDistance)) {
|
||||
if (thisDistance < minDistance) {
|
||||
minDistance = thisDistance;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (minDistance < FLT_MAX) {
|
||||
distance = minDistance;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
bool PhysicsEntity::findRayIntersection(RayIntersectionInfo& intersection) const {
|
||||
return ShapeCollider::findRayIntersection(_shapes, intersection);
|
||||
}
|
||||
|
||||
bool PhysicsEntity::findCollisions(const QVector<const Shape*> shapes, CollisionList& collisions) {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
#include "CollisionInfo.h"
|
||||
#include "RayIntersectionInfo.h"
|
||||
|
||||
class Shape;
|
||||
class PhysicsSimulation;
|
||||
|
@ -52,7 +53,7 @@ public:
|
|||
|
||||
PhysicsSimulation* getSimulation() const { return _simulation; }
|
||||
|
||||
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
|
||||
bool findRayIntersection(RayIntersectionInfo& intersection) const;
|
||||
bool findCollisions(const QVector<const Shape*> shapes, CollisionList& collisions);
|
||||
bool findSphereCollisions(const glm::vec3& sphereCenter, float sphereRadius, CollisionList& collisions);
|
||||
bool findPlaneCollisions(const glm::vec4& plane, CollisionList& collisions);
|
||||
|
|
|
@ -39,17 +39,23 @@ glm::vec4 PlaneShape::getCoefficients() const {
|
|||
return glm::vec4(normal.x, normal.y, normal.z, -glm::dot(normal, _translation));
|
||||
}
|
||||
|
||||
bool PlaneShape::findRayIntersection(const glm::vec3& rayStart, const glm::vec3& rayDirection, float& distance) const {
|
||||
bool PlaneShape::findRayIntersection(RayIntersectionInfo& intersection) const {
|
||||
glm::vec3 n = getNormal();
|
||||
float denominator = glm::dot(n, rayDirection);
|
||||
float denominator = glm::dot(n, intersection._rayDirection);
|
||||
if (fabsf(denominator) < EPSILON) {
|
||||
// line is parallel to plane
|
||||
return glm::dot(_translation - rayStart, n) < EPSILON;
|
||||
if (glm::dot(_translation - intersection._rayStart, n) < EPSILON) {
|
||||
// ray starts on the plane
|
||||
intersection._hitDistance = 0.0f;
|
||||
intersection._hitNormal = n;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
float d = glm::dot(_translation - rayStart, n) / denominator;
|
||||
if (d > 0.0f) {
|
||||
float d = glm::dot(_translation - intersection._rayStart, n) / denominator;
|
||||
if (d > 0.0f && d < intersection._rayLength && intersection._hitDistance) {
|
||||
// ray points toward plane
|
||||
distance = d;
|
||||
intersection._hitDistance = d;
|
||||
intersection._hitNormal = n;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ public:
|
|||
glm::vec3 getNormal() const;
|
||||
glm::vec4 getCoefficients() const;
|
||||
|
||||
bool findRayIntersection(const glm::vec3& rayStart, const glm::vec3& rayDirection, float& distance) const;
|
||||
bool findRayIntersection(RayIntersectionInfo& intersection) const;
|
||||
};
|
||||
|
||||
#endif // hifi_PlaneShape_h
|
||||
|
|
35
libraries/shared/src/RayIntersectionInfo.h
Normal file
35
libraries/shared/src/RayIntersectionInfo.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// RayIntersectionInfo.h
|
||||
// interface/src/avatar
|
||||
//
|
||||
// Created by Andrew Meadows 2014.09.09
|
||||
// Copyright 2014 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_RayIntersectionInfo_h
|
||||
#define hifi_RayIntersectionInfo_h
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
class Shape;
|
||||
|
||||
class RayIntersectionInfo {
|
||||
public:
|
||||
RayIntersectionInfo() : _rayStart(0.0f), _rayDirection(1.0f, 0.0f, 0.0f), _rayLength(FLT_MAX),
|
||||
_hitDistance(FLT_MAX), _hitNormal(1.0f, 0.0f, 0.0f), _hitShape(NULL) { }
|
||||
|
||||
// input
|
||||
glm::vec3 _rayStart;
|
||||
glm::vec3 _rayDirection;
|
||||
float _rayLength;
|
||||
|
||||
// output
|
||||
float _hitDistance;
|
||||
glm::vec3 _hitNormal;
|
||||
Shape* _hitShape;
|
||||
};
|
||||
|
||||
#endif // hifi_RayIntersectionInfo_h
|
|
@ -17,6 +17,8 @@
|
|||
#include <QtGlobal>
|
||||
#include <QVector>
|
||||
|
||||
#include "RayIntersectionInfo.h"
|
||||
|
||||
class PhysicsEntity;
|
||||
class VerletPoint;
|
||||
|
||||
|
@ -59,7 +61,7 @@ public:
|
|||
virtual void setMass(float mass) { _mass = mass; }
|
||||
virtual float getMass() const { return _mass; }
|
||||
|
||||
virtual bool findRayIntersection(const glm::vec3& rayStart, const glm::vec3& rayDirection, float& distance) const = 0;
|
||||
virtual bool findRayIntersection(RayIntersectionInfo& intersection) const = 0;
|
||||
|
||||
/// \param penetration of collision
|
||||
/// \param contactPoint of collision
|
||||
|
|
|
@ -1087,24 +1087,18 @@ bool capsuleVsAACubeLegacy(const CapsuleShape* capsuleA, const glm::vec3& cubeCe
|
|||
return sphereVsAACubeLegacy(nearestApproach, capsuleA->getRadius(), cubeCenter, cubeSide, collisions);
|
||||
}
|
||||
|
||||
bool findRayIntersectionWithShapes(const QVector<Shape*> shapes, const glm::vec3& rayStart, const glm::vec3& rayDirection, float& minDistance) {
|
||||
float hitDistance = FLT_MAX;
|
||||
bool findRayIntersection(const QVector<Shape*>& shapes, RayIntersectionInfo& intersection) {
|
||||
int numShapes = shapes.size();
|
||||
bool hit = false;
|
||||
for (int i = 0; i < numShapes; ++i) {
|
||||
Shape* shape = shapes.at(i);
|
||||
if (shape) {
|
||||
float distance;
|
||||
if (shape->findRayIntersection(rayStart, rayDirection, distance)) {
|
||||
if (distance < hitDistance) {
|
||||
hitDistance = distance;
|
||||
}
|
||||
if (shape->findRayIntersection(intersection)) {
|
||||
hit = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hitDistance < FLT_MAX) {
|
||||
minDistance = hitDistance;
|
||||
}
|
||||
return false;
|
||||
return hit;
|
||||
}
|
||||
|
||||
} // namespace ShapeCollider
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <QVector>
|
||||
|
||||
#include "CollisionInfo.h"
|
||||
#include "RayIntersectionInfo.h"
|
||||
#include "SharedUtil.h"
|
||||
|
||||
class Shape;
|
||||
|
@ -145,11 +146,9 @@ namespace ShapeCollider {
|
|||
bool capsuleVsAACubeLegacy(const CapsuleShape* capsuleA, const glm::vec3& cubeCenter, float cubeSide, CollisionList& collisions);
|
||||
|
||||
/// \param shapes list of pointers to shapes (shape pointers may be NULL)
|
||||
/// \param startPoint beginning of ray
|
||||
/// \param direction direction of ray
|
||||
/// \param minDistance[out] shortest distance to intersection of ray with a shapes
|
||||
/// \param intersection[out] struct with info about Ray and hit
|
||||
/// \return true if ray hits any shape in shapes
|
||||
bool findRayIntersectionWithShapes(const QVector<Shape*> shapes, const glm::vec3& startPoint, const glm::vec3& direction, float& minDistance);
|
||||
bool findRayIntersection(const QVector<Shape*>& shapes, RayIntersectionInfo& intersection);
|
||||
|
||||
} // namespace ShapeCollider
|
||||
|
||||
|
|
|
@ -13,18 +13,19 @@
|
|||
|
||||
#include "SphereShape.h"
|
||||
|
||||
bool SphereShape::findRayIntersection(const glm::vec3& rayStart, const glm::vec3& rayDirection, float& distance) const {
|
||||
bool SphereShape::findRayIntersection(RayIntersectionInfo& intersection) const {
|
||||
float r2 = _boundingRadius * _boundingRadius;
|
||||
|
||||
// compute closest approach (CA)
|
||||
float a = glm::dot(_translation - rayStart, rayDirection); // a = distance from ray-start to CA
|
||||
float b2 = glm::distance2(_translation, rayStart + a * rayDirection); // b2 = squared distance from sphere-center to CA
|
||||
float a = glm::dot(_translation - intersection._rayStart, intersection._rayDirection); // a = distance from ray-start to CA
|
||||
float b2 = glm::distance2(_translation, intersection._rayStart + a * intersection._rayDirection); // b2 = squared distance from sphere-center to CA
|
||||
if (b2 > r2) {
|
||||
// ray does not hit sphere
|
||||
return false;
|
||||
}
|
||||
float c = sqrtf(r2 - b2); // c = distance from CA to sphere surface along rayDirection
|
||||
float d2 = glm::distance2(rayStart, _translation); // d2 = squared distance from sphere-center to ray-start
|
||||
float c = sqrtf(r2 - b2); // c = distance from CA to sphere surface along intersection._rayDirection
|
||||
float d2 = glm::distance2(intersection._rayStart, _translation); // d2 = squared distance from sphere-center to ray-start
|
||||
float distance = FLT_MAX;
|
||||
if (a < 0.0f) {
|
||||
// ray points away from sphere-center
|
||||
if (d2 > r2) {
|
||||
|
@ -40,5 +41,10 @@ bool SphereShape::findRayIntersection(const glm::vec3& rayStart, const glm::vec3
|
|||
// ray starts inside sphere
|
||||
distance = a + c;
|
||||
}
|
||||
return true;
|
||||
if (distance > 0.0f && distance < intersection._rayLength && distance < intersection._hitDistance) {
|
||||
intersection._hitDistance = distance;
|
||||
intersection._hitNormal = glm::normalize(intersection._rayStart + distance * intersection._rayDirection - _translation);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ public:
|
|||
|
||||
void setRadius(float radius) { _boundingRadius = radius; }
|
||||
|
||||
bool findRayIntersection(const glm::vec3& rayStart, const glm::vec3& rayDirection, float& distance) const;
|
||||
bool findRayIntersection(RayIntersectionInfo& intersection) const;
|
||||
|
||||
float getVolume() const { return 1.3333333333f * PI * _boundingRadius * _boundingRadius * _boundingRadius; }
|
||||
};
|
||||
|
|
|
@ -1803,23 +1803,23 @@ void ShapeColliderTests::capsuleTouchesAACube() {
|
|||
|
||||
void ShapeColliderTests::rayHitsSphere() {
|
||||
float startDistance = 3.0f;
|
||||
glm::vec3 rayStart(-startDistance, 0.0f, 0.0f);
|
||||
glm::vec3 rayDirection(1.0f, 0.0f, 0.0f);
|
||||
|
||||
float radius = 1.0f;
|
||||
glm::vec3 center(0.0f);
|
||||
|
||||
SphereShape sphere(radius, center);
|
||||
|
||||
// very simple ray along xAxis
|
||||
{
|
||||
float distance = FLT_MAX;
|
||||
if (!sphere.findRayIntersection(rayStart, rayDirection, distance)) {
|
||||
RayIntersectionInfo intersection;
|
||||
intersection._rayStart = glm::vec3(-startDistance, 0.0f, 0.0f);
|
||||
intersection._rayDirection = glm::vec3(1.0f, 0.0f, 0.0f);
|
||||
|
||||
if (!sphere.findRayIntersection(intersection)) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray should intersect sphere" << std::endl;
|
||||
}
|
||||
|
||||
float expectedDistance = startDistance - radius;
|
||||
float relativeError = fabsf(distance - expectedDistance) / startDistance;
|
||||
float relativeError = fabsf(intersection._hitDistance - expectedDistance) / startDistance;
|
||||
if (relativeError > EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray sphere intersection distance error = " << relativeError << std::endl;
|
||||
}
|
||||
|
@ -1827,16 +1827,16 @@ void ShapeColliderTests::rayHitsSphere() {
|
|||
|
||||
// ray along a diagonal axis
|
||||
{
|
||||
rayStart = glm::vec3(startDistance, startDistance, 0.0f);
|
||||
rayDirection = - glm::normalize(rayStart);
|
||||
RayIntersectionInfo intersection;
|
||||
intersection._rayStart = glm::vec3(startDistance, startDistance, 0.0f);
|
||||
intersection._rayDirection = - glm::normalize(intersection._rayStart);
|
||||
|
||||
float distance = FLT_MAX;
|
||||
if (!sphere.findRayIntersection(rayStart, rayDirection, distance)) {
|
||||
if (!sphere.findRayIntersection(intersection)) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray should intersect sphere" << std::endl;
|
||||
}
|
||||
|
||||
float expectedDistance = SQUARE_ROOT_OF_2 * startDistance - radius;
|
||||
float relativeError = fabsf(distance - expectedDistance) / startDistance;
|
||||
float relativeError = fabsf(intersection._hitDistance - expectedDistance) / startDistance;
|
||||
if (relativeError > EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray sphere intersection distance error = " << relativeError << std::endl;
|
||||
}
|
||||
|
@ -1854,19 +1854,19 @@ void ShapeColliderTests::rayHitsSphere() {
|
|||
glm::vec3 unrotatedRayDirection(-1.0f, 0.0f, 0.0f);
|
||||
glm::vec3 untransformedRayStart(startDistance, 0.0f, 0.0f);
|
||||
|
||||
rayStart = rotation * (untransformedRayStart + translation);
|
||||
rayDirection = rotation * unrotatedRayDirection;
|
||||
RayIntersectionInfo intersection;
|
||||
intersection._rayStart = rotation * (untransformedRayStart + translation);
|
||||
intersection._rayDirection = rotation * unrotatedRayDirection;
|
||||
|
||||
sphere.setRadius(radius);
|
||||
sphere.setTranslation(rotation * translation);
|
||||
|
||||
float distance = FLT_MAX;
|
||||
if (!sphere.findRayIntersection(rayStart, rayDirection, distance)) {
|
||||
if (!sphere.findRayIntersection(intersection)) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray should intersect sphere" << std::endl;
|
||||
}
|
||||
|
||||
float expectedDistance = startDistance - radius;
|
||||
float relativeError = fabsf(distance - expectedDistance) / startDistance;
|
||||
float relativeError = fabsf(intersection._hitDistance - expectedDistance) / startDistance;
|
||||
if (relativeError > EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray sphere intersection distance error = "
|
||||
<< relativeError << std::endl;
|
||||
|
@ -1879,31 +1879,36 @@ void ShapeColliderTests::rayBarelyHitsSphere() {
|
|||
glm::vec3 center(0.0f);
|
||||
float delta = 2.0f * EPSILON;
|
||||
|
||||
float startDistance = 3.0f;
|
||||
glm::vec3 rayStart(-startDistance, radius - delta, 0.0f);
|
||||
glm::vec3 rayDirection(1.0f, 0.0f, 0.0f);
|
||||
|
||||
SphereShape sphere(radius, center);
|
||||
float startDistance = 3.0f;
|
||||
|
||||
// very simple ray along xAxis
|
||||
float distance = FLT_MAX;
|
||||
if (!sphere.findRayIntersection(rayStart, rayDirection, distance)) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray should just barely hit sphere" << std::endl;
|
||||
{
|
||||
RayIntersectionInfo intersection;
|
||||
intersection._rayStart = glm::vec3(-startDistance, radius - delta, 0.0f);
|
||||
intersection._rayDirection = glm::vec3(1.0f, 0.0f, 0.0f);
|
||||
|
||||
// very simple ray along xAxis
|
||||
if (!sphere.findRayIntersection(intersection)) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray should just barely hit sphere" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// translate and rotate the whole system...
|
||||
glm::vec3 axis = glm::normalize(glm::vec3(1.0f, 2.0f, 3.0f));
|
||||
glm::quat rotation = glm::angleAxis(0.987654321f, axis);
|
||||
glm::vec3 translation(35.7f, 2.46f, -1.97f);
|
||||
|
||||
rayStart = rotation * (rayStart + translation);
|
||||
rayDirection = rotation * rayDirection;
|
||||
sphere.setTranslation(rotation * translation);
|
||||
|
||||
// ...and test again
|
||||
distance = FLT_MAX;
|
||||
if (!sphere.findRayIntersection(rayStart, rayDirection, distance)) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray should just barely hit sphere" << std::endl;
|
||||
{
|
||||
// translate and rotate the whole system...
|
||||
glm::vec3 axis = glm::normalize(glm::vec3(1.0f, 2.0f, 3.0f));
|
||||
glm::quat rotation = glm::angleAxis(0.987654321f, axis);
|
||||
glm::vec3 translation(1.7f, 0.46f, -1.97f);
|
||||
|
||||
RayIntersectionInfo intersection;
|
||||
intersection._rayStart = rotation * (intersection._rayStart + translation);
|
||||
intersection._rayDirection = rotation * intersection._rayDirection;
|
||||
|
||||
sphere.setTranslation(rotation * translation);
|
||||
|
||||
// ...and test again
|
||||
if (!sphere.findRayIntersection(intersection)) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray should just barely hit sphere" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1915,17 +1920,17 @@ void ShapeColliderTests::rayBarelyMissesSphere() {
|
|||
float delta = 2.0f * EPSILON;
|
||||
|
||||
float startDistance = 3.0f;
|
||||
glm::vec3 rayStart(-startDistance, radius + delta, 0.0f);
|
||||
glm::vec3 rayDirection(1.0f, 0.0f, 0.0f);
|
||||
RayIntersectionInfo intersection;
|
||||
intersection._rayStart = glm::vec3(-startDistance, radius + delta, 0.0f);
|
||||
intersection._rayDirection = glm::vec3(1.0f, 0.0f, 0.0f);
|
||||
|
||||
SphereShape sphere(radius, center);
|
||||
|
||||
// very simple ray along xAxis
|
||||
float distance = FLT_MAX;
|
||||
if (sphere.findRayIntersection(rayStart, rayDirection, distance)) {
|
||||
if (sphere.findRayIntersection(intersection)) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray should just barely miss sphere" << std::endl;
|
||||
}
|
||||
if (distance != FLT_MAX) {
|
||||
if (intersection._hitDistance != FLT_MAX) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: distance should be unchanged after intersection miss"
|
||||
<< std::endl;
|
||||
}
|
||||
|
@ -1935,16 +1940,16 @@ void ShapeColliderTests::rayBarelyMissesSphere() {
|
|||
glm::quat rotation = glm::angleAxis(0.987654321f, axis);
|
||||
glm::vec3 translation(35.7f, 2.46f, -1.97f);
|
||||
|
||||
rayStart = rotation * (rayStart + translation);
|
||||
rayDirection = rotation * rayDirection;
|
||||
intersection._hitDistance = FLT_MAX;
|
||||
intersection._rayStart = rotation * (intersection._rayStart + translation);
|
||||
intersection._rayDirection = rotation * intersection._rayDirection;
|
||||
sphere.setTranslation(rotation * translation);
|
||||
|
||||
// ...and test again
|
||||
distance = FLT_MAX;
|
||||
if (sphere.findRayIntersection(rayStart, rayDirection, distance)) {
|
||||
if (sphere.findRayIntersection(intersection)) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray should just barely miss sphere" << std::endl;
|
||||
}
|
||||
if (distance != FLT_MAX) {
|
||||
if (intersection._hitDistance != FLT_MAX) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: distance should be unchanged after intersection miss"
|
||||
<< std::endl;
|
||||
}
|
||||
|
@ -1959,26 +1964,26 @@ void ShapeColliderTests::rayHitsCapsule() {
|
|||
|
||||
{ // simple test along xAxis
|
||||
// toward capsule center
|
||||
glm::vec3 rayStart(startDistance, 0.0f, 0.0f);
|
||||
glm::vec3 rayDirection(-1.0f, 0.0f, 0.0f);
|
||||
float distance = FLT_MAX;
|
||||
if (!capsule.findRayIntersection(rayStart, rayDirection, distance)) {
|
||||
RayIntersectionInfo intersection;
|
||||
intersection._rayStart = glm::vec3(startDistance, 0.0f, 0.0f);
|
||||
intersection._rayDirection = glm::vec3(-1.0f, 0.0f, 0.0f);
|
||||
if (!capsule.findRayIntersection(intersection)) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray should hit capsule" << std::endl;
|
||||
}
|
||||
float expectedDistance = startDistance - radius;
|
||||
float relativeError = fabsf(distance - expectedDistance) / startDistance;
|
||||
float relativeError = fabsf(intersection._hitDistance - expectedDistance) / startDistance;
|
||||
if (relativeError > EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray capsule intersection distance error = "
|
||||
<< relativeError << std::endl;
|
||||
}
|
||||
|
||||
// toward top of cylindrical wall
|
||||
rayStart.y = halfHeight;
|
||||
distance = FLT_MAX;
|
||||
if (!capsule.findRayIntersection(rayStart, rayDirection, distance)) {
|
||||
intersection._rayStart.y = halfHeight;
|
||||
intersection._hitDistance = FLT_MAX;
|
||||
if (!capsule.findRayIntersection(intersection)) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray should hit capsule" << std::endl;
|
||||
}
|
||||
relativeError = fabsf(distance - expectedDistance) / startDistance;
|
||||
relativeError = fabsf(intersection._hitDistance - expectedDistance) / startDistance;
|
||||
if (relativeError > EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray capsule intersection distance error = "
|
||||
<< relativeError << std::endl;
|
||||
|
@ -1986,12 +1991,12 @@ void ShapeColliderTests::rayHitsCapsule() {
|
|||
|
||||
// toward top cap
|
||||
float delta = 2.0f * EPSILON;
|
||||
rayStart.y = halfHeight + delta;
|
||||
distance = FLT_MAX;
|
||||
if (!capsule.findRayIntersection(rayStart, rayDirection, distance)) {
|
||||
intersection._rayStart.y = halfHeight + delta;
|
||||
intersection._hitDistance = FLT_MAX;
|
||||
if (!capsule.findRayIntersection(intersection)) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray should hit capsule" << std::endl;
|
||||
}
|
||||
relativeError = fabsf(distance - expectedDistance) / startDistance;
|
||||
relativeError = fabsf(intersection._hitDistance - expectedDistance) / startDistance;
|
||||
if (relativeError > EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray capsule intersection distance error = "
|
||||
<< relativeError << std::endl;
|
||||
|
@ -2000,13 +2005,13 @@ void ShapeColliderTests::rayHitsCapsule() {
|
|||
const float EDGE_CASE_SLOP_FACTOR = 20.0f;
|
||||
|
||||
// toward tip of top cap
|
||||
rayStart.y = halfHeight + radius - delta;
|
||||
distance = FLT_MAX;
|
||||
if (!capsule.findRayIntersection(rayStart, rayDirection, distance)) {
|
||||
intersection._rayStart.y = halfHeight + radius - delta;
|
||||
intersection._hitDistance = FLT_MAX;
|
||||
if (!capsule.findRayIntersection(intersection)) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray should hit capsule" << std::endl;
|
||||
}
|
||||
expectedDistance = startDistance - radius * sqrtf(2.0f * delta); // using small angle approximation of cosine
|
||||
relativeError = fabsf(distance - expectedDistance) / startDistance;
|
||||
relativeError = fabsf(intersection._hitDistance - expectedDistance) / startDistance;
|
||||
// for edge cases we allow a LOT of error
|
||||
if (relativeError > EDGE_CASE_SLOP_FACTOR * EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray capsule intersection distance error = "
|
||||
|
@ -2014,13 +2019,13 @@ void ShapeColliderTests::rayHitsCapsule() {
|
|||
}
|
||||
|
||||
// toward tip of bottom cap
|
||||
rayStart.y = - halfHeight - radius + delta;
|
||||
distance = FLT_MAX;
|
||||
if (!capsule.findRayIntersection(rayStart, rayDirection, distance)) {
|
||||
intersection._rayStart.y = - halfHeight - radius + delta;
|
||||
intersection._hitDistance = FLT_MAX;
|
||||
if (!capsule.findRayIntersection(intersection)) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray should hit capsule" << std::endl;
|
||||
}
|
||||
expectedDistance = startDistance - radius * sqrtf(2.0f * delta); // using small angle approximation of cosine
|
||||
relativeError = fabsf(distance - expectedDistance) / startDistance;
|
||||
relativeError = fabsf(intersection._hitDistance - expectedDistance) / startDistance;
|
||||
// for edge cases we allow a LOT of error
|
||||
if (relativeError > EDGE_CASE_SLOP_FACTOR * EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray capsule intersection distance error = "
|
||||
|
@ -2028,14 +2033,14 @@ void ShapeColliderTests::rayHitsCapsule() {
|
|||
}
|
||||
|
||||
// toward edge of capsule cylindrical face
|
||||
rayStart.y = 0.0f;
|
||||
rayStart.z = radius - delta;
|
||||
distance = FLT_MAX;
|
||||
if (!capsule.findRayIntersection(rayStart, rayDirection, distance)) {
|
||||
intersection._rayStart.y = 0.0f;
|
||||
intersection._rayStart.z = radius - delta;
|
||||
intersection._hitDistance = FLT_MAX;
|
||||
if (!capsule.findRayIntersection(intersection)) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray should hit capsule" << std::endl;
|
||||
}
|
||||
expectedDistance = startDistance - radius * sqrtf(2.0f * delta); // using small angle approximation of cosine
|
||||
relativeError = fabsf(distance - expectedDistance) / startDistance;
|
||||
relativeError = fabsf(intersection._hitDistance - expectedDistance) / startDistance;
|
||||
// for edge cases we allow a LOT of error
|
||||
if (relativeError > EDGE_CASE_SLOP_FACTOR * EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray capsule intersection distance error = "
|
||||
|
@ -2055,40 +2060,41 @@ void ShapeColliderTests::rayMissesCapsule() {
|
|||
|
||||
{ // simple test along xAxis
|
||||
// toward capsule center
|
||||
glm::vec3 rayStart(startDistance, 0.0f, 0.0f);
|
||||
glm::vec3 rayDirection(-1.0f, 0.0f, 0.0f);
|
||||
RayIntersectionInfo intersection;
|
||||
intersection._rayStart = glm::vec3(startDistance, 0.0f, 0.0f);
|
||||
intersection._rayDirection = glm::vec3(-1.0f, 0.0f, 0.0f);
|
||||
float delta = 2.0f * EPSILON;
|
||||
|
||||
// over top cap
|
||||
rayStart.y = halfHeight + radius + delta;
|
||||
float distance = FLT_MAX;
|
||||
if (capsule.findRayIntersection(rayStart, rayDirection, distance)) {
|
||||
intersection._rayStart.y = halfHeight + radius + delta;
|
||||
intersection._hitDistance = FLT_MAX;
|
||||
if (capsule.findRayIntersection(intersection)) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray should miss capsule" << std::endl;
|
||||
}
|
||||
if (distance != FLT_MAX) {
|
||||
if (intersection._hitDistance != FLT_MAX) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: distance should be unchanged after intersection miss"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
// below bottom cap
|
||||
rayStart.y = - halfHeight - radius - delta;
|
||||
distance = FLT_MAX;
|
||||
if (capsule.findRayIntersection(rayStart, rayDirection, distance)) {
|
||||
intersection._rayStart.y = - halfHeight - radius - delta;
|
||||
intersection._hitDistance = FLT_MAX;
|
||||
if (capsule.findRayIntersection(intersection)) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray should miss capsule" << std::endl;
|
||||
}
|
||||
if (distance != FLT_MAX) {
|
||||
if (intersection._hitDistance != FLT_MAX) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: distance should be unchanged after intersection miss"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
// past edge of capsule cylindrical face
|
||||
rayStart.y = 0.0f;
|
||||
rayStart.z = radius + delta;
|
||||
distance = FLT_MAX;
|
||||
if (capsule.findRayIntersection(rayStart, rayDirection, distance)) {
|
||||
intersection._rayStart.y = 0.0f;
|
||||
intersection._rayStart.z = radius + delta;
|
||||
intersection._hitDistance = FLT_MAX;
|
||||
if (capsule.findRayIntersection(intersection)) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray should miss capsule" << std::endl;
|
||||
}
|
||||
if (distance != FLT_MAX) {
|
||||
if (intersection._hitDistance != FLT_MAX) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: distance should be unchanged after intersection miss"
|
||||
<< std::endl;
|
||||
}
|
||||
|
@ -2105,16 +2111,16 @@ void ShapeColliderTests::rayHitsPlane() {
|
|||
|
||||
// make a simple ray
|
||||
float startDistance = 1.234f;
|
||||
glm::vec3 rayStart(-startDistance, 0.0f, 0.0f);
|
||||
glm::vec3 rayDirection = glm::normalize(glm::vec3(1.0f, 1.0f, 1.0f));
|
||||
RayIntersectionInfo intersection;
|
||||
intersection._rayStart = glm::vec3(-startDistance, 0.0f, 0.0f);
|
||||
intersection._rayDirection = glm::normalize(glm::vec3(1.0f, 1.0f, 1.0f));
|
||||
|
||||
float distance = FLT_MAX;
|
||||
if (!plane.findRayIntersection(rayStart, rayDirection, distance)) {
|
||||
if (!plane.findRayIntersection(intersection)) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray should hit plane" << std::endl;
|
||||
}
|
||||
|
||||
float expectedDistance = SQUARE_ROOT_OF_3 * planeDistanceFromOrigin;
|
||||
float relativeError = fabsf(distance - expectedDistance) / planeDistanceFromOrigin;
|
||||
float relativeError = fabsf(intersection._hitDistance - expectedDistance) / planeDistanceFromOrigin;
|
||||
if (relativeError > EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray plane intersection distance error = "
|
||||
<< relativeError << std::endl;
|
||||
|
@ -2127,16 +2133,16 @@ void ShapeColliderTests::rayHitsPlane() {
|
|||
|
||||
plane.setTranslation(rotation * planePosition);
|
||||
plane.setRotation(rotation);
|
||||
rayStart = rotation * rayStart;
|
||||
rayDirection = rotation * rayDirection;
|
||||
intersection._rayStart = rotation * intersection._rayStart;
|
||||
intersection._rayDirection = rotation * intersection._rayDirection;
|
||||
|
||||
distance = FLT_MAX;
|
||||
if (!plane.findRayIntersection(rayStart, rayDirection, distance)) {
|
||||
intersection._hitDistance = FLT_MAX;
|
||||
if (!plane.findRayIntersection(intersection)) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray should hit plane" << std::endl;
|
||||
}
|
||||
|
||||
expectedDistance = SQUARE_ROOT_OF_3 * planeDistanceFromOrigin;
|
||||
relativeError = fabsf(distance - expectedDistance) / planeDistanceFromOrigin;
|
||||
relativeError = fabsf(intersection._hitDistance - expectedDistance) / planeDistanceFromOrigin;
|
||||
if (relativeError > EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray plane intersection distance error = "
|
||||
<< relativeError << std::endl;
|
||||
|
@ -2152,14 +2158,14 @@ void ShapeColliderTests::rayMissesPlane() {
|
|||
|
||||
{ // parallel rays should miss
|
||||
float startDistance = 1.234f;
|
||||
glm::vec3 rayStart(-startDistance, 0.0f, 0.0f);
|
||||
glm::vec3 rayDirection = glm::normalize(glm::vec3(-1.0f, 0.0f, -1.0f));
|
||||
RayIntersectionInfo intersection;
|
||||
intersection._rayStart = glm::vec3(-startDistance, 0.0f, 0.0f);
|
||||
intersection._rayDirection = glm::normalize(glm::vec3(-1.0f, 0.0f, -1.0f));
|
||||
|
||||
float distance = FLT_MAX;
|
||||
if (plane.findRayIntersection(rayStart, rayDirection, distance)) {
|
||||
if (plane.findRayIntersection(intersection)) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray should miss plane" << std::endl;
|
||||
}
|
||||
if (distance != FLT_MAX) {
|
||||
if (intersection._hitDistance != FLT_MAX) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: distance should be unchanged after intersection miss"
|
||||
<< std::endl;
|
||||
}
|
||||
|
@ -2171,14 +2177,15 @@ void ShapeColliderTests::rayMissesPlane() {
|
|||
|
||||
plane.setTranslation(rotation * planePosition);
|
||||
plane.setRotation(rotation);
|
||||
rayStart = rotation * rayStart;
|
||||
rayDirection = rotation * rayDirection;
|
||||
|
||||
distance = FLT_MAX;
|
||||
if (plane.findRayIntersection(rayStart, rayDirection, distance)) {
|
||||
|
||||
intersection._rayStart = rotation * intersection._rayStart;
|
||||
intersection._rayDirection = rotation * intersection._rayDirection;
|
||||
intersection._hitDistance = FLT_MAX;
|
||||
|
||||
if (plane.findRayIntersection(intersection)) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray should miss plane" << std::endl;
|
||||
}
|
||||
if (distance != FLT_MAX) {
|
||||
if (intersection._hitDistance != FLT_MAX) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: distance should be unchanged after intersection miss"
|
||||
<< std::endl;
|
||||
}
|
||||
|
@ -2186,14 +2193,16 @@ void ShapeColliderTests::rayMissesPlane() {
|
|||
|
||||
{ // make a simple ray that points away from plane
|
||||
float startDistance = 1.234f;
|
||||
glm::vec3 rayStart(-startDistance, 0.0f, 0.0f);
|
||||
glm::vec3 rayDirection = glm::normalize(glm::vec3(-1.0f, -1.0f, -1.0f));
|
||||
|
||||
RayIntersectionInfo intersection;
|
||||
intersection._rayStart = glm::vec3(-startDistance, 0.0f, 0.0f);
|
||||
intersection._rayDirection = glm::normalize(glm::vec3(-1.0f, -1.0f, -1.0f));
|
||||
intersection._hitDistance = FLT_MAX;
|
||||
|
||||
float distance = FLT_MAX;
|
||||
if (plane.findRayIntersection(rayStart, rayDirection, distance)) {
|
||||
if (plane.findRayIntersection(intersection)) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray should miss plane" << std::endl;
|
||||
}
|
||||
if (distance != FLT_MAX) {
|
||||
if (intersection._hitDistance != FLT_MAX) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: distance should be unchanged after intersection miss"
|
||||
<< std::endl;
|
||||
}
|
||||
|
@ -2205,14 +2214,15 @@ void ShapeColliderTests::rayMissesPlane() {
|
|||
|
||||
plane.setTranslation(rotation * planePosition);
|
||||
plane.setRotation(rotation);
|
||||
rayStart = rotation * rayStart;
|
||||
rayDirection = rotation * rayDirection;
|
||||
|
||||
intersection._rayStart = rotation * intersection._rayStart;
|
||||
intersection._rayDirection = rotation * intersection._rayDirection;
|
||||
intersection._hitDistance = FLT_MAX;
|
||||
|
||||
distance = FLT_MAX;
|
||||
if (plane.findRayIntersection(rayStart, rayDirection, distance)) {
|
||||
if (plane.findRayIntersection(intersection)) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: ray should miss plane" << std::endl;
|
||||
}
|
||||
if (distance != FLT_MAX) {
|
||||
if (intersection._hitDistance != FLT_MAX) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: distance should be unchanged after intersection miss"
|
||||
<< std::endl;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue