parabola triangle intersection

This commit is contained in:
SamGondelman 2018-07-09 18:06:33 -07:00
parent fcc523fbef
commit ca5ce888f4
8 changed files with 333 additions and 19 deletions

View file

@ -294,6 +294,18 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori
face, surfaceNormal, extraInfo, precisionPicking, false);
}
bool RenderableModelEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity,
const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, BoxFace& face,
glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const {
auto model = getModel();
if (!model || !isModelLoaded()) {
return false;
}
return model->findParabolaIntersectionAgainstSubMeshes(origin, velocity, acceleration, parabolicDistance,
face, surfaceNormal, extraInfo, precisionPicking, false);
}
void RenderableModelEntityItem::getCollisionGeometryResource() {
QUrl hullURL(getCompoundShapeURL());
QUrlQuery queryArgs(hullURL);

View file

@ -71,6 +71,10 @@ public:
OctreeElementPointer& element, float& distance,
BoxFace& face, glm::vec3& surfaceNormal,
QVariantMap& extraInfo, bool precisionPicking) const override;
virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity,
const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance,
BoxFace& face, glm::vec3& surfaceNormal,
QVariantMap& extraInfo, bool precisionPicking) const override;
virtual void setShapeType(ShapeType type) override;
virtual void setCompoundShapeURL(const QString& url) override;

View file

