游戏碰撞检测 AABB包围体 sphere 圆形包围体计算
2013-10-28 09:17
1046 查看
包围体Bounding Volumes
有时候我们想要计算一个mesh模型的Bounding Volume。一般使用圆形和AABB。如下图,左边AABB,右边圆形:
圆形是由它的圆心和半径确定其位置,AABB是有其最小和最大顶点确定位置。
使用包围体的原因是可以只测试一个图形就确定这个包围体里面的所有meshes的碰撞状态。
如果希望更加准确的碰撞,那么就可以测试到包围体重合之后,就测试其meshes中的三角形是否重合,重合即碰撞。三角形(ray/triangle intersection)测试会很消耗时间。
我们可以手工计算AABB和圆形包围体,但是Direc3D的D3DX库里面提供了自动计算一个mehs模型的AABB和圆形的。只要知道其顶点数组,那么就可以计算了。
dwStride: 这个参数有点难理解,就是可以定义其往前跳跃的float数,比如顶点的位置格式是FLOAT3,那么就是占3个float位置,如果带了normal单位法向量信息格式FLOAT3,那么也是占3个float位置,但是计算bounding volume不需要normal的信息,只需要位置信息,那么就可以跳过normal的信息,所以设置dwStride为6。
AABB:
一些特别的常量:
如下使用EPSILON::
Bounding Volume类型
可以如下自定义类:
碰撞包围盒例子:
mBox是 ID3DXMesh 对象,存储一个由AABB为边的四方形,然后可以把这个四方形显示出来,当然一般AABB都只是用作碰撞检测,不会直接显示出来的。下面为了显示这个AABB,需要额外功夫去渲染:
transforme mBox.
定义材质:
下面是渲染这个AABB:
总结:
物理碰撞是游戏的一个方向,其数学也非常复杂,但是这些简单的AABB也可以应付不少游戏任务了。
有时候我们想要计算一个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也可以应付不少游戏任务了。
相关文章推荐
- 2D游戏中的碰撞检测:圆形与矩形碰撞检测(Javascript&C++版)
- 2D游戏中圆形与矩形碰撞检测
- 2D游戏中的碰撞检测:圆形与矩形碰撞检测(Javascript&C++版)
- 2D游戏中的碰撞检测:圆形与矩形碰撞检测(Javascript&C++版)
- 2D游戏中圆形与矩形碰撞检测
- Android游戏开发之碰撞检测(矩形碰撞、圆形碰撞、像素碰撞)
- 2D游戏中的碰撞检测:圆形与矩形碰撞检测(Javascrip版)
- Sphere and AABB 包围盒碰撞检测应用
- 2D游戏碰撞检测--矩形与圆形
- 【WP7进阶】——XNA游戏平面矩形碰撞检测 推荐
- 利用函数计算实现网络游戏或视频直播中的敏感词检测
- [Game] 游戏开发中的数学和物理算法:圆和球的碰撞检测
- 自己封装的三维AABB包围盒类,用于三维模型静态碰撞检测,可以直接调用,使用OpenGL进行绘制
- cocos2d-x游戏开发系列教程-坦克大战游戏之坦克和地图碰撞的检测下
- (译)碰撞检测和收集物品:如何使用cocos2d制作基于tiled地图的游戏:第二部分
- Flash游戏学习笔记:矩形检测碰撞
- 游戏中的碰撞检测
- Android游戏开发十日通(4)-行走,跳跃,碰撞检测
- Cocos2d-x 3.2 lua飞机大战开发实例(三)道具的掉落,碰撞检测,声音,分数,爆炸效果,完善游戏的功能细节
- 游戏开发基础--碰撞检测