射线-三角形相交。它有两个方向
Ray-triangle intersection. It work with two directions
我不知道为什么,但光线-三角形相交算法(Möller-Trumbore 和 Watertight)适用于 2 个方向。
从头到尾 - 它必须如何工作
从头到尾——问题所在
白色十字 - 不必要的交叉路口
screenshot
我尝试使用 3 个分量向量,所以我从代码中删除了所有 W 值。
雷
class Ray
{
public:
Ray(){}
~Ray(){}
Vector4 m_origin;
Vector4 m_end;
Vector4 m_direction;
void update()
{
m_end._f32[3] = 0.f;
m_origin._f32[3] = 0.f;
m_direction._f32[ 0 ] = m_end._f32[0] - m_origin._f32[0];
m_direction._f32[ 1 ] = m_end._f32[1] - m_origin._f32[1];
m_direction._f32[ 2 ] = m_end._f32[2] - m_origin._f32[2];
m_direction._f32[ 3 ] = 0.f;
m_direction.normalize(); // without W
}
};
三角与算法
struct Triangle
{
Vector4 v1; // vertex 1 position
Vector4 v2; // vertex 2 position
Vector4 v3; // vertex 3 position
Vector4 e1; // edge, see update()
Vector4 e2; // edge, see update()
void update()
{
e1 = Vector4( v2._f32[0] - v1._f32[0],
v2._f32[1] - v1._f32[1],
v2._f32[2] - v1._f32[2],
0.f);
e2 = Vector4( v3._f32[0] - v1._f32[0],
v3._f32[1] - v1._f32[1],
v3._f32[2] - v1._f32[2],
0.f);
}
// Möller-Trumbore algorithm
bool rayTest_MT( const Ray& ray, bool withBackFace, f32& T, f32& U, f32& V, f32& W )
{
Vector4 pvec = ray.m_direction.cross_return(e2);
f32 det = e1.dot(pvec);
if( withBackFace )
{
if( std::abs(det) < 0.0000001f && det > -0.0000001f )
return false;
}
else
{
if( det < 0.0000001f && det > -0.0000001f )
return false;
}
Vector4 tvec(
ray.m_origin._f32[0] - v1._f32[0],
ray.m_origin._f32[1] - v1._f32[1],
ray.m_origin._f32[2] - v1._f32[2],
0.f);
//tvec.setW(1.f);//...
f32 inv_det = 1.f / det;
U = tvec.dot(pvec) * inv_det;
if( U < 0.f || U > 1.f )
return false;
Vector4 qvec = tvec.cross_return(e1);
V = ray.m_direction.dot(qvec) * inv_det;
if( V < 0.f || U + V > 1.f )
return false;
T = e2.dot(qvec) * inv_det;
W = 1.f - U - V;
return true;
}
};
简单向量
Vector4
{
public:
f32 _f32[4];
Vector4()
{
_f32[ 0 ] = 0.f;
_f32[ 1 ] = 0.f;
_f32[ 2 ] = 0.f;
_f32[ 3 ] = 0.f;
}
.........
也许我需要使用 W 组件...某处没有。看我的评论。
拦截射线上的单位距离
计算的最后一个值T
是射线上距射线原点的单位距离。其中 T == 0.0f
在原点,T == 1.0f
在光线末端,T > 1.0f
在光线末端之后,T < 0.0f
在光线原点之前。
因此您需要检查 T
以确保截距位于射线的正确部分。例子
前面不包括原点。 return T > EPSILON;
在包括原点在内的光线之前。 return T > -EPSILON;
在包括起点和终点的射线上。 return T > -EPSILON && T < 1.0f + EPSILON;
在不包括起点和终点的射线上。 return T > EPSILON && T < 1.0f - EPSILON;
等等...
EPSILON
我们使用 EPSILON
来处理浮点数错误,对于此算法,您可能希望使用比 EPSILON
更大的值,尤其是当光线与多边形法线之间的角度接近时90 度
我不知道为什么,但光线-三角形相交算法(Möller-Trumbore 和 Watertight)适用于 2 个方向。
从头到尾 - 它必须如何工作
从头到尾——问题所在
白色十字 - 不必要的交叉路口
screenshot
我尝试使用 3 个分量向量,所以我从代码中删除了所有 W 值。
雷
class Ray
{
public:
Ray(){}
~Ray(){}
Vector4 m_origin;
Vector4 m_end;
Vector4 m_direction;
void update()
{
m_end._f32[3] = 0.f;
m_origin._f32[3] = 0.f;
m_direction._f32[ 0 ] = m_end._f32[0] - m_origin._f32[0];
m_direction._f32[ 1 ] = m_end._f32[1] - m_origin._f32[1];
m_direction._f32[ 2 ] = m_end._f32[2] - m_origin._f32[2];
m_direction._f32[ 3 ] = 0.f;
m_direction.normalize(); // without W
}
};
三角与算法
struct Triangle
{
Vector4 v1; // vertex 1 position
Vector4 v2; // vertex 2 position
Vector4 v3; // vertex 3 position
Vector4 e1; // edge, see update()
Vector4 e2; // edge, see update()
void update()
{
e1 = Vector4( v2._f32[0] - v1._f32[0],
v2._f32[1] - v1._f32[1],
v2._f32[2] - v1._f32[2],
0.f);
e2 = Vector4( v3._f32[0] - v1._f32[0],
v3._f32[1] - v1._f32[1],
v3._f32[2] - v1._f32[2],
0.f);
}
// Möller-Trumbore algorithm
bool rayTest_MT( const Ray& ray, bool withBackFace, f32& T, f32& U, f32& V, f32& W )
{
Vector4 pvec = ray.m_direction.cross_return(e2);
f32 det = e1.dot(pvec);
if( withBackFace )
{
if( std::abs(det) < 0.0000001f && det > -0.0000001f )
return false;
}
else
{
if( det < 0.0000001f && det > -0.0000001f )
return false;
}
Vector4 tvec(
ray.m_origin._f32[0] - v1._f32[0],
ray.m_origin._f32[1] - v1._f32[1],
ray.m_origin._f32[2] - v1._f32[2],
0.f);
//tvec.setW(1.f);//...
f32 inv_det = 1.f / det;
U = tvec.dot(pvec) * inv_det;
if( U < 0.f || U > 1.f )
return false;
Vector4 qvec = tvec.cross_return(e1);
V = ray.m_direction.dot(qvec) * inv_det;
if( V < 0.f || U + V > 1.f )
return false;
T = e2.dot(qvec) * inv_det;
W = 1.f - U - V;
return true;
}
};
简单向量
Vector4
{
public:
f32 _f32[4];
Vector4()
{
_f32[ 0 ] = 0.f;
_f32[ 1 ] = 0.f;
_f32[ 2 ] = 0.f;
_f32[ 3 ] = 0.f;
}
.........
也许我需要使用 W 组件...某处没有。看我的评论。
拦截射线上的单位距离
计算的最后一个值T
是射线上距射线原点的单位距离。其中 T == 0.0f
在原点,T == 1.0f
在光线末端,T > 1.0f
在光线末端之后,T < 0.0f
在光线原点之前。
因此您需要检查 T
以确保截距位于射线的正确部分。例子
前面不包括原点。
return T > EPSILON;
在包括原点在内的光线之前。
return T > -EPSILON;
在包括起点和终点的射线上。
return T > -EPSILON && T < 1.0f + EPSILON;
在不包括起点和终点的射线上。
return T > EPSILON && T < 1.0f - EPSILON;
等等...
EPSILON
我们使用 EPSILON
来处理浮点数错误,对于此算法,您可能希望使用比 EPSILON
更大的值,尤其是当光线与多边形法线之间的角度接近时90 度