@ -353,31 +353,27 @@ void Model::initJointStates() {
bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance,
BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo,
bool pickAgainstTriangles, bool allowBackface) {
bool intersectedSomething = false;
// if we aren't active, we can't ray pick yet...
// if we aren't active, we can't pick yet...
if (!isActive()) {
return intersectedSomething;
}
// extents is the entity relative, scaled, centered extents of the entity
glm::vec3 position = _translation;
glm::mat4 rotation = glm::mat4_cast(_rotation);
glm::mat4 translation = glm::translate(position);
glm::mat4 modelToWorldMatrix = translation * rotation;
glm::mat4 modelToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation);
glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix);
Extents modelExtents = getMeshExtents(); // NOTE: unrotated
glm::vec3 dimensions = modelExtents.maximum - modelExtents.minimum;
glm::vec3 corner = -(dimensions * _registrationPoint); // since we're going to do the ray picking in the model frame of reference
glm::vec3 corner = -(dimensions * _registrationPoint); // since we're going to do the picking in the model frame of reference
AABox modelFrameBox(corner, dimensions);
glm::vec3 modelFrameOrigin = glm::vec3(worldToModelMatrix * glm::vec4(origin, 1.0f));
glm::vec3 modelFrameDirection = glm::vec3(worldToModelMatrix * glm::vec4(direction, 0.0f));
// we can use the AABox's ray intersection by mapping our origin and direction into the model frame
// we can use the AABox's intersection by mapping our origin and direction into the model frame
// and testing intersection there.
if (modelFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, distance, face, surfaceNormal)) {
QMutexLocker locker(&_mutex);
@ -395,7 +391,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g
}
glm::mat4 meshToModelMatrix = glm::scale(_scale) * glm::translate(_offset);
glm::mat4 meshToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation) * meshToModelMatrix;
glm::mat4 meshToWorldMatrix = modelToWorldMatrix * meshToModelMatrix;
glm::mat4 worldToMeshMatrix = glm::inverse(meshToWorldMatrix);
glm::vec3 meshFrameOrigin = glm::vec3(worldToMeshMatrix * glm::vec4(origin, 1.0f));
@ -405,11 +401,10 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g
for (auto& meshTriangleSets : _modelSpaceMeshTriangleSets) {
int partIndex = 0;
for (auto &partTriangleSet : meshTriangleSets) {
float triangleSetDistance = 0.0f;
float triangleSetDistance;
BoxFace triangleSetFace;
Triangle triangleSetTriangle;
if (partTriangleSet.findRayIntersection(meshFrameOrigin, meshFrameDirection, triangleSetDistance, triangleSetFace, triangleSetTriangle, pickAgainstTriangles, allowBackface)) {
glm::vec3 meshIntersectionPoint = meshFrameOrigin + (meshFrameDirection * triangleSetDistance);
glm::vec3 worldIntersectionPoint = glm::vec3(meshToWorldMatrix * glm::vec4(meshIntersectionPoint, 1.0f));
float worldDistance = glm::distance(origin, worldIntersectionPoint);
@ -457,6 +452,111 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g
return intersectedSomething;
}
bool Model::findParabolaIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration,
float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo,
bool pickAgainstTriangles, bool allowBackface) {
bool intersectedSomething = false;
// if we aren't active, we can't pick yet...
if (!isActive()) {
return intersectedSomething;
}
// extents is the entity relative, scaled, centered extents of the entity
glm::mat4 modelToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation);
glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix);
Extents modelExtents = getMeshExtents(); // NOTE: unrotated
glm::vec3 dimensions = modelExtents.maximum - modelExtents.minimum;
glm::vec3 corner = -(dimensions * _registrationPoint); // since we're going to do the picking in the model frame of reference
AABox modelFrameBox(corner, dimensions);
glm::vec3 modelFrameOrigin = glm::vec3(worldToModelMatrix * glm::vec4(origin, 1.0f));
glm::vec3 modelFrameVelocity = glm::vec3(worldToModelMatrix * glm::vec4(velocity, 0.0f));
glm::vec3 modelFrameAcceleration = glm::vec3(worldToModelMatrix * glm::vec4(acceleration, 0.0f));
// we can use the AABox's intersection by mapping our origin and direction into the model frame
// and testing intersection there.
if (modelFrameBox.findParabolaIntersection(modelFrameOrigin, modelFrameVelocity, modelFrameAcceleration, parabolicDistance, face, surfaceNormal)) {
QMutexLocker locker(&_mutex);
float bestDistance = FLT_MAX;
Triangle bestModelTriangle;
Triangle bestWorldTriangle;
int bestSubMeshIndex = 0;
int subMeshIndex = 0;
const FBXGeometry& geometry = getFBXGeometry();
if (!_triangleSetsValid) {
calculateTriangleSets(geometry);
}
glm::mat4 meshToModelMatrix = glm::scale(_scale) * glm::translate(_offset);
glm::mat4 meshToWorldMatrix = modelToWorldMatrix * meshToModelMatrix;
glm::mat4 worldToMeshMatrix = glm::inverse(meshToWorldMatrix);
glm::vec3 meshFrameOrigin = glm::vec3(worldToMeshMatrix * glm::vec4(origin, 1.0f));
glm::vec3 meshFrameVelocity = glm::vec3(worldToMeshMatrix * glm::vec4(velocity, 0.0f));
glm::vec3 meshFrameAcceleration = glm::vec3(worldToMeshMatrix * glm::vec4(acceleration, 0.0f));
int shapeID = 0;
for (auto& meshTriangleSets : _modelSpaceMeshTriangleSets) {
int partIndex = 0;
for (auto &partTriangleSet : meshTriangleSets) {
float triangleSetDistance;
BoxFace triangleSetFace;
Triangle triangleSetTriangle;
if (partTriangleSet.findParabolaIntersection(meshFrameOrigin, meshFrameVelocity, meshFrameAcceleration,
triangleSetDistance, triangleSetFace, triangleSetTriangle, pickAgainstTriangles, allowBackface)) {
if (triangleSetDistance < bestDistance) {
bestDistance = triangleSetDistance;
intersectedSomething = true;
face = triangleSetFace;
bestModelTriangle = triangleSetTriangle;
bestWorldTriangle = triangleSetTriangle * meshToWorldMatrix;
glm::vec3 worldIntersectionPoint = meshFrameOrigin + meshFrameVelocity * triangleSetDistance +
0.5f * meshFrameAcceleration * triangleSetDistance * triangleSetDistance;
glm::vec3 meshIntersectionPoint = origin + velocity * triangleSetDistance +
0.5f * acceleration * triangleSetDistance * triangleSetDistance;
extraInfo["worldIntersectionPoint"] = vec3toVariant(worldIntersectionPoint);
extraInfo["meshIntersectionPoint"] = vec3toVariant(meshIntersectionPoint);
extraInfo["partIndex"] = partIndex;
extraInfo["shapeID"] = shapeID;
bestSubMeshIndex = subMeshIndex;
}
}
partIndex++;
shapeID++;
}
subMeshIndex++;
}
if (intersectedSomething) {
parabolicDistance = bestDistance;
surfaceNormal = bestWorldTriangle.getNormal();
if (pickAgainstTriangles) {
extraInfo["subMeshIndex"] = bestSubMeshIndex;
extraInfo["subMeshName"] = geometry.getModelNameOfMesh(bestSubMeshIndex);
extraInfo["subMeshTriangleWorld"] = QVariantMap{
{ "v0", vec3toVariant(bestWorldTriangle.v0) },
{ "v1", vec3toVariant(bestWorldTriangle.v1) },
{ "v2", vec3toVariant(bestWorldTriangle.v2) },
};
extraInfo["subMeshNormal"] = vec3toVariant(bestModelTriangle.getNormal());
extraInfo["subMeshTriangle"] = QVariantMap{
{ "v0", vec3toVariant(bestModelTriangle.v0) },
{ "v1", vec3toVariant(bestModelTriangle.v1) },
{ "v2", vec3toVariant(bestModelTriangle.v2) },
};
}
}
}
return intersectedSomething;
}
bool Model::convexHullContains(glm::vec3 point) {
// if we aren't active, we can't compute that yet...
if (!isActive()) {
@ -594,7 +694,7 @@ bool Model::replaceScriptableModelMeshPart(scriptable::ScriptableModelBasePointe
}
scene->enqueueTransaction(transaction);
}
// update triangles for ray picking
// update triangles for picking
{
FBXGeometry geometry;
for (const auto& newMesh : meshes) {

View file

@ -178,6 +178,9 @@ public:
bool findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance,
BoxFace& face, glm::vec3& surfaceNormal,
QVariantMap& extraInfo, bool pickAgainstTriangles = false, bool allowBackface = false);
bool findParabolaIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration,
float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal,
QVariantMap& extraInfo, bool pickAgainstTriangles = false, bool allowBackface = false);
void setOffset(const glm::vec3& offset);
const glm::vec3& getOffset() const { return _offset; }

View file

@ -18,6 +18,7 @@
#include <complex>
#include <qmath.h>
#include <glm/gtx/quaternion.hpp>
#include "glm/gtc/matrix_transform.hpp"
#include "NumericalConstants.h"
#include "GLMHelpers.h"
@ -797,6 +798,62 @@ bool findParabolaSphereIntersection(const glm::vec3& origin, const glm::vec3& ve
return false;
}
void checkPossibleParabolicIntersectionWithTriangle(float t, float& minDistance,
const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration,
const glm::vec3& localVelocity, const glm::vec3& localAcceleration, const glm::vec3& normal,
const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, bool allowBackface) {
// Check if we're hitting the backface in the rotated coordinate space
float localIntersectionVelocityZ = localVelocity.z + localAcceleration.z * t;
if (!allowBackface && localIntersectionVelocityZ < 0.0f) {
return;
}
// Check that the point is within all three sides
glm::vec3 point = origin + velocity * t + 0.5f * acceleration * t * t;
if (glm::dot(normal, glm::cross(point - v1, v0 - v1)) > 0.0f &&
glm::dot(normal, glm::cross(v2 - v1, point - v1)) > 0.0f &&
glm::dot(normal, glm::cross(point - v0, v2 - v0)) > 0.0f) {
minDistance = t;
}
}
bool findParabolaTriangleIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration,
const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, float& parabolicDistance, bool allowBackface) {
glm::vec3 normal = glm::cross(v2 - v1, v0 - v1);
// We transform the parabola and triangle so that the triangle is in the plane z = 0, with v0 at the origin
glm::quat inverseRot;
// Note: OpenGL view matrix is already the inverse of our camera matrix
// if the direction is nearly aligned with the Y axis, then use the X axis for 'up'
const float MAX_ABS_Y_COMPONENT = 0.9999991f;
if (fabsf(normal.y) > MAX_ABS_Y_COMPONENT) {
inverseRot = glm::quat_cast(glm::lookAt(glm::vec3(0.0f), normal, Vectors::UNIT_X));
} else {
inverseRot = glm::quat_cast(glm::lookAt(glm::vec3(0.0f), normal, Vectors::UNIT_Y));
}
glm::vec3 localOrigin = inverseRot * (origin - v0);
glm::vec3 localVelocity = inverseRot * velocity;
glm::vec3 localAcceleration = inverseRot * acceleration;
float minDistance = FLT_MAX;
float a = 0.5f * localAcceleration.z;
float b = localVelocity.z;
float c = localOrigin.z;
glm::vec2 possibleDistances = { FLT_MAX, FLT_MAX };
if (computeRealQuadraticRoots(a, b, c, possibleDistances)) {
checkPossibleParabolicIntersectionWithTriangle(possibleDistances.x, minDistance, origin, velocity, acceleration,
localVelocity, localAcceleration, normal, v0, v1, v2, allowBackface);
checkPossibleParabolicIntersectionWithTriangle(possibleDistances.y, minDistance, origin, velocity, acceleration,
localVelocity, localAcceleration, normal, v0, v1, v2, allowBackface);
}
if (minDistance < FLT_MAX) {
parabolicDistance = minDistance;
return true;
}
return false;
}
void swingTwistDecomposition(const glm::quat& rotation,
const glm::vec3& direction,
glm::quat& swing,

View file

@ -94,6 +94,9 @@ 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& distance);
bool findParabolaTriangleIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration,
const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, float& parabolicDistance, bool allowBackface = false);
/// \brief decomposes rotation into its components such that: rotation = swing * twist
/// \param rotation[in] rotation to decompose
/// \param direction[in] normalized axis about which the twist happens (typically original direction before rotation applied)
@ -118,6 +121,11 @@ inline bool findRayTriangleIntersection(const glm::vec3& origin, const glm::vec3
return findRayTriangleIntersection(origin, direction, triangle.v0, triangle.v1, triangle.v2, distance, allowBackface);
}
inline bool findParabolaTriangleIntersection(const glm::vec3& origin, const glm::vec3& velocity,
const glm::vec3& acceleration, const Triangle& triangle, float& parabolicDistance, bool allowBackface = false) {
return findParabolaTriangleIntersection(origin, velocity, acceleration, triangle.v0, triangle.v1, triangle.v2, parabolicDistance, allowBackface);
}
int clipTriangleWithPlane(const Triangle& triangle, const Plane& plane, Triangle* clippedTriangles, int maxClippedTriangleCount);
int clipTriangleWithPlanes(const Triangle& triangle, const Plane* planes, int planeCount, Triangle* clippedTriangles, int maxClippedTriangleCount);
@ -194,5 +202,9 @@ bool isWithin(float value, float corner, float size);
void checkPossibleParabolicIntersectionWithZPlane(float t, float& minDistance,
const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, const glm::vec2& corner, const glm::vec2& scale);
void checkPossibleParabolicIntersectionWithTriangle(float t, float& minDistance,
const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration,
const glm::vec3& localVelocity, const glm::vec3& localAcceleration, const glm::vec3& normal,
const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, bool allowBackface);
#endif // hifi_GeometryUtil_h

