记录一下:
点与面的关系如图:
如果法相量是单位向量的话,那么分母为1
所以,当 平面的法向量是单位向量的话,看一个点与平面的关系的公司就是分子:
Ax0 + By0 + Cz0 + D
在Muli3D 中,看到下面的代码
inline float32 plane::operator *( const vector3 &i_vVal ) const
{
return fVector3Dot( normal, i_vVal ) + d;
}
inline float32 plane::operator *( const vector4 &i_vVal ) const
{
return fVector3Dot( normal, (vector3)i_vVal ) + d * i_vVal.w;
}
第一个函数就比较好理解,直接就是上面的数学推导。
对于第二个函数,考虑的点的坐标是齐次坐标,
下面进行推导下,
得到的就是 点的坐标就是 (x, y, z, w) => ( x / w , y / w, z / w, 1)
所以:
PQ 点积 n 得到,n 是单位向量的情况下,公式是
A ( x0/w0 - x) + B (y0/w0 - y) + C (z0/w0 - z)
=>
A ( x0 - w0x) + B (y0 - w0y) + C (z0 - w0z) / w0
=>
( Ax0 + By0 + Cz0 + w0 * (Ax + By + Cz)) / w0
=>
( fVector3Dot( normal, (vector3)i_vVal ) + d * i_vVal.w ) / i_vVal.w
对比代码,上面的公式多了 / i_vVal.w,
个人理解:
因为向量的w分量大多数情况下都是为1的,只有在经过了投影矩阵变换后,w才不为1,在Muli3D中,投影矩阵类似于Dx的投影矩阵,所以,经过投影变换之后的w > 0,
所以,代码中只用了分子来判断点与面的关系,只要是 > 0 的话,就是在面的正面区域,只要是 < 0 的话,就是在面的背面区域。
下面是Muli3D的投影矩阵代码:
matrix44 &matMatrix44PerspectiveFovLH( matrix44 &o_matMatOut, const float32 i_fFOVY, const float32 i_fAspect, const float32 i_fZNear, const float32 i_fZFar )
{
const float32 fViewSpaceHeight = 1.0f / tanf( i_fFOVY * 0.5f );
const float32 fViewSpaceWidth = fViewSpaceHeight / i_fAspect;
o_matMatOut._11 = fViewSpaceWidth; o_matMatOut._12 = 0.0f; o_matMatOut._13 = 0.0f; o_matMatOut._14 = 0.0f;
o_matMatOut._21 = 0.0f; o_matMatOut._22 = fViewSpaceHeight; o_matMatOut._23 = 0.0f; o_matMatOut._24 = 0.0f;
o_matMatOut._31 = 0.0f; o_matMatOut._32 = 0.0f; o_matMatOut._33 = i_fZFar / ( i_fZFar - i_fZNear ); o_matMatOut._34 = 1.0f;
o_matMatOut._41 = 0.0f; o_matMatOut._42 = 0.0f; o_matMatOut._43 = -i_fZNear * i_fZFar / ( i_fZFar - i_fZNear ); o_matMatOut._44 = 0.0f;
return o_matMatOut;
}