【3D技术宅公社】XR数字艺术论坛  XR技术讨论 XR互动电影 定格动画

 找回密码
 立即注册

QQ登录

只需一步,快速开始

调查问卷
论坛即将给大家带来全新的技术服务,面向三围图形学、游戏、动画的全新服务论坛升级为UTF8版本后,中文用户名和用户密码中有中文的都无法登陆,请发邮件到324007255(at)QQ.com联系手动修改密码

3D技术论坛将以计算机图形学为核心,面向教育 推出国内的三维教育引擎该项目在持续研发当中,感谢大家的关注。

查看: 2123|回复: 1

[DirectX] D3DXIntersectTri 求三角形与射线相交

[复制链接]
发表于 2012-10-29 16:46:33 | 显示全部楼层 |阅读模式

  1.     D3DXVECTOR3 vec1(-10,0,-10);
  2.     D3DXVECTOR3 vec2(  0,0, 10);
  3.     D3DXVECTOR3 vec3( 10,0,-10);

  4.     D3DXVECTOR3 vecOrg(0,10,0);
  5.     D3DXVECTOR3 vecDir(0,-2,0);

  6.     //求射线长度
  7.     D3DXVECTOR3 _vecDir;
  8.     D3DXVec3Subtract(&_vecDir, &vecDir, &vecOrg);
  9.     float dis_Ray = D3DXVec3Length(&_vecDir);

  10.     D3DXVec3Normalize(&vecDir,&vecDir);

  11.     float u;
  12.     float v;
  13.     float dis;
  14.     bool bInt = D3DXIntersectTri(&vec1, &vec2, &vec3, &vecOrg, &vecDir,&u, &v, &dis );
  15.     if (bInt && dis <= dis_Ray)
  16.     {
  17.         //求交点
  18.         D3DXVECTOR3 vecIntPoint =  vec1 + u * (vec2 - vec1) + v * (vec3 - vec1);
  19.         return S_OK;
  20.     }
复制代码
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的值和向量长度成正比关系
  1. D3DXVECTOR3    rayDir;
  2.     D3DXVECTOR3 vDest( 10,200,0.f);
  3.     D3DXVECTOR3 vSour( 10,200,-10.f );
  4.     rayDir = vDest - vSour;
  5.     D3DXVec3Normalize( &rayDir, &rayDir );                                    //将方向向量化
  6.     BOOL bHit = D3DXIntersectTri( &D3DXVECTOR3(0.0f,  0.0f, 0.5f),
  7.                                 &D3DXVECTOR3(250.0f, 250.0f, 0.5f),
  8.                                 &D3DXVECTOR3(0.0f, 250.0f, 0.5f),        //pos
  9.                                 &D3DXVECTOR3(10,200,-10.f ),            //dir
  10.                                 &rayDir,
  11.                                 &fu,
  12.                                 &fv,
  13.                                 &t );
复制代码
游戏中应用
  1. float CTerrain::GetZByXY( float fx,float fy  )
  2.     {
  3.         //求出第几个方格
  4.         int x,y;
  5.         x = fx / MAPTILESIZE;
  6.         y = fy / MAPTILESIZE;
  7.         if( x < 0 || x >= m_iMapWidth-1  )
  8.             return 0;
  9.         if( y < 0 || y >= m_iMapHeight-1 )
  10.             return 0;   
  11.         
  12.         //方格四顶点
  13.         D3DXVECTOR3 *pos[4];
  14.         pos[0] = &m_ppPointPos[ y ][ x ];
  15.         pos[1] = &m_ppPointPos[ y ][ x + 1];
  16.         pos[2] = &m_ppPointPos[ y + 1][ x + 1];
  17.         pos[3] = &m_ppPointPos[ y + 1][ x ];

  18.         float fMaxZ;
  19.         fMaxZ = pos[ 0 ]->z ;
  20.         int iLoop;
  21.         for( iLoop = 1 ; iLoop < 4 ; iLoop ++ )
  22.         {
  23.             if( fMaxZ < pos[ iLoop ]->z )
  24.                 fMaxZ = pos[ iLoop ]->z;
  25.         }

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

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

  31.         float fU,fV,fDis;

  32.         if( !D3DXIntersectTri( pos[0],pos[1] ,pos[2],&vEye,&vDir,            //三角形1
  33.             &fU,&fV,&fDis ) )
  34.         {   
  35.             if( !D3DXIntersectTri( pos[2],pos[3],pos[0],&vEye,&vDir,        //三角形2
  36.                 &fU,&fV,&fDis ) )
  37.             {
  38.                 return 0.0f;
  39.             }
  40.             else
  41.             {
  42.                 return vEye.z - fDis;
  43.             }
  44.         }
  45.         else
  46.         {
  47.             return vEye.z - fDis;
  48.         }
  49.     }
复制代码

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


发表于 2013-7-9 16:28:42 | 显示全部楼层
这个方面的话题的 都讨论一下

qq皮肤非主流 qq个性签名 情侣网名大全 头像图片 非主流意境唯美图片 
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|3D数字艺术论坛 ( 沪ICP备14023054号 )

GMT+8, 2025-2-6 07:09

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表