⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aabb3.cpp

📁 3D数学基础:图形与游戏开发书籍源码,里面有很多实用的代码,对做3D的同志很有意义
💻 CPP
📖 第 1 页 / 共 2 页
字号:
				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 + -