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

📄 aabb3.cpp

📁 3D数学基础:图形与游戏开发书籍源码,里面有很多实用的代码,对做3D的同志很有意义
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/////////////////////////////////////////////////////////////////////////////
//
// 3D Math Primer for Games and Graphics Development
//
// AABB3.cpp - Implementation for class AABB3
//
// Visit gamemath.com for the latest version of this file.
//
// For more details, see Chapter 12
//
/////////////////////////////////////////////////////////////////////////////

#include <assert.h>
#include <stdlib.h>

#include "AABB3.h"
#include "Matrix4x3.h"
#include "CommonStuff.h"

/////////////////////////////////////////////////////////////////////////////
//
// class AABB3 member functions
//
/////////////////////////////////////////////////////////////////////////////

//---------------------------------------------------------------------------
// AABB3::corner
//
// Return one of the 8 corner points.  The points are numbered as follows:
//
//            6                                7
//              ------------------------------
//             /|                           /|
//            / |                          / |
//           /  |                         /  |
//          /   |                        /   |
//         /    |                       /    |
//        /     |                      /     |
//       /      |                     /      |
//      /       |                    /       |
//     /        |                   /        |
//  2 /         |                3 /         |
//   /----------------------------/          |
//   |          |                 |          |
//   |          |                 |          |      +Y
//   |        4 |                 |          | 
//   |          |-----------------|----------|      |
//   |         /                  |         /  5    |
//   |        /                   |        /        |       +Z
//   |       /                    |       /         |
//   |      /                     |      /          |     /
//   |     /                      |     /           |    /
//   |    /                       |    /            |   /
//   |   /                        |   /             |  /
//   |  /                         |  /              | /
//   | /                          | /               |/
//   |/                           |/                ----------------- +X
//   ------------------------------
//  0                              1
//
// Bit 0 selects min.x vs. max.x
// Bit 1 selects min.y vs. max.y
// Bit 2 selects min.z vs. max.z

Vector3 AABB3::corner(int i) const {

	// Make sure index is in range...

	assert(i >= 0);
	assert(i <= 7);

	// Return it

	return Vector3(
		(i & 1) ? max.x : min.x,
		(i & 2) ? max.y : min.y,
		(i & 4) ? max.z : min.z
	);
}

//---------------------------------------------------------------------------
// AABB3::empty
//
// "Empty" the box, by setting the values to really
// large/small numbers

void    AABB3::empty() {
	const float kBigNumber = 1e37f;
	min.x = min.y = min.z = kBigNumber;
	max.x = max.y = max.z = -kBigNumber;
}

//---------------------------------------------------------------------------
// AABB3::add
//
// Add a point to the box

void    AABB3::add(const Vector3 &p) {

	// Expand the box as necessary to contain the point.

	if (p.x < min.x) min.x = p.x;
	if (p.x > max.x) max.x = p.x;
	if (p.y < min.y) min.y = p.y;
	if (p.y > max.y) max.y = p.y;
	if (p.z < min.z) min.z = p.z;
	if (p.z > max.z) max.z = p.z;
}

//---------------------------------------------------------------------------
// AABB3::add
//
// Add an AABB to the box

void    AABB3::add(const AABB3 &box) {

	// Expand the box as necessary.

	if (box.min.x < min.x) min.x = box.min.x;
	if (box.min.x > max.x) max.x = box.min.x;
	if (box.min.y < min.y) min.y = box.min.y;
	if (box.min.y > max.y) max.y = box.min.y;
	if (box.min.z < min.z) min.z = box.min.z;
	if (box.min.z > max.z) max.z = box.min.z;
}

//---------------------------------------------------------------------------
// AABB3::setToTransformedBox
//
// Transform the box and compute the new AABB.  Remember, this always
// results in an AABB that is at least as big as the origin, and may be
// considerably bigger.
//
// See 12.4.4

void    AABB3::setToTransformedBox(const AABB3 &box, const Matrix4x3 &m) {

	// If we're empty, then bail

	if (box.isEmpty()) {
		empty();
		return;
	}

	// Start with the translation portion

	min = max = getTranslation(m);

	// Examine each of the 9 matrix elements
	// and compute the new AABB

	if (m.m11 > 0.0f) {
		min.x += m.m11 * box.min.x; max.x += m.m11 * box.max.x;
	} else {
		min.x += m.m11 * box.max.x; max.x += m.m11 * box.min.x;
	}

	if (m.m12 > 0.0f) {
		min.y += m.m12 * box.min.x; max.y += m.m12 * box.max.x;
	} else {
		min.y += m.m12 * box.max.x; max.y += m.m12 * box.min.x;
	}

	if (m.m13 > 0.0f) {
		min.z += m.m13 * box.min.x; max.z += m.m13 * box.max.x;
	} else {
		min.z += m.m13 * box.max.x; max.z += m.m13 * box.min.x;
	}

	if (m.m21 > 0.0f) {
		min.x += m.m21 * box.min.y; max.x += m.m21 * box.max.y;
	} else {
		min.x += m.m21 * box.max.y; max.x += m.m21 * box.min.y;
	}

	if (m.m22 > 0.0f) {
		min.y += m.m22 * box.min.y; max.y += m.m22 * box.max.y;
	} else {
		min.y += m.m22 * box.max.y; max.y += m.m22 * box.min.y;
	}

	if (m.m23 > 0.0f) {
		min.z += m.m23 * box.min.y; max.z += m.m23 * box.max.y;
	} else {
		min.z += m.m23 * box.max.y; max.z += m.m23 * box.min.y;
	}

	if (m.m31 > 0.0f) {
		min.x += m.m31 * box.min.z; max.x += m.m31 * box.max.z;
	} else {
		min.x += m.m31 * box.max.z; max.x += m.m31 * box.min.z;
	}

	if (m.m32 > 0.0f) {
		min.y += m.m32 * box.min.z; max.y += m.m32 * box.max.z;
	} else {
		min.y += m.m32 * box.max.z; max.y += m.m32 * box.min.z;
	}

	if (m.m33 > 0.0f) {
		min.z += m.m33 * box.min.z; max.z += m.m33 * box.max.z;
	} else {
		min.z += m.m33 * box.max.z; max.z += m.m33 * box.min.z;
	}
}