View file

@ -51,6 +51,26 @@ bool TriangleSet::findRayIntersection(const glm::vec3& origin, const glm::vec3&
return result;
}
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) {
// reset our distance to be the max possible, lower level tests will store best distance here
parabolicDistance = FLT_MAX;
if (!_isBalanced) {
balanceOctree();
}
int trianglesTouched = 0;
auto result = _triangleOctree.findParabolaIntersection(origin, velocity, acceleration, parabolicDistance, face, triangle, precision, trianglesTouched, allowBackface);
#if WANT_DEBUGGING
if (precision) {
qDebug() << "trianglesTouched :" << trianglesTouched << "out of:" << _triangleOctree._population << "_triangles.size:" << _triangles.size();
}
#endif
return result;
}
bool TriangleSet::convexHullContains(const glm::vec3& point) const {
if (!_bounds.contains(point)) {
return false;
@ -105,7 +125,7 @@ bool TriangleSet::TriangleOctreeCell::findRayIntersectionInternal(const glm::vec
if (_bounds.findRayIntersection(origin, direction, boxDistance, face, surfaceNormal)) {
// if our bounding box intersects at a distance greater than the current known
// best distance, and our origin isn't inside the boounds, then we can safely
// best distance, and our origin isn't inside the boounds, then we can safely
// not check any of our triangles
if (boxDistance > bestDistance && !_bounds.contains(origin)) {
return false;
@ -127,6 +147,7 @@ bool TriangleSet::TriangleOctreeCell::findRayIntersectionInternal(const glm::vec
}
} else {
intersectedSomething = true;
// FIXME: this needs to set triangle to something or it will carry the previous value
distance = boxDistance;
}
}
@ -134,6 +155,48 @@ bool TriangleSet::TriangleOctreeCell::findRayIntersectionInternal(const glm::vec
return intersectedSomething;
}
bool TriangleSet::TriangleOctreeCell::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) {
bool intersectedSomething = false;
float boxDistance = parabolicDistance;
float bestDistance = parabolicDistance;
glm::vec3 surfaceNormal;
if (_bounds.findParabolaIntersection(origin, velocity, acceleration, boxDistance, face, surfaceNormal)) {
// if our bounding box intersects at a distance greater than the current known
// best distance, and our origin isn't inside the boounds, then we can safely
// not check any of our triangles
if (boxDistance > bestDistance && !_bounds.contains(origin)) {
return false;
}
if (precision) {
for (const auto& triangleIndex : _triangleIndices) {
const auto& thisTriangle = _allTriangles[triangleIndex];
float thisTriangleDistance;
trianglesTouched++;
if (findParabolaTriangleIntersection(origin, velocity, acceleration, thisTriangle, thisTriangleDistance, allowBackface)) {
if (thisTriangleDistance < bestDistance) {
bestDistance = thisTriangleDistance;
intersectedSomething = true;
triangle = thisTriangle;
parabolicDistance = bestDistance;
}
}
}
} else {
intersectedSomething = true;
// FIXME: this needs to set triangle to something or it will carry the previous value
parabolicDistance = boxDistance;
}
}
return intersectedSomething;
}
static const int MAX_DEPTH = 4; // for now
static const int MAX_CHILDREN = 8;
@ -267,3 +330,64 @@ bool TriangleSet::TriangleOctreeCell::findRayIntersection(const glm::vec3& origi
}
return intersects;
}
bool TriangleSet::TriangleOctreeCell::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) {
if (_population < 1) {
return false; // no triangles below here, so we can't intersect
}
float bestLocalDistance = parabolicDistance;
BoxFace bestLocalFace;
Triangle bestLocalTriangle;
glm::vec3 bestLocalNormal;
bool intersects = false;
// if the ray intersects our bounding box, then continue
if (getBounds().findParabolaIntersection(origin, velocity, acceleration, bestLocalDistance, bestLocalFace, bestLocalNormal)) {
// if the intersection with our bounding box, is greater than the current best distance (the distance passed in)
// then we know that none of our triangles can represent a better intersection and we can return
if (bestLocalDistance > parabolicDistance) {
return false;
}
bestLocalDistance = parabolicDistance;
float childDistance = parabolicDistance;
BoxFace childFace;
Triangle childTriangle;
// if we're not yet at the max depth, then check which child the triangle fits in
if (_depth < MAX_DEPTH) {
for (auto& child : _children) {
// check each child, if there's an intersection, it will return some distance that we need
// to compare against the other results, because there might be multiple intersections and
// we will always choose the best (shortest) intersection
if (child.second.findParabolaIntersection(origin, velocity, acceleration, childDistance, childFace, childTriangle, precision, trianglesTouched)) {
if (childDistance < bestLocalDistance) {
bestLocalDistance = childDistance;
bestLocalFace = childFace;
bestLocalTriangle = childTriangle;
intersects = true;
}
}
}
}
// also check our local triangle set
if (findParabolaIntersectionInternal(origin, velocity, acceleration, childDistance, childFace, childTriangle, precision, trianglesTouched, allowBackface)) {
if (childDistance < bestLocalDistance) {
bestLocalDistance = childDistance;
bestLocalFace = childFace;
bestLocalTriangle = childTriangle;
intersects = true;
}
}
}
if (intersects) {
parabolicDistance = bestLocalDistance;
face = bestLocalFace;
triangle = bestLocalTriangle;
}
return intersects;
}

