zoukankan      html  css  js  c++  java
  • D3DXIntersectTri 求三角形与射线相交

        D3DXVECTOR3 vec1(-10,0,-10);
        D3DXVECTOR3 vec2(  
    0,010);
        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的值和向量长度成正比关系


    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.0f0.5f),
                                    
    &D3DXVECTOR3(250.0f250.0f0.5f),
                                    
    &D3DXVECTOR3(0.0f250.0f0.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);
     }

  • 相关阅读:
    android 发送短信 怎样做到一条一条的发送,仅仅有在上一条发送成功之后才发送下一条短信
    qt学习笔记(五) QGraphicsPixmapItem与QGraphicsScene的编程实例 图标拖动渐变效果
    C小加 之 随机数
    垂死挣扎还是涅槃重生 -- Delphi XE5 公布会归来感想
    WIZnet推出串口转以太网模块WIZ550S2E
    java里,当long与上了int
    几个常见字符串处理函数的实现原理
    Android平台调用Web Service:演示样例
    怎样学好游戏编程
    void及void指针含义的深刻解析
  • 原文地址:https://www.cnblogs.com/kex1n/p/2127047.html
Copyright © 2011-2022 走看看