游戏碰撞检测 AABB包围体 sphere 圆形包围体计算
来源:互联网 发布:招商银行行情软件 编辑:程序博客网 时间:2024/05/16 07:42
包围体Bounding Volumes
有时候我们想要计算一个mesh模型的Bounding Volume。一般使用圆形和AABB。如下图,左边AABB,右边圆形:
圆形是由它的圆心和半径确定其位置,AABB是有其最小和最大顶点确定位置。
使用包围体的原因是可以只测试一个图形就确定这个包围体里面的所有meshes的碰撞状态。
如果希望更加准确的碰撞,那么就可以测试到包围体重合之后,就测试其meshes中的三角形是否重合,重合即碰撞。三角形(ray/triangle intersection)测试会很消耗时间。
我们可以手工计算AABB和圆形包围体,但是Direc3D的D3DX库里面提供了自动计算一个mehs模型的AABB和圆形的。只要知道其顶点数组,那么就可以计算了。
HRESULT D3DXComputeBoundingSphere( LPD3DXVECTOR3 pFirstPosition, DWORD NumVertices, DWORD dwStride, D3DXVECTOR3* pCenter, FLOAT* pRadius);
dwStride: 这个参数有点难理解,就是可以定义其往前跳跃的float数,比如顶点的位置格式是FLOAT3,那么就是占3个float位置,如果带了normal单位法向量信息格式FLOAT3,那么也是占3个float位置,但是计算bounding volume不需要normal的信息,只需要位置信息,那么就可以跳过normal的信息,所以设置dwStride为6。
AABB:
HRESULT D3DXComputeBoundingBox( LPD3DXVECTOR3 pFirstPosition, DWORD NumVertices, DWORD dwStride, D3DXVECTOR3* pMin, D3DXVECTOR3* pMax);
一些特别的常量:
const float INFINITY = FLT_MAX;//float的最大值const float EPSILON = 0.001f;//少于这个数的就当做0.不直接设置为零,因为计算机表示浮点数本来就不是概念中那么精确的。
如下使用EPSILON::
bool Equals(float lhs, float rhs){ // if lhs == rhs their difference should be zero return fabs(lhs - rhs) < EPSILON ? true : false;}
Bounding Volume类型
可以如下自定义类:
struct AABB{ // Initialize to an infinitely small AABB. AABB() : minPt(INFINITY, INFINITY, INFINITY), maxPt(-INFINITY, -INFINITY, -INFINITY){} D3DXVECTOR3 center() { return 0.5f*(minPt+maxPt); } D3DXVECTOR3 minPt; D3DXVECTOR3 maxPt;};struct BoundingSphere{ BoundingSphere() : pos(0.0f, 0.0f, 0.0f), radius(0.0f){} D3DXVECTOR3 pos; float radius;};
碰撞包围盒例子:
LoadXFile("skullocc.x", &mMesh, mMtrl, mTex);//自动转换mMesh顶点属性为(position, normal, texture)带位置单位法向量和纹理的格式。D3DXMatrixIdentity(&mWorld);// Compute the bounding box.VertexPNT* v = 0;HR(mMesh->LockVertexBuffer(0, (void**)&v));HR(D3DXComputeBoundingBox(&v[0].pos, mMesh->GetNumVertices(), sizeof(VertexPNT), &mBoundingBox.minPt, &mBoundingBox.maxPt));//是用sizeof计算其往前跳跃数HR(mMesh->UnlockVertexBuffer());
float width = mBoundingBox.maxPt.x - mBoundingBox.minPt.x;float height = mBoundingBox.maxPt.y - mBoundingBox.minPt.y;float depth = mBoundingBox.maxPt.z - mBoundingBox.minPt.z;// Build a box mesh so that we can render the bounding box visually.HR(D3DXCreateBox(gd3dDevice, width, height, depth, &mBox, 0));
mBox是 ID3DXMesh 对象,存储一个由AABB为边的四方形,然后可以把这个四方形显示出来,当然一般AABB都只是用作碰撞检测,不会直接显示出来的。下面为了显示这个AABB,需要额外功夫去渲染:
transforme mBox.
D3DXVECTOR3 center = mBoundingBox.center(); D3DXMatrixTranslation(&mBoundingBoxOffset, center.x, center.y, center.z);
定义材质:
// Define the box material--make semi-transparent.mBoxMtrl.ambient = D3DXCOLOR(0.0f, 0.0f, 1.0f, 1.0f);mBoxMtrl.diffuse = D3DXCOLOR(0.0f, 0.0f, 1.0f, 0.5f);mBoxMtrl.spec = D3DXCOLOR(0.5f, 0.5f, 0.5f, 1.0f);mBoxMtrl.specPower = 8.0f;
下面是渲染这个AABB:
// Draw the bounding box with alpha blending.HR(gd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true));HR(gd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA));HR(gd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA));HR(mFX->SetMatrix(mhWVP, &(mBoundingBoxOffset*mView*mProj)));D3DXMatrixInverse(&worldInvTrans, 0, &mBoundingBoxOffset);D3DXMatrixTranspose(&worldInvTrans, &worldInvTrans);HR(mFX->SetMatrix(mhWorldInvTrans, &worldInvTrans));HR(mFX->SetMatrix(mhWorld, &mBoundingBoxOffset));HR(mFX->SetValue(mhMtrl, &mBoxMtrl, sizeof(Mtrl)));HR(mFX->SetTexture(mhTex, mWhiteTex));HR(mFX->CommitChanges());HR(mBox->DrawSubset(0));HR(gd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false));
总结:
物理碰撞是游戏的一个方向,其数学也非常复杂,但是这些简单的AABB也可以应付不少游戏任务了。
- 游戏碰撞检测 AABB包围体 sphere 圆形包围体计算
- Sphere and AABB 包围盒碰撞检测应用
- D3D11 包围体碰撞检测
- 【U3D】AABB包围体
- aabb与oob包围盒 碰撞检测
- 判断平面和AABB包围体是否发生碰撞
- 《实时碰撞检测算法技术》读书笔记(二):轴对齐包围盒(AABB)的计算与更新
- 碰撞检测 包围盒 包围球 XNA
- AABB包围盒碰撞的理解
- 包围盒性能对比测试AABB vs OBB vs Sphere
- [OpenGL]基于AABB包围盒的漫游时视点与场景的碰撞检测
- 包围球与包围盒的碰撞检测
- AABB轴向包围盒
- AABB包围盒算法
- AABB轴向包围盒
- AABB包围盒详解
- [OpenGL] AABB包围盒
- 《实时碰撞检测算法技术》读书笔记(一):包围体(BV)
- 笔记本开机数字小键盘自动打开问题
- [转][重构到模式-Decorator Pattern]咖啡连锁店KataStarbuzzCoffee招式-刘成章版
- JS中的call()和apply()方法
- 结构化大数据的几种计算方法(二)
- 2013-C++第9周OJ题目及参考答案
- 游戏碰撞检测 AABB包围体 sphere 圆形包围体计算
- 未来的搜索市场
- 练习求四个数中最大的数
- 超级楼梯
- 第9周项目1-多分段函数的值
- opencv——访问图像元素(imagedata widthstep)
- 手把手教你如何把java代码,打包成jar文件以及转换为exe可执行文件
- 浅析Hadoop文件格式
- Weblogic跨域session冲突解决办法