|
|
大家好,第一次来这里学习,请大家多多指教. 最近看了一段代码这部分实在是看不懂了, 来请教大虾帮忙,代码如下,:
头文件中的内容
#ifndef AFX_CMATH_H
#define AFX_CMATH_H
#define INTERSECT_NEGATIVEY 0x10
#define INTERSECT_HORIZENTAL 0x30
//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;
};
[em3] |
|