//---------------------------------------------------------------------------
// AABB3::isEmpty
//
// Return true if the box is enmpty

bool    AABB3::isEmpty() const {

	// Check if we're inverted on any axis

	return (min.x > max.x) || (min.y > max.y) || (min.z > max.z);
}

//---------------------------------------------------------------------------
// AABB3::contains
//
// Return true if the box contains a point

bool    AABB3::contains(const Vector3 &p) const {

	// Check for overlap on each axis

	return
		(p.x >= min.x) && (p.x <= max.x) &&
		(p.y >= min.y) && (p.y <= max.y) &&
		(p.z >= min.z) && (p.z <= max.z);
}

//---------------------------------------------------------------------------
// AABB3::closestPointTo
//
// Return the closest point on this box to another point

Vector3 AABB3::closestPointTo(const Vector3 &p) const {

	// "Push" p into the box, on each dimension

	Vector3 r;

	if (p.x < min.x) {
		r.x = min.x;
	} else if (p.x > max.x) {
		r.x = max.x;
	} else {
		r.x = p.x;
	}

	if (p.y < min.y) {
		r.y = min.y;
	} else if (p.y > max.y) {
		r.y = max.y;
	} else {
		r.y = p.y;
	}

	if (p.z < min.z) {
		r.z = min.z;
	} else if (p.z > max.z) {
		r.z = max.z;
	} else {
		r.z = p.z;
	}

	// Return it

	return r;
}

//---------------------------------------------------------------------------
// AABB3::intersectsSphere
//
// Return true if we intersect a sphere.  Uses Arvo's algorithm.

bool    AABB3::intersectsSphere(const Vector3 &center, float radius) const {

	// Find the closest point on box to the point

	Vector3 closestPoint = closestPointTo(center);

	// Check if it's within range

	return distanceSquared(center, closestPoint) < radius*radius;
}

//---------------------------------------------------------------------------
// AABB3::rayIntersect
//
// Parametric intersection with a ray.  Returns parametric point
// of intsersection in range 0...1 or a really big number (>1) if no
// intersection.
//
// From "Fast Ray-Box Intersection," by Woo in Graphics Gems I,
// page 395.
//
// See 12.9.11

float   AABB3::rayIntersect(
	const Vector3 &rayOrg,          // orgin of the ray
	const Vector3 &rayDelta,        // length and direction of the ray
	Vector3 *returnNormal           // optionally, the normal is returned
) const {

	// We'll return this huge number if no intersection

	const float kNoIntersection = 1e30f;

	// Check for point inside box, trivial reject, and determine parametric
	// distance to each front face

	bool inside = true;

	float xt, xn;
	if (rayOrg.x < min.x) {
		xt = min.x - rayOrg.x;
		if (xt > rayDelta.x) return kNoIntersection;
		xt /= rayDelta.x;
		inside = false;
		xn = -1.0f;
	} else if (rayOrg.x > max.x) {
		xt = max.x - rayOrg.x;
		if (xt < rayDelta.x) return kNoIntersection;
		xt /= rayDelta.x;
		inside = false;
		xn = 1.0f;
	} else {
		xt = -1.0f;
	}

	float yt, yn;
	if (rayOrg.y < min.y) {
		yt = min.y - rayOrg.y;
		if (yt > rayDelta.y) return kNoIntersection;
		yt /= rayDelta.y;
		inside = false;
		yn = -1.0f;
	} else if (rayOrg.y > max.y) {
		yt = max.y - rayOrg.y;
		if (yt < rayDelta.y) return kNoIntersection;
		yt /= rayDelta.y;
		inside = false;
		yn = 1.0f;
	} else {
		yt = -1.0f;
	}

	float zt, zn;
	if (rayOrg.z < min.z) {
		zt = min.z - rayOrg.z;
		if (zt > rayDelta.z) return kNoIntersection;
		zt /= rayDelta.z;
		inside = false;
		zn = -1.0f;
	} else if (rayOrg.z > max.z) {
		zt = max.z - rayOrg.z;
		if (zt < rayDelta.z) return kNoIntersection;
		zt /= rayDelta.z;
		inside = false;
		zn = 1.0f;
	} else {
		zt = -1.0f;
	}

	// Inside box?

	if (inside) {
		if (returnNormal != NULL) {
			*returnNormal = -rayDelta;
			returnNormal->normalize();
		}
		return 0.0f;
	}

	// Select farthest plane - this is
	// the plane of intersection.

	int which = 0;
	float t = xt;
	if (yt > t) {
		which = 1;
		t = yt;
	}
	if (zt > t) {
		which = 2;
		t = zt;
	}

	switch (which) {

		case 0: // intersect with yz plane
		{
			float y = rayOrg.y + rayDelta.y*t;
			if (y < min.y || y > max.y) return kNoIntersection;
			float z = rayOrg.z + rayDelta.z*t;
			if (z < min.z || z > max.z) return kNoIntersection;

			if (returnNormal != NULL) {
				returnNormal->x = xn;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -