📄 aabb3.cpp
字号:
returnNormal->y = 0.0f;
returnNormal->z = 0.0f;
}
} break;
case 1: // intersect with xz plane
{
float x = rayOrg.x + rayDelta.x*t;
if (x < min.x || x > max.x) return kNoIntersection;
float z = rayOrg.z + rayDelta.z*t;
if (z < min.z || z > max.z) return kNoIntersection;
if (returnNormal != NULL) {
returnNormal->x = 0.0f;
returnNormal->y = yn;
returnNormal->z = 0.0f;
}
} break;
case 2: // intersect with xy plane
{
float x = rayOrg.x + rayDelta.x*t;
if (x < min.x || x > max.x) return kNoIntersection;
float y = rayOrg.y + rayDelta.y*t;
if (y < min.y || y > max.y) return kNoIntersection;
if (returnNormal != NULL) {
returnNormal->x = 0.0f;
returnNormal->y = 0.0f;
returnNormal->z = zn;
}
} break;
}
// Return parametric point of intersection
return t;
}
//---------------------------------------------------------------------------
// AABB3::classifyPlane
//
// Perform static AABB-plane intersection test. Returns:
//
// <0 Box is completely on the BACK side of the plane
// >0 Box is completely on the FRONT side of the plane
// 0 Box intersects the plane
int AABB3::classifyPlane(const Vector3 &n, float d) const {
// Inspect the normal and compute the minimum and maximum
// D values.
float minD, maxD;
if (n.x > 0.0f) {
minD = n.x*min.x; maxD = n.x*max.x;
} else {
minD = n.x*max.x; maxD = n.x*min.x;
}
if (n.y > 0.0f) {
minD += n.y*min.y; maxD += n.y*max.y;
} else {
minD += n.y*max.y; maxD += n.y*min.y;
}
if (n.z > 0.0f) {
minD += n.z*min.z; maxD += n.z*max.z;
} else {
minD += n.z*max.z; maxD += n.z*min.z;
}
// Check if completely on the front side of the plane
if (minD >= d) {
return +1;
}
// Check if completely on the back side of the plane
if (maxD <= d) {
return -1;
}
// We straddle the plane
return 0;
}
//---------------------------------------------------------------------------
// AABB3::intersectPlane
//
// Perform dynamic AABB-plane intersection test.
//
// n is the plane normal (assumed to be normalized)
// planeD is the D value of the plane equation p.n = d
// dir dir is the direction of movement of the AABB.
//
// The plane is assumed to be stationary.
//
// Returns the parametric point of intersection - the distance traveled
// before an intersection occurs. If no intersection, a REALLY big
// number is returned. You must check against the length of the
// displacement.
//
// Only intersections with the front side of the plane are detected
float AABB3::intersectPlane(
const Vector3 &n,
float planeD,
const Vector3 &dir
) const {
// Make sure they are passing in normalized vectors
assert(fabs(n*n - 1.0) < .01);
assert(fabs(dir*dir - 1.0) < .01);
// We'll return this huge number if no intersection
const float kNoIntersection = 1e30f;
// Compute glancing angle, make sure we are moving towards
// the front of the plane
float dot = n * dir;
if (dot >= 0.0f) {
return kNoIntersection;
}
// Inspect the normal and compute the minimum and maximum
// D values. minD is the D value of the "frontmost" corner point
float minD, maxD;
if (n.x > 0.0f) {
minD = n.x*min.x; maxD = n.x*max.x;
} else {
minD = n.x*max.x; maxD = n.x*min.x;
}
if (n.y > 0.0f) {
minD += n.y*min.y; maxD += n.y*max.y;
} else {
minD += n.y*max.y; maxD += n.y*min.y;
}
if (n.z > 0.0f) {
minD += n.z*min.z; maxD += n.z*max.z;
} else {
minD += n.z*max.z; maxD += n.z*min.z;
}
// Check if we're already completely on the other
// side of the plane
if (maxD <= planeD) {
return kNoIntersection;
}
// Perform standard raytrace equation using the
// frontmost corner point
float t = (planeD - minD) / dot;
// Were we already penetrating?
if (t < 0.0f) {
return 0.0f;
}
// Return it. If > l, then we didn't hit in time. That's
// the condition that the caller should be checking for.
return t;
}
/////////////////////////////////////////////////////////////////////////////
//
// Global nonmember code
//
/////////////////////////////////////////////////////////////////////////////
//---------------------------------------------------------------------------
// intersectAABBs
//
// Check if two AABBs intersect, and return true if so. Optionally return
// the AABB of their intersection if an intersection is detected
bool intersectAABBs(
const AABB3 &box1,
const AABB3 &box2,
AABB3 *boxIntersect
) {
// Check for no overlap
if (box1.min.x > box2.max.x) return false;
if (box1.max.x < box2.min.x) return false;
if (box1.min.y > box2.max.y) return false;
if (box1.max.y < box2.min.y) return false;
if (box1.min.z > box2.max.z) return false;
if (box1.max.z < box2.min.z) return false;
// We have overlap. Compute AABB of intersection, if they want it
if (boxIntersect != NULL) {
boxIntersect->min.x = max(box1.min.x, box2.min.x);
boxIntersect->max.x = min(box1.max.x, box2.max.x);
boxIntersect->min.y = max(box1.min.y, box2.min.y);
boxIntersect->max.y = min(box1.max.y, box2.max.y);
boxIntersect->min.z = max(box1.min.z, box2.min.z);
boxIntersect->max.z = min(box1.max.z, box2.max.z);
}
// They intersected
return true;
}
//---------------------------------------------------------------------------
// intersectMovingAABB
//
// Return parametric point in time when a moving AABB collides
// with a stationary AABB. Returns > 1 if no intersection
float intersectMovingAABB(
const AABB3 &stationaryBox,
const AABB3 &movingBox,
const Vector3 &d
) {
// We'll return this huge number if no intersection
const float kNoIntersection = 1e30f;
// Initialize interval to contain all the time under consideration
float tEnter = 0.0f;
float tLeave = 1.0f;
//
// Compute interval of overlap on each dimension, and intersect
// this interval with the interval accumulated so far. As soon as
// an empty interval is detected, return a negative result
// (no intersection.) In each case, we have to be careful for
// an infinite of empty interval on each dimension
//
// Check x-axis
if (d.x == 0.0f) {
// Empty or infinite inverval on x
if (
(stationaryBox.min.x >= movingBox.max.x) ||
(stationaryBox.max.x <= movingBox.min.x)
) {
// Empty time interval, so no intersection
return kNoIntersection;
}
// Inifinite time interval - no update necessary
} else {
// Divide once
float oneOverD = 1.0f / d.x;
// Compute time value when they begin and end overlapping
float xEnter = (stationaryBox.min.x - movingBox.max.x) * oneOverD;
float xLeave = (stationaryBox.max.x - movingBox.min.x) * oneOverD;
// Check for interval out of order
if (xEnter > xLeave) {
swap(xEnter, xLeave);
}
// Update interval
if (xEnter > tEnter) tEnter = xEnter;
if (xLeave < tLeave) tLeave = xLeave;
// Check if this resulted in empty interval
if (tEnter > tLeave) {
return kNoIntersection;
}
}
// Check y-axis
if (d.y == 0.0f) {
// Empty or infinite inverval on y
if (
(stationaryBox.min.y >= movingBox.max.y) ||
(stationaryBox.max.y <= movingBox.min.y)
) {
// Empty time interval, so no intersection
return kNoIntersection;
}
// Inifinite time interval - no update necessary
} else {
// Divide once
float oneOverD = 1.0f / d.y;
// Compute time value when they begin and end overlapping
float yEnter = (stationaryBox.min.y - movingBox.max.y) * oneOverD;
float yLeave = (stationaryBox.max.y - movingBox.min.y) * oneOverD;
// Check for interval out of order
if (yEnter > yLeave) {
swap(yEnter, yLeave);
}
// Update interval
if (yEnter > tEnter) tEnter = yEnter;
if (yLeave < tLeave) tLeave = yLeave;
// Check if this resulted in empty interval
if (tEnter > tLeave) {
return kNoIntersection;
}
}
// Check z-axis
if (d.z == 0.0f) {
// Empty or infinite inverval on z
if (
(stationaryBox.min.z >= movingBox.max.z) ||
(stationaryBox.max.z <= movingBox.min.z)
) {
// Empty time interval, so no intersection
return kNoIntersection;
}
// Inifinite time interval - no update necessary
} else {
// Divide once
float oneOverD = 1.0f / d.z;
// Compute time value when they begin and end overlapping
float zEnter = (stationaryBox.min.z - movingBox.max.z) * oneOverD;
float zLeave = (stationaryBox.max.z - movingBox.min.z) * oneOverD;
// Check for interval out of order
if (zEnter > zLeave) {
swap(zEnter, zLeave);
}
// Update interval
if (zEnter > tEnter) tEnter = zEnter;
if (zLeave < tLeave) tLeave = zLeave;
// Check if this resulted in empty interval
if (tEnter > tLeave) {
return kNoIntersection;
}
}
// OK, we have an intersection. Return the parametric point in time
// where the intersection occurs
return tEnter;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -