请高手帮我指点一下这个关于网格和鼠标碰撞检测的问题
我是新手,想请大家帮忙。最近看了一段代码这部分实在是看不懂了,这里是地图和鼠标的碰撞检测, 来请教大虾帮忙,代码如下,:
头文件中的内容
#ifndef AFX_CMATH_H
#define AFX_CMATH_H
#define INTERSECT_NEGATIVEY0x10
#define INTERSECT_HORIZENTAL0x30
//Summary:
//Description:计算一个三角形和一个射线的交点
//Parameters:
//orig:射线起始点
//dir:射线的方向
//v0:三角形的第一个顶点
//v1:三角形的第二个顶点
//v2:三角形的第三个顶点
//t:交点到射线起始点的距离
//u:交点在v1-v0上的投影的位置,
//v:交点在v1-v0上的投影的位置, 交点为vRet=v0+u*(v1-v0)+v*(v2-v0)
//Returns:是否有交点
BOOL IntersectTriangle( const D3DXVECTOR3& orig,
const D3DXVECTOR3& dir, const D3DXVECTOR3& v0,
const D3DXVECTOR3& v1, const D3DXVECTOR3& v2,
FLOAT* t, FLOAT* u, FLOAT* v );
//Summary:求射线和网格的交点
//Description:求射线和用顶点缓冲区和索引缓冲区定义的网格的交点
//Parameters:
//pIB:索引缓冲区
//pVB:顶点缓冲区
//nStide:每个顶点的大小
//dwNumFaces:面数
//vRayOrig:射线起始点
//vRayDir:射线的方向
//pVRet:交点
//Returns:是否有交点
BOOL IntersectIndexBuffer(LPDIRECT3DINDEXBUFFER9 pIB,
LPDIRECT3DVERTEXBUFFER9 pVB,
UINT nStride,UINT dwNumFaces,
const D3DVECTOR *vRayOrig,const D3DVECTOR *vRayDir,
D3DVECTOR *pVRet,DWORD dwFlag=0);
#endif
CPP中的内容:
#include <d3d9.h>
#include <d3dx9.h>
#include "CMath.h "
//Summary:求射线和网格的交点
//Description:求射线和用顶点缓冲区和索引缓冲区定义的网格的交点
//Parameters:
//pIB:索引缓冲区
//pVB:顶点缓冲区
//nStide:每个顶点的大小
//dwNumFaces:面数
//vRayOrig:射线起始点
//vRayDir:射线的方向
//pVRet:交点
// dwFlag暂时不用
//Returns:是否有交点
BOOL IntersectIndexBuffer(LPDIRECT3DINDEXBUFFER9 pIB,//实现碰撞检测 的全局函数(顶点缓冲)
LPDIRECT3DVERTEXBUFFER9 pVB,
UINT nStride,UINT dwNumFaces,
const D3DVECTOR *vRayOrig,const D3DVECTOR *vRayDir,D3DVECTOR *pVRet,DWORD dwFlag)
{
WORD*pIndices;
BYTE*pVertices;
D3DINDEXBUFFER_DESC IB_Desc;
FLOAT fBary1, fBary2,fDist=1e+32f;
FLOAT t_fBary1, t_fBary2,t_fDist;
DWORD dwFace=-1;
DWORD dwUpperLower;
D3DXVECTOR3* pV[3];
ULONG n;
pIB-> GetDesc(&IB_Desc);
pIB-> Lock( 0, 0, (void**)&pIndices, 0 );//这里为什么前俩个参数都是0呢?
pVB-> Lock( 0, 0, (void**)&pVertices,0 );
for( DWORD i=0; i <dwNumFaces; i++ )
{
for(int j=0;j <3;j++)
{
if(IB_Desc.Format==D3DFMT_INDEX16)n=(WORD)pIndices[3*i+j];//此处和下面的n的区别,具体就是16位和32位算法的区别
else if(IB_Desc.Format==D3DFMT_INDEX32)
n=*(DWORD*)&pIndices[2*(3*i+j)];
else return FALSE;
pV[j]=(D3DXVECTOR3*)(pVertices+nStride*n);
}
dwUpperLower=0;
if(dwFlag)
{
if(dwFlag & INTERSECT_NEGATIVEY)//此处请高手帮我讲解
{
for(j=0;j <3;j++)
{
dwUpperLower|= vRayOrig-> x > pV[j]-> x ? 0x0010:0x0001;
dwUpperLower|= vRayOrig-> z > pV[j]-> z ? 0x1000:0x0100;
}
if(dwUpperLower!=0x1111) continue;
}
else if(dwFlag & INTERSECT_HORIZENTAL)
{
for(j=0;j <3;j++)
{
dwUpperLower|=(vRayOrig-> y > pV[j]-> y)? 0x0010:0x0001;
}
if(dwUpperLower!=0x0011) continue;
}
}
// 检测是否穿过三角形
if( IntersectTriangle( *vRayOrig, *vRayDir, *pV[0], *pV[1], *pV[2],
&t_fDist, &t_fBary1, &t_fBary2 ) )
{
if(t_fDist < fDist )//是否返回最近的一个点
{
dwFace = i;
fBary1 = t_fBary1;
fBary2 = t_fBary2;
fDist = t_fDist;
}
}
}
if(dwFace <dwNumFaces && dwFace> =0 )
{
for(int j=0;j <3;j++)
{
if(IB_Desc.Format==D3DFMT_INDEX16)n=(WORD)pIndices[3*dwFace +j];
else if(IB_Desc.Format==D3DFMT_INDEX32)
n=*(DWORD*)&pIndices[2*(3*dwFace+j)];
else return FALSE;
pV[j]=(D3DXVECTOR3*)(pVertices+nStride*n);
}
*pVRet=*pV[0] +fBary1*(*pV[1]-*pV[0])+fBary2*(*pV[2]-*pV[0]);
pVB-> Unlock();
pIB-> Unlock();
return 1;
}
pVB-> Unlock();
pIB-> Unlock();
return 0;
}
//Summary:
//Description:计算一个三角形和一个射线的交点
//Parameters:
//orig:射线起始点
//dir:射线的方向
//v0:三角形的第一个顶点
//v1:三角形的第二个顶点
//v2:三角形的第三个顶点
//t:交点到射线起始点的距离
//u:交点在v1-v0上的投影的位置,
//v:交点在v1-v0上的投影的位置, 交点为vRet=v0+u*(v1-v0)+v*(v2-v0)
//Returns:是否有交点
//Sample:
//IntersectIndexBuffer(pIB,pVB,
//dwVSize,
//dwNumFace,
//pRayOrig,pRayDir,pVRet,dwFlag);
BOOL IntersectTriangle( const D3DXVECTOR3& orig,//实现碰撞检测 的全局函数(三角面)
const D3DXVECTOR3& dir, const D3DXVECTOR3& v0,
const D3DXVECTOR3& v1, const D3DXVECTOR3& v2,
FLOAT* t, FLOAT* u, FLOAT* v )
{
// Find vectors for two edges sharing vert0
D3DXVECTOR3 edge1 = v1 - v0;
D3DXVECTOR3 edge2 = v2 - v0;
// Begin calculating determinant - also used to calculate U parameter
//交点p=edge1*u+edge2*v;
D3DXVECTOR3 pvec;
D3DXVec3Cross( &pvec, &dir, &edge2 );//|a×b|=|a||b|sinθ
// 如果det接近0,表明射线平行于三角形
FLOAT det = D3DXVec3Dot( &edge1, &pvec );//|a dot b|=|a||b|cosθ
D3DXVECTOR3 tvec;
if( det > 0 )
{
tvec = orig - v0;
}
else
{return FALSE;//方向相反
tvec = v0 - orig;
det = -det;
}
//if(D3DXVec3Dot(&dir,&tvec)> 0) return FALSE;
if( det < 0.0001f )
return FALSE;
// Calculate U parameter and test bounds
*u = D3DXVec3Dot( &tvec, &pvec );
if( *u < 0.0f || *u > det )
return FALSE;
// Prepare to test V parameter
D3DXVECTOR3 qvec;
D3DXVec3Cross( &qvec, &tvec, &edge1 );
// Calculate V parameter and test bounds
*v = D3DXVec3Dot( &dir, &qvec );
if( *v < 0.0f || *u + *v > det )
return FALSE;
// Calculate t, scale parameters, ray intersects triangle
*t = D3DXVec3Dot( &edge2, &qvec );
FLOAT fInvDet = 1.0f / det;
*t *= fInvDet;
*u *= fInvDet;
*v *= fInvDet;
if(*t <0) return FALSE;
return TRUE;
};
[解决办法]
沙发,帮楼主顶顶