D3DXIntersectTri 求三角形与射线相交

    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;
    }


None.gif BOOL D3DXIntersectTri(
None.gif        CONST D3DXVECTOR3
*  p0,                           //顶点1
None.gif        CONST D3DXVECTOR3
*  p1,
None.gif        CONST D3DXVECTOR3
*  p2,
None.gif        CONST D3DXVECTOR3
*  pRayPos,               //射线起始位置
None.gif        CONST D3DXVECTOR3
*  pRayDir,               //射线方向
None.gif        FLOAT
*              pU,                                          //三个点比重
None.gif        FLOAT
*              pV,
None.gif        FLOAT
*              pDist                                       //射线起点到交点位置
None.gif        );

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的值和向量长度成正比关系


eg:

None.gif     D3DXVECTOR3    rayDir;
None.gif    D3DXVECTOR3 vDest( 
10 , 200 , 0 .f);
None.gif    D3DXVECTOR3 vSour( 
10 , 200 , - 10 .f );
None.gif    rayDir 
=  vDest  -  vSour;
None.gif    D3DXVec3Normalize( 
& rayDir,  & rayDir );                                    //将方向向量化
None.gif    BOOL bHit 
=  D3DXIntersectTri(  & D3DXVECTOR3( 0.0f ,   0.0f 0.5f ),
None.gif                                
& D3DXVECTOR3( 250.0f 250.0f 0.5f ),
None.gif                                
& D3DXVECTOR3( 0.0f 250.0f 0.5f ),         // pos
None.gif
                                 & D3DXVECTOR3( 10 , 200 , - 10 .f ),             // dir
None.gif
                                 & rayDir, 
None.gif                                
& fu, 
None.gif                                
& fv, 
None.gif                                
& t );


游戏中应用

None.gif      float  CTerrain::GetZByXY(  float  fx, float  fy  )
ExpandedBlockStart.gif    
{
InBlock.gif        
//求出第几个方格
InBlock.gif
        int x,y;
InBlock.gif        x 
= fx / MAPTILESIZE;
InBlock.gif        y 
= fy / MAPTILESIZE;
InBlock.gif        
if( x < 0 || x >= m_iMapWidth-1  )
InBlock.gif            
return 0;
InBlock.gif        
if( y < 0 || y >= m_iMapHeight-1 )
InBlock.gif            
return 0;    
InBlock.gif        
InBlock.gif        
//方格四顶点
InBlock.gif
        D3DXVECTOR3 *pos[4];
InBlock.gif        pos[
0= &m_ppPointPos[ y ][ x ];
InBlock.gif        pos[
1= &m_ppPointPos[ y ][ x + 1];
InBlock.gif        pos[
2= &m_ppPointPos[ y + 1][ x + 1];
InBlock.gif        pos[
3= &m_ppPointPos[ y + 1][ x ];
InBlock.gif
InBlock.gif        
float fMaxZ;
InBlock.gif        fMaxZ 
= pos[ 0 ]->z ;
InBlock.gif        
int iLoop;
InBlock.gif        
for( iLoop = 1 ; iLoop < 4 ; iLoop ++ )
ExpandedSubBlockStart.gif        
{
InBlock.gif            
if( fMaxZ < pos[ iLoop ]->z )
InBlock.gif                fMaxZ 
= pos[ iLoop ]->z;
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
// 求眼睛和地形相交位置,注意单位化方向向量
InBlock.gif
        D3DXVECTOR3 vEye,vDir(0,0,-1);
InBlock.gif
InBlock.gif        vEye.x 
= fx;
InBlock.gif        vEye.y 
= fy;
InBlock.gif        vEye.z 
= fMaxZ + 10;
InBlock.gif
InBlock.gif        
float fU,fV,fDis;
InBlock.gif
InBlock.gif        
if!D3DXIntersectTri( pos[0],pos[1] ,pos[2],&vEye,&vDir,            //三角形1
InBlock.gif
            &fU,&fV,&fDis ) )
ExpandedSubBlockStart.gif        
{    
InBlock.gif            
if!D3DXIntersectTri( pos[2],pos[3],pos[0],&vEye,&vDir,        //三角形2
InBlock.gif
                &fU,&fV,&fDis ) )
ExpandedSubBlockStart.gif            
{
InBlock.gif                
return 0.0f;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else
ExpandedSubBlockStart.gif            
{
InBlock.gif                
return vEye.z - fDis;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        
else
ExpandedSubBlockStart.gif        
{
InBlock.gif            
return vEye.z - fDis;
ExpandedSubBlockEnd.gif        }

ExpandedBlockEnd.gif    }



 参考:
地形碰撞计算:
一.如果是鼠标点击地面,
可将射线固定长度并分段,然后用射线与每一个分段上的点所落在的地面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);
 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值