这个例子主体部分采用Pick.fx进行渲染
关键的部分是拾取算法的实现
第一种方式采用dx中的函数D3DXIntersect,比较简单,第二种方式是自己实现射线与三角形相交测试算法。
我自己想到的算法是求出射线与三角形所在平面交点,然后判断交点是否在三角形内部,实现如下:
// http://www.cnblogs.com/graphics/archive/2010/08/05/1793393.html
bool ptInTri(const D3DXVECTOR3& P, D3DXVECTOR3& A, D3DXVECTOR3& B, D3DXVECTOR3& C,
FLOAT* u, FLOAT* v)
{
D3DXVECTOR3 v0 = C - A ;
D3DXVECTOR3 v1 = B - A ;
D3DXVECTOR3 v2 = P - A ;
float dot00 = D3DXVec3Dot(&v0, &v0) ;
float dot01 = D3DXVec3Dot(&v0, &v1) ;
float dot02 = D3DXVec3Dot(&v0, &v2) ;
float dot11 = D3DXVec3Dot(&v1, &v1) ;
float dot12 = D3DXVec3Dot(&v1, &v2) ;
float inverDeno = 1 / (dot00 * dot11 - dot01 * dot01) ;
*u = (dot11 * dot02 - dot01 * dot12) * inverDeno ;
if (*u < 0 || *u > 1) // if u out of range, return directly
{
return false ;
}
*v = (dot00 * dot12 - dot01 * dot02) * inverDeno ;
if (*v < 0 || *v > 1) // if v out of range, return directly
{
return false ;
}
return *u + *v <= 1 ;
}
bool IntersectTriangle1( const D3DXVECTOR3& orig, const D3DXVECTOR3& dir,
D3DXVECTOR3& v0, D3DXVECTOR3& v1, D3DXVECTOR3& v2,
FLOAT* t, FLOAT* u, FLOAT* v )
{
// 平面两条边
D3DXVECTOR3 edge1 = v1 - v0;
D3DXVECTOR3 edge2 = v2 - v0;
// 计算平面法线
D3DXVECTOR3 planeNormal;
D3DXVec3Cross( &planeNormal, &edge1, &edge2 );
// 判断orig是否在平面上
D3DXVECTOR3 pvec = v0 - orig;
FLOAT det = D3DXVec3Dot(&pvec, &planeNormal);
if( det < 0.0001f && det > -0.0001f )
return FALSE;
// 求距离
*f = D3DXVec3Dot(&dir, &planeNormal);
*f /= det;
// 距离为负值
if (*f<=0.0f)
return FALSE;
// 射线与平面的交点
D3DXVECTOR3 vecInPlane = orig + *f*dir;
// 交点是否在三角形内部
if (!ptInTri(vecInPlane, v0, v1, v2, u, v))
return FALSE;
return TRUE;
}
上面的算法比较复杂,计算量大,网上找到了dx中算法的说明,转帖如下,用到了两个知识点,克莱姆法则和混合积,早忘记了,所以靠自己是不可能想出来的
英文文献下载csdn地址 http://download.csdn.net/detail/buck84/5520925
转帖地址 http://www.cnblogs.com/graphics/archive/2010/08/09/1795348.html
射线和三角形的相交检测(ray triangle intersection test)
本文以Fast, Minimum Storage Ray Triangle Intersection为参考,在此感谢原作者,大家也可以直接阅读原版。
概述
射线和三角形的相交检测是游戏程序设计中一个常见的问题,最典型的应用就是拾取(Picking),本文介绍一个最常见的方法,这个方法也是DirectX中采用的方法,该方法速度快,而且存储空间少。先讲述理论,然后给出对应的代码实现。
理论部分
一个直观的方法
我想大多数人在看到这个问题时,可能都会想到一个简单而直观的方法:首先判断射线是否与三角形所在的平面相交,如果相交,再判断交点是否在三角形内。