检查射线碰撞主要用到的是Direct中的D3DXIntersect函数。
HRESULT D3DXIntersect(
__in LPD3DXBASEMESH pMesh, //碰撞模型的Mesh
__in const D3DXVECTOR3 *pRayPos, //射线的位置
__in const D3DXVECTOR3 *pRayDir, //射线的方向
__out BOOL *pHit, //是否碰撞到
__out DWORD *pFaceIndex, //碰撞到面的索引
__out FLOAT *pU, //面的U坐标
__out FLOAT *pV, //面的V坐标
__out FLOAT *pDist, //射线到碰撞点的距离
__out LPD3DXBUFFER *ppAllHits, //如果碰撞到多个点,返回这些点缓存的头指针(D3DXINTERSECTINFO类型的结构体)
__out DWORD *pCountOfHits //碰撞到多少个点
);
我在CMeshBaseOBJ类中重新封装了检测碰撞的函数,返回的结构体CInterSect比D3DXINTERSECTINFO多了法线的结构,用来解决当物体上坡时,多个退的物体移动时需要改变上方向的问题。
//参数分别为射线位置,方向,是否计算法线,返回碰撞的结果体
HRESULT hr = D3DXIntersect(mMesh, &Pos, &Dir,
&pInterSect->u, &pInterSect->v,
&pInterSect->Dist, NULL, NULL);
hr = mMeshForVector->LockIndexBuffer(D3DLOCK_READONLY, (void**)&pIB);
I[0] = pIB[pInterSect->FaceIndex*3+0];
I[1] = pIB[pInterSect->FaceIndex*3+1];
I[2] = pIB[pInterSect->FaceIndex*3+2];
mMeshForVector->UnlockIndexBuffer();
hr = mMeshForVector->LockVertexBuffer(D3DLOCK_READONLY, (void**)&pVB);
mMeshForVector->UnlockVertexBuffer();
V1 = D3DXVECTOR3(V[1]) - D3DXVECTOR3(V[0]);
V2 = D3DXVECTOR3(V[2]) - D3DXVECTOR3(V[0]);
D3DXVec3Cross(&Norm, &V1, &V2);
D3DXVec3Normalize(&Norm, &Norm);
pInterSect->FaceNormal = (D3DVECTOR)Norm;
这时在物体的渲染时,就可以加入检查和地图的碰撞。先用ForceOnMap函数来把一个物体固定在一个地图上
//pForceMap为地图的指针,ForeHeight为地图的高度,UWM为枚举类型表示是否物体的上方向随地形变化
void CXVisOBJ::ForceOnMap( void* pForceMap, float ForecHeight, UpOnWithMap UWM)
然后再调用CXVisOBJ的Update方法来时时检查和地形的碰撞,并且根据枚举类型来决定物体是否上方向发生改变
void CXVisOBJ::Update( float fPass )
D3DXVECTOR3 Pos(mXPos.mPos.x, mXPos.mPos.y+50, mXPos.mPos.z), Dir(0, -1, 0);
bool bHit = ((CMapCell*)mForcedMap)->CheckInterSect(Pos, Dir, mUWM == uwmMap, &InterSect);
float y = mXPos.mPos.y + 50 - InterSect.Dist+mForcedHeight;
mXPos.SetUpWithDir(mUpWithMap);
浙公网安备 33010602011771号