- D3DXVECTOR3 vec1(-10,0,-10);
- D3DXVECTOR3 vec2( 0,0, 10);
- D3DXVECTOR3 vec3( 10,0,-10);
- D3DXVECTOR3 vecOrg(0,10,0);
- D3DXVECTOR3 vecDir(0,-2,0);
- //求射线长度
- D3DXVECTOR3 _vecDir;
- D3DXVec3Subtract(&_vecDir, &vecDir, &vecOrg);
- float dis_Ray = D3DXVec3Length(&_vecDir);
- D3DXVec3Normalize(&vecDir,&vecDir);
- float u;
- float v;
- float dis;
- bool bInt = D3DXIntersectTri(&vec1, &vec2, &vec3, &vecOrg, &vecDir,&u, &v, &dis );
- if (bInt && dis <= dis_Ray)
- {
- //求交点
- D3DXVECTOR3 vecIntPoint = vec1 + u * (vec2 - vec1) + v * (vec3 - vec1);
- return S_OK;
- }
复制代码 BOOL D3DXIntersectTri(
CONST D3DXVECTOR3* p0, //顶点1
CONST D3DXVECTOR3* p1,
CONST D3DXVECTOR3* p2,
CONST D3DXVECTOR3* pRayPos, //射线起始位置
CONST D3DXVECTOR3* pRayDir, //射线方向
FLOAT* pU, //三个点比重
FLOAT* pV,
FLOAT* pDist //射线起点到交点位置
);
para :其中p0, p1, p2分别指向三角形的三个顶点,position为射线起点,direction为射线方向向量,u,v,为交点重心坐标,因为不可能只点到顶点上,可能点在三角形范围内,distance为起点到交点距离,成功返回TRUE,失败返回FALSE。
vPickPos = v0 * ( 1-u-v) + v1*u + v2*v = v0 + u * (v1 - v0) + v * (v3 - v0);
特别注意:方向向量必须为单位向量,即pRayDir - pRayPos 为单位向量否则,pDist的值和向量长度成正比关系- 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 );
复制代码游戏中应用 - float CTerrain::GetZByXY( float fx,float fy )
- {
- //求出第几个方格
- 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;
-
- //方格四顶点
- 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;
- }
- }
复制代码 参考:
地形碰撞计算:
一.如果是鼠标点击地面,
可将射线固定长度并分段,然后用射线与每一个分段上的点所落在的地面tile(两个三角形)进行求交,
相交则返回对应位置,否则继续与下一个段上的点所落在的地面tile求交
/*
0 1
---->
| \ |
| \ |
2 V --- 3
*/
这里不讨论点击屏幕求射线方法与射线分段处理,只算求交
如下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;
} 二.如果是仅是求地表某点高度
则可用uv重心求法(注意上述第一点的d3d的那个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);
}
|