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

📄 aabb3.cpp

📁 3D赛车游戏源代码-用Visual Studio 2005
💻 CPP
📖 第 1 页 / 共 2 页
字号:
{
	// 检查法向量,计算最大和最小D值,即距离
	Vector3 n(plane.a, plane.b, plane.c);
	float d = plane.d;

	float minD, maxD;

	if (n.x > 0.f)
	{
		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.f)
	{
		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.f)
	{
		minD += n.z * min.z; 
		maxD += n.z * max.z;
	}
	else
	{
		minD += n.z * max.z;
		maxD += n.z * min.z;
	}

	// 完全在平面的前面
	if (minD >= d)
	{
		return 1;
	}

	// 完全在平面的背面
	if (maxD <= d)
	{
		return -1;
	}

	// 横跨平面
	return 0;
}

//-------------------------------------------------------------------------------
// 动态检测和面的交集,返回时间参数
//-------------------------------------------------------------------------------

//-------------------------------------------------------------------------------
// 跟OBB的碰撞检测
// vRadiiB是传入盒子的尺寸(x,y,z的一半长),假定它在自己空间原点
// mToA是从传入盒子到我们AABB空间的变换矩阵
//-------------------------------------------------------------------------------
bool AABB3::IntersectOBB(const Vector3 &bRadii, const CMatrix44F &mToA) const
{
	Vector3 p;
	mToA.GetRow(3, &p);				// 得到OBB的中心的位置
	Vector3 aCenter = min + max;	
	aCenter *= 0.5f;				// 得到本AABB的位置
	p -= aCenter;					// 这个得到OBB中心到本AABB中心的距离
	Vector3 aRadii = max - min;
	aRadii *= 0.5f;					// AABB的半径

	float absXX, absXY, absXZ;		// X轴的向量方向
	float absYX, absYY, absYZ;		// Y轴的向量方向
	float absZX, absZY, absZZ;		// Z轴的向量方向

	const float * f = mToA.m;

	// 一,先在AABB盒子的每个坐标轴上投影,判断有没有相交

	//                     ***
	//                    *    *
	//                   *      *
	// *************     **   *  * 
	// *           *        **  *
	// *      *    *          **  
	// *           *         
	// *************  bRadii.x * absXX                    
	//                    \/          
	//      |aRadii.x|   |   | | <---bRadii.y * absYX
	//-------------------------------------------------------
    //      |      p.x       |

	// 取出每个轴向量的x分量
	absXX = fabs(f[0]);
	absYX = fabs(f[4]);
	absZX = fabs(f[8]);

	// 如果两个盒子在X轴上的总距离小于两个中心的X距离则没有相交
	if (aRadii.x + bRadii.x * absXX + bRadii.y * absYX + bRadii.z * absZX - fabs(p.x)<0.0f)
		return false;

	// 取出每个轴的y分量
	absXY = fabs(f[1]);
	absYY = fabs(f[5]);
	absZY = fabs(f[9]);

	// 如果两个盒子在Y轴上的总距离小于两个中心的Y距离则没有相交
	if (aRadii.y + bRadii.x * absXY + bRadii.y * absYY + bRadii.z * absZY - fabs(p.y)<0.0f)
		return false;

	// 取出每个轴的z分量
	absXZ = fabs(f[2]);
	absYZ = fabs(f[6]);
	absZZ = fabs(f[10]);

	// 如果两个盒子在Z轴上的总距离小于两个中心的Z距离则没有相交
	if (aRadii.z + bRadii.x * absXZ + bRadii.y * absYZ + bRadii.z * absZZ - fabs(p.z)<0.0f)
		return false;

	// 二、然后在OBB的坐标轴上投影,判断有没有相交

	// 如果两个盒子在OBB的X轴上的总距离小于两个中心的X距离则没有相交
	if (aRadii.x*absXX + aRadii.y*absXY + aRadii.z*absXZ + bRadii.x - fabs(p.x*f[0] + p.y*f[1] + p.z*f[2])<0.0f)
		return false;

	// 如果两个盒子在OBB的Y轴上的总距离小于两个中心的Y距离则没有相交
	if (aRadii.x*absYX + aRadii.y*absYY + aRadii.z*absYZ + bRadii.y - fabs(p.x*f[4] + p.y*f[5] + p.z*f[6])<0.0f)
		return false;		

	// 如果两个盒子在OBB的Z轴上的总距离小于两个中心的Z距离则没有相交
	if (aRadii.x*absZX + aRadii.y*absZY + aRadii.z*absZZ + bRadii.z - fabs(p.x*f[8] + p.y*f[9] + p.z*f[10])<0.0f)
		return false;		

	// 三、在AABB与OBB的三个轴的叉乘向量上投影,判断有没有相交

	// 在两个盒子的X轴叉乘的向量上投影,判断有没有相交
	// 投影轴为:(1, 0, 0) X (f[0], f[1], f[2]) = (0, -f[2], f[1])
	if (fabs(p.z*f[1] - p.y*f[2]) >
		aRadii.y * absXZ + aRadii.z * absXY +
		bRadii.y * absZX + bRadii.z * absYX)
		return false;

	// 投影轴为:(1, 0, 0) X (f[4], f[5], f[6]) = (0, -f[6], f[5])
	if (fabs(p.z*f[5] - p.y*f[6]) >
		aRadii.y * absYZ + aRadii.z * absYY +
		bRadii.x * absZX + bRadii.z * absXX)
		return false;

	// 投影轴为:(1, 0, 0) X (f[8], f[9], f[10]) = (0, -f[10], f[9])
	if (fabs(p.z*f[9] - p.y*f[10]) >
		aRadii.y * absZZ + aRadii.z * absZY +
		bRadii.x * absYX + bRadii.y * absXX)
		return false;

	// 投影轴为:(0, 1, 0) X (f[0], f[1], f[2]) = (f[2], 0, -f[0])
	if (fabs(p.x*f[2] - p.z*f[0]) >
		aRadii.x * absXZ + aRadii.z * absXX +
		bRadii.y * absZY + bRadii.z * absYY)
		return false;

	// 投影轴为:(0, 1, 0) X (f[4], f[5], f[6]) = (f[6], 0, -f[4])
	if (fabs(p.x*f[6] - p.z*f[4]) >
		aRadii.x * absYZ + aRadii.z * absYX +
		bRadii.x * absZY + bRadii.z * absXY)
		return false;

	// 投影轴为:(0, 1, 0) X (f[8], f[9], f[10]) = (f[10], 0, -f[8])
	if (fabs(p.x*f[10] - p.z*f[8]) >
		aRadii.x * absZZ + aRadii.z * absZX +
		bRadii.x * absYY + bRadii.y * absXY)
		return false;

	// 投影轴为:(0, 0, 1) X (f[0], f[1], f[2]) = (-f[1], f[0], 0)
	if (fabs(p.y*f[0] - p.x*f[1]) >
		aRadii.x * absXY + aRadii.y * absXX +
		bRadii.y * absZZ + bRadii.z * absYZ)
		return false;

	// 投影轴为:(0, 0, 1) X (f[4], f[5], f[6]) = (-f[5], f[4], 0)
	if (fabs(p.y*f[4] - p.x*f[5]) >
		aRadii.x * absYY + aRadii.y * absYX +
		bRadii.x * absZZ + bRadii.z * absXZ)
		return false;

	// 投影轴为:(0, 0, 1) X (f[8], f[9], f[10]) = (-f[9], f[8], 0)
	if (fabs(p.y*f[8] - p.x*f[9]) >
		aRadii.x * absZY + aRadii.y * absZX +
		bRadii.x * absYZ + bRadii.y * absXZ)
		return false;

	return true;
}

