BOOL D3DXIntersectTri(
CONST D3DXVECTOR3* p0, //頂點(diǎn)1
CONST D3DXVECTOR3* p1,
CONST D3DXVECTOR3* p2,
CONST D3DXVECTOR3* pRayPos, //射線起始位置
CONST D3DXVECTOR3* pRayDir, //射線方向
FLOAT* pU, //三個(gè)點(diǎn)比重
FLOAT* pV,
FLOAT* pDist //射線起點(diǎn)到交點(diǎn)位置
);
para :其中p0, p1, p2分別指向三角形的三個(gè)頂點(diǎn),position為射線起點(diǎn),direction為射線方向向量,u,v,為交點(diǎn)重心坐標(biāo),因?yàn)椴豢赡苤稽c(diǎn)到頂點(diǎn)上,可能點(diǎn)在三角形范圍內(nèi),distance為起點(diǎn)到交點(diǎn)距離,成功返回TRUE,失敗返回FALSE。
vPickPos = v0 * ( 1-u-v) + v1*u + v2*v = v0 + u * (v1 - v0) + v * (v3 - v0);
特別注意:方向向量必須為單位向量,即pRayDir - pRayPos 為單位向量否則,pDist的值和向量長(zhǎng)度成正比關(guān)系
eg:
D3DXVECTOR3 rayDir;
D3DXVECTOR3 vDest( 10,200,0.f);
D3DXVECTOR3 vSour( 10,200,-10.f );
rayDir = vDest - vSour;
D3DXVec3Normalize( &rayDir, &rayDir ); //將方向向量化
BOOL bHit = D3DXIntersectTri( &D3DXVECTOR3(0.0f, 0.0f, 0.5f),
&D3DXVECTOR3(250.0f, 250.0f, 0.5f),
&D3DXVECTOR3(0.0f, 250.0f, 0.5f), //pos
&D3DXVECTOR3(10,200,-10.f ), //dir
&rayDir,
&fu,
&fv,
&t );
游戲中應(yīng)用
float CTerrain::GetZByXY( float fx,float fy )

{
//求出第幾個(gè)方格
int x,y;
x = fx / MAPTILESIZE;
y = fy / MAPTILESIZE;
if( x < 0 || x >= m_iMapWidth-1 )
return 0;
if( y < 0 || y >= m_iMapHeight-1 )
return 0;
//方格四頂點(diǎn)
D3DXVECTOR3 *pos[4];
pos[0] = &m_ppPointPos[ y ][ x ];
pos[1] = &m_ppPointPos[ y ][ x + 1];
pos[2] = &m_ppPointPos[ y + 1][ x + 1];
pos[3] = &m_ppPointPos[ y + 1][ x ];

float fMaxZ;
fMaxZ = pos[ 0 ]->z ;
int iLoop;
for( iLoop = 1 ; iLoop < 4 ; iLoop ++ )

{
if( fMaxZ < pos[ iLoop ]->z )
fMaxZ = pos[ iLoop ]->z;
}

// 求眼睛和地形相交位置,注意單位化方向向量
D3DXVECTOR3 vEye,vDir(0,0,-1);

vEye.x = fx;
vEye.y = fy;
vEye.z = fMaxZ + 10;

float fU,fV,fDis;

if( !D3DXIntersectTri( pos[0],pos[1] ,pos[2],&vEye,&vDir, //三角形1
&fU,&fV,&fDis ) )

{
if( !D3DXIntersectTri( pos[2],pos[3],pos[0],&vEye,&vDir, //三角形2
&fU,&fV,&fDis ) )

{
return 0.0f;
}
else

{
return vEye.z - fDis;
}
}
else

{
return vEye.z - fDis;
}
}
參考:
地形碰撞計(jì)算:
一.如果是鼠標(biāo)點(diǎn)擊地面,
可將射線固定長(zhǎng)度并分段,然后用射線與每一個(gè)分段上的點(diǎn)所落在的地面tile(兩個(gè)三角形)進(jìn)行求交,
相交則返回對(duì)應(yīng)位置,否則繼續(xù)與下一個(gè)段上的點(diǎn)所落在的地面tile求交
/*
0 1
---->
| \ |
| \ |
2 V --- 3
*/
這里不討論點(diǎn)擊屏幕求射線方法與射線分段處理,只算求交
如下d3d求交得出uv,再求位置:
VECTOR3 vPickPos;
// 右邊:
if( D3DXIntersectTri(&v0, &v1, &v3, &vOrig, &vDir, &u, &v, NULL) == TRUE)
{
vPickPos = v0 + u * (v1 - v0) + v * (v3 - v0);
return vPickPos.z;
}
// 左邊:
if( D3DXIntersectTri(&v0, &v3, &v2, &vOrig, &vDir, &u, &v, NULL) == TRUE)
{
vPickPos = v0 + u * (v3 - v0) + v * (v2 - v0);
return vPickPos.z;
}
二.如果是僅是求地表某點(diǎn)高度
則可用uv重心求法(注意上述第一點(diǎn)的d3d的那個(gè)uv重心求法不太一樣,他的uv跟他的向量走?)
float u = (fX-(int)fX);
float v = (fY-(int)fY);
float p0 = fHeight[0];
float p1 = fHeight[1];
float p2 = fHeight[2];
float p3 = fHeight[3];
if(u>v){ // 右邊
return p0 + u * (p1 - p0) + v * (p3 - p1);;
}
else{ // 左邊
return p0 + u * (p3 - p2) + v * (p2 - p0);
}
http://flipcode.spaces.live.com/blog/cns!8E578E7901A88369!1052.entry
posted on 2010-08-18 14:23
風(fēng)輕云淡 閱讀(1349)
評(píng)論(0) 編輯 收藏 引用 所屬分類:
DX