View file

@ -31,6 +31,9 @@ class TriangleSet {
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
float& distance, BoxFace& face, Triangle& triangle, bool precision, int& trianglesTouched,
bool allowBackface = false);
bool 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 = false);
const AABox& getBounds() const { return _bounds; }
@ -43,6 +46,9 @@ class TriangleSet {
bool findRayIntersectionInternal(const glm::vec3& origin, const glm::vec3& direction,
float& distance, BoxFace& face, Triangle& triangle, bool precision, int& trianglesTouched,
bool allowBackface = false);
bool 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 = false);
std::vector<Triangle>& _allTriangles;
std::map<AABox::OctreeChild, TriangleOctreeCell> _children;
@ -65,6 +71,8 @@ public:
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
float& distance, BoxFace& face, Triangle& triangle, bool precision, bool allowBackface = false);
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();
@ -72,12 +80,6 @@ public:
size_t size() const { return _triangles.size(); }
void clear();
// Determine if 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.
// note: this might side-effect internal structures
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
float& distance, BoxFace& face, Triangle& triangle, bool precision, int& trianglesTouched);
// Determine if a point is "inside" all the triangles of a convex hull. It is the responsibility of the caller to
// determine that the triangle set is indeed a convex hull. If the triangles added to this set are not in fact a
// convex hull, the result of this method is meaningless and undetermined.