//-------------------------------------------------------------------------------
// 判断两个盒子是否重叠了,还可以通过参数返回重叠部分。
//-------------------------------------------------------------------------------
bool    IntersectAABBs(const AABB3 &box1, const AABB3 &box2, AABB3 *boxIntersect) 
{

	// 检测没有重叠的情况
	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;

	// 有重叠,如果需要返回重叠部分,则计算一下
	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);
	}

	// 返回相交了
    return true;
}

//-------------------------------------------------------------------------------
//  动态检测两个盒子的碰撞,返回时间参数,无碰撞,则返回>1的数
//-------------------------------------------------------------------------------



// AABB与三角形的相交
/////   1.   判断三角形的任一顶点是否被AABB包含   
/////   2.   判断三角形的任一边是否与AABB相交   
/////         2.1   先判断任一边所在射线与AABB是否相交   
/////         2.2   再判断相交点距离是否小于这条边的边长   
/////   </remarks>   
/////   <param   name="aabb"></param>   
/////   <param   name="A">三角形顶点一</param>   
/////   <param   name="B">三角形顶点二</param>   
/////   <param   name="C">三角形顶点三</param>   
/////   <returns>相交情况</returns>   
//public   static   bool   Intersects(AxisAlignedBox   aabb,   Vector3   A,   Vector3   B,   Vector3   C)   
//{   
//	if (aabb.IsContainVector(A)   ||   aabb.IsContainVector(B)||   aabb.IsContainVector(C))   
//		return   true;   
//
//	Vector3[]   vertexs   =   new   Vector3[]{A,B,C};   
//	Vector3[]   edges   =   new   Vector3[]{B   -   A,   C   -   B,   A   -   C};   
//	Ray   ray   =   null; IntersectResult   result;   
//
//	for(int   i   =   0;   i   <   3;   i++)   
//	{   
//		ray   =   new   Ray(vertexs[i],   edges[i]);   
//		result   =   Intersects(ray,   aabb);   
//		if(result.Hit   &&   result.Distance   *   result.Distance   <   edges[i].LengthSq())   
//			return   true;   
//	}   
//	return   false;   
//}   

/////   <summary>   
/////   是否与指定的AABB相交   
/////   </summary>   
/////   <param   name="box"></param>   
/////   <returns></returns>   
//public   override   Intersection   Intersect(AxisAlignedBox   box)   
//{   
//	Intersection   result   =   base.Intersect(box);   
//	//   如果与AABB相交,再进行三角形级别的碰撞检测   
//	if(result   !=   Intersection.None)   
//	{   
//		Matrix   M   =   this.ParentNodeFullTransform;   
//		Vector3   A,B,C;   
//		for(int   i   =   0;   i   <   this.mesh.Geom.TriangleCount;   i++)   
//		{   
//			A   =   Vector3.TransformCoordinate(this.mesh.Geom.Vertices[this.mesh.Geom.TriangleIndex[i   *   3]],   M);   
//			B   =   Vector3.TransformCoordinate(this.mesh.Geom.Vertices[this.mesh.Geom.TriangleIndex[i   *   3   +   1]],   M);   
//			C   =   Vector3.TransformCoordinate(this.mesh.Geom.Vertices[this.mesh.Geom.TriangleIndex[i   *   3   +   2]],   M);   
//			if(Smart.Maths.MathUtil.Intersects(box,   A,   B,   C))   
//				return   Intersection.Partial;   
//		}   
//	}   
//	return   Intersection.None;   
//}   

⌨️ 快捷键说明

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