Bullet 物理引擎 详细分析 Dbvt (4)
光線與AABB 相交檢測:
這是一個非常經典的問題, <<real time collision detection>> 5.33章節有非常詳盡的討論。
下面是光線的方程
?? t是可變參數, P是光線的起始點 RayFrom, d是光線的方向向量
下面這個是平面的方程
??
向量n是平面的法向量,所以如果光線與任何一個平面相交,應該有如下等式
?
對于AABB來說是六個平面, 每個面的法向量為(0,0,1)(0,1,0) ..... 總之三個坐標有兩個是0,另外的一個是1或者-1
AABB同時是3個平面槽的交集, 光線與AABB最多有2個相交點,一個是前景點,一個后景點,分別與兩個平面相交。
特例是完全與一個平面重合。可以被認為是和相鄰的兩個平面相交。
btRayAabb2.是bullet中用于檢測的相關函數
view plaincopy to clipboardprint?
SIMD_FORCE_INLINE bool btRayAabb2(const btVector3& rayFrom,? // point P??
const btVector3& rayInvDirection,? // Direction Vector inverse??
const unsigned int raySign[3],??
const btVector3 bounds[2],??? // min x, max x AABB volume??
btScalar& tmin,??
btScalar lambda_min,??
btScalar lambda_max)??
{??
btScalar tmax, tymin, tymax, tzmin, tzmax;??
// get the far plane intersect param t along x axis??
tmax = (bounds[1-raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();??
// get the near plane intersect param t along y axis??
tymin = (bounds[raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();??
// get the far plane intersect param t along y axis??
tymax = (bounds[1-raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();??
// if it is not intersect with any plane then exit??
if ( (tmin > tymax) || (tymin > tmax) )??
return false;??
if (tymin > tmin)??
tmin = tymin;? // update the tmin??
if (tymax < tmax)??
tmax = tymax; // update tmax??
// get the near plane intersect param t along Z axis??
tzmin = (bounds[raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();??
// get the far plane intersect param t along Z axis??
tzmax = (bounds[1-raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();??
// if it is not intersect with any plane then exit??
if ( (tmin > tzmax) || (tzmin > tmax) )??
return false;??
// caculate the interval??
if (tzmin > tmin)??
tmin = tzmin;?? // if find nearer point update tmin??
if (tzmax < tmax)??
tmax = tzmax;?? // if found the farer point update tmax??
return ( (tmin < lambda_max) && (tmax > lambda_min) );??
}?
SIMD_FORCE_INLINE bool btRayAabb2(const btVector3& rayFrom,? // point P
const btVector3& rayInvDirection,? // Direction Vector inverse
const unsigned int raySign[3],
const btVector3 bounds[2],??? // min x, max x AABB volume
btScalar& tmin,
btScalar lambda_min,
btScalar lambda_max)
{
btScalar tmax, tymin, tymax, tzmin, tzmax;
// get the far plane intersect param t along x axis
tmax = (bounds[1-raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
// get the near plane intersect param t along y axis
tymin = (bounds[raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
// get the far plane intersect param t along y axis
tymax = (bounds[1-raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
// if it is not intersect with any plane then exit
if ( (tmin > tymax) || (tymin > tmax) )
return false;
if (tymin > tmin)
tmin = tymin;? // update the tmin
if (tymax < tmax)
tmax = tymax; // update tmax
// get the near plane intersect param t along Z axis
tzmin = (bounds[raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
// get the far plane intersect param t along Z axis
tzmax = (bounds[1-raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
// if it is not intersect with any plane then exit
if ( (tmin > tzmax) || (tzmin > tmax) )
return false;
// caculate the interval
if (tzmin > tmin)
tmin = tzmin;?? // if find nearer point update tmin
if (tzmax < tmax)
tmax = tzmax;?? // if found the farer point update tmax
return ( (tmin < lambda_max) && (tmax > lambda_min) );
}
現在可以討論ayTestInternal 函數, 這個函數基本的算法就是遍歷所有的節點(基于棧)
光線講和樹中的每個節點做相交測試,如果相交就繼續處理對應的子結點,否則就跳過。
對應所有最終的相交葉子節點,調用相交處理邏輯(回調函數)來處理。
view plaincopy to clipboardprint?
do?
{??
//pop out the top of stack??
const btDbvtNode* node=stack[--depth];??
//set up the AABB BOX??
bounds[0] = node->volume.Mins()-aabbMax;??
bounds[1] = node->volume.Maxs()-aabbMin;??
btScalar tmin=1.f,lambda_min=0.f;??
unsigned int result1=false;??
// Do the intersect tes t!!??
result1 = btRayAabb2(rayFrom,rayDirectionInverse,??
signs,bounds,tmin,lambda_min,??
lambda_max);??
if(result1)??
{??
//if test pass??
if(node->isinternal())??
{ //if node is intertal??
if(depth>treshold) //dynamic expand stack??
{??
stack.resize(stack.size()*2);??
treshold=stack.size()-2;??
}??
//push the left child into stack??
stack[depth++]=node->childs[0];??
//push the right child into stack??
stack[depth++]=node->childs[1];??
}??
else?
{??
//if node is leaf node,then process it by callback??
policy.Process(node);??
}??
}??
} while(depth);?
?
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/superwiles/archive/2010/03/16/5383896.aspx
轉載于:https://www.cnblogs.com/lancidie/archive/2011/03/02/1968585.html
總結
以上是生活随笔為你收集整理的Bullet 物理引擎 详细分析 Dbvt (4)的全部內容,希望文章能夠幫你解決所遇到的問題。