一些基础的东西
ICollide
接口
声明了一些回调函数,检测到两个节点碰撞后调用。bullet里还有一些默认的实现。
比如btDbvtTreeCollider::Process
就将两个节点放到btDbvtBroadphase
的碰撞对缓存btOverlappingPairCache
中
btDbvtProxy
继承btBroadphaseProxy
,定义了一个object可以和哪些group的object碰撞,以及自己属于哪个group
aabb树的raycast
和树中的每个aabb测试,如果成功:如果是叶子节点,则执行回调;否则深度优先搜索孩子节点
aabb的raycast
bool btRayAabb2(const btVector3& rayFrom,
const btVector3& rayInvDirection, // 射线方向的倒数
const unsigned int raySign[3], // 射线三个分量的符号,负数是1,正数是0,便于区分射线起点离aabb两个相对的面的哪个更近
const btVector3 bounds[2],
btScalar& tmin,
btScalar lambda_min, // 0
btScalar lambda_max) // 射线长度
{
btScalar tmax, tymin, tymax, tzmin, tzmax;
tmin = (bounds[raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX(); // 射入x的
tmax = (bounds[1-raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX(); // 射出x的
tymin = (bounds[raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY(); // 射入y的
tymax = (bounds[1-raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();// 射出y的
if ( (tmin > tymax) || (tymin > tmax) )
return false;
if (tymin > tmin)
tmin = tymin;
if (tymax < tmax)
tmax = tymax;
tzmin = (bounds[raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
tzmax = (bounds[1-raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
if ( (tmin > tzmax) || (tzmin > tmax) )
return false;
if (tzmin > tmin)
tmin = tzmin;
if (tzmax < tmax)
tmax = tzmax;
return ( (tmin < lambda_max) && (tmax > lambda_min) ); // t要比0大,比射线长度小。t小于0说明射线是原理aabb的
}
Slabs method算法
总共4个表示射线的长度,分别是射入x=x0、射出x=x1、射入y=y0、射出y=y1的长度
如果射出的两个长度中较小的(tmax),大于 射入的两个长度中较大的(tmin),则有可能相交
求射线的长度:
光线的参数方程为R(t) = O + t * Dir, t就是射线的长度
一般平面方程为aX+bY+cZ+d=0,因为AABB的六个面分别平行于XY、XZ、YZ平面,所以平面的方程为X=d,Y=d,Z=d
光线与垂直于x轴的两个面相交时,t = (d - O.x) / Dir.x
光线与垂直于y轴的两个面相交时,t = (d - O.y) / Dir.y
光线与垂直于z轴的两个面相交时,t = (d - O.z) / Dir.z