#include "StdAfx.h"
#include "AABB3.h"
#include "Matrix.h"
#include "Sphere.h"
#include "Plane.h"
//---------------------------------------------------------------------------
// AABB3::corner
//
// 返回8个端点中的一个,端点编号如下:
//
// 2 3
// ------------------------------
// /| /|
// / | / |
// / | / |
// / | / |
// / | / |
// / | / |
// / | / |
// / | / |
// / | / |
// 6 / | 7 / |
// /----------------------------/ |
// | | | |
// | | | | +Y
// | 0 | | |
// | |-----------------|----------| |
// | / | / 1 |
// | / | / |
// | / | / |
// | / | / |
// | / | / |
// | / | / |
// | / | / |
// | / | / |
// | / | / |
// |/ |/ /----------------- +X
// ------------------------------ /
// 4 5 /
// /
// Bit 0 selects min.x vs. max.x +Z
// Bit 1 selects min.y vs. max.y
// Bit 2 selects min.z vs. max.z
//-------------------------------------------------------------------------------
// 获取盒子的一个顶点
//-------------------------------------------------------------------------------
Vector3 AABB3::Corner(int i) const
{
// 确认索引有效...
assert(i >= 0);
assert(i <= 7);
// 返回它
return Vector3(
(i & 1) ? max.x : min.x,
(i & 2) ? max.y : min.y,
(i & 4) ? max.z : min.z
);
}
//-------------------------------------------------------------------------------
// 把盒子置空
//-------------------------------------------------------------------------------
void AABB3::Empty()
{
const float kBigNumber = 1e37f;
min.x = min.y = min.z = kBigNumber;
max.x = max.y = max.z = -kBigNumber;
}
//-------------------------------------------------------------------------------
// 增加一个点
//-------------------------------------------------------------------------------
void AABB3::Add(const Vector3 &p)
{
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;
}
//-------------------------------------------------------------------------------
// 增加一个盒子
//-------------------------------------------------------------------------------
void AABB3::Add(const AABB3 &box)
{
if (box.min.x < min.x) min.x = box.min.x;
if (box.max.x > max.x) max.x = box.max.x;
if (box.min.y < min.y) min.y = box.min.y;
if (box.max.y > max.y) max.y = box.max.y;
if (box.min.z < min.z) min.z = box.min.z;
if (box.max.z > max.z) max.z = box.max.z;
}
//-------------------------------------------------------------------------------
// 变换盒子,并且计算新的盒子,新的盒子可能比原的大一些
//-------------------------------------------------------------------------------
void AABB3::SetToTransformedBox(const AABB3 &box, const CMatrix44F &m)
{
if (box.IsEmpty())
{
Empty();
return;
}
// 从平移部分开始
min = max = GetTranslation(m);
// 依次检查矩阵的9个元素,计算新的AABB
if (m.m[0] > 0.0f)
{
min.x += m.m[0] * box.min.x; max.x += m.m[0] * box.max.x;
}
else
{
min.x += m.m[0] * box.max.x; max.x += m.m[0] * box.min.x;
}
if (m.m[1] > 0.0f)
{
min.y += m.m[1] * box.min.x; max.y += m.m[1] * box.max.x;
}
else
{
min.y += m.m[1] * box.max.x; max.y += m.m[1] * box.min.x;
}
if (m.m[2] > 0.0f)
{
min.z += m.m[2] * box.min.x; max.z += m.m[2] * box.max.x;
}
else
{
min.z += m.m[2] * box.max.x; max.z += m.m[2] * box.min.x;
}
if (m.m[4] > 0.0f)
{
min.x += m.m[4] * box.min.y; max.x += m.m[4] * box.max.y;
}
else
{
min.x += m.m[4] * box.max.y; max.x += m.m[4] * box.min.y;
}
if (m.m[5] > 0.0f)
{
min.y += m.m[5] * box.min.y; max.y += m.m[5] * box.max.y;
}
else
{
min.y += m.m[5] * box.max.y; max.y += m.m[5] * box.min.y;
}
if (m.m[6] > 0.0f)
{
min.z += m.m[6] * box.min.y; max.z += m.m[6] * box.max.y;
}
else
{
min.z += m.m[6] * box.max.y; max.z += m.m[6] * box.min.y;
}
if (m.m[8] > 0.0f)
{
min.x += m.m[8] * box.min.z; max.x += m.m[8] * box.max.z;
}
else
{
min.x += m.m[8] * box.max.z; max.x += m.m[8] * box.min.z;
}
if (m.m[9] > 0.0f)
{
min.y += m.m[9] * box.min.z; max.y += m.m[9] * box.max.z;
}
else
{
min.y += m.m[9] * box.max.z; max.y += m.m[9] * box.min.z;
}
if (m.m[10] > 0.0f)
{
min.z += m.m[10] * box.min.z; max.z += m.m[10] * box.max.z;
}
else
{
min.z += m.m[10] * box.max.z; max.z += m.m[10] * box.min.z;
}
}
//-------------------------------------------------------------------------------
// 判断盒子是否为空
//-------------------------------------------------------------------------------
bool AABB3::IsEmpty() const
{
return (min.x > max.x) || (min.y > max.y) || (min.z > max.z);
}
//-------------------------------------------------------------------------------
// 判断盒子是否包含特定点
//-------------------------------------------------------------------------------
bool AABB3::Contains(const Vector3 &p) const
{
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);
}
//-------------------------------------------------------------------------------
// 返回盒子上与特定点最近的一点
//-------------------------------------------------------------------------------
Vector3 AABB3::ClosestPointTo(const Vector3 &p) const
{
// 在每一轴将p“推向”矩形边界框
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 r;
}
//-------------------------------------------------------------------------------
// 判断是否和特定的球重叠了
//-------------------------------------------------------------------------------
bool AABB3::IntersectsSphere(const CSphere &sph) const
{
// 找到矩形边界框上离球心最近的点
Vector3 closestPoint = ClosestPointTo(sph.center);
// 检查最近点到球心的距离是否小于半径
return DistanceSquared(sph.center, closestPoint) < sph.radius * sph.radius;
}
//-------------------------------------------------------------------------------
// 判断与射线的交集,返回时间参数,无碰撞,则返回>1的数
//-------------------------------------------------------------------------------
//-------------------------------------------------------------------------------
// 判断盒子是在特定平面的哪一面
//-------------------------------------------------------------------------------
int AABB3::ClassifyPlane(const CPlane &plane) const
{
// 检查法向量,计算最大和最小D值,即距离
Vector3 n(plane.a, plane.b, plane.c);
float d = plane.d;
评论2
最新资源