在做光线追踪的时候,有一步是已知光线所打到的平面的normal,和光线的入射方向。我们想将入射方向转换为normal的局部坐标,这就首先需要构建出基于normal的局部坐标系。然后利用这篇文章( https://www.cnblogs.com/wickedpriest/p/12074420.html ) 来进行转换。
那么现在的问题就是:给定normal作为局部坐标系的z轴,如何去构建x、y轴来组成新的局部坐标系呢?
图形学网站scratch_pixel上提到了一种方法,在这里贴出代码:
XMVECTOR Nt, Nb, N;
N = XMVectorSet(n.x, n.y, n.z, 0.0);
if (std::fabs(n.x) > std::fabs(n.y))
Nt = XMVector3Normalize(XMVectorSet(n.z, 0, -n.x, 0.0));
else
Nt = XMVector3Normalize(XMVectorSet(0.0, -n.z, n.y, 0.0));
Nb = XMVector3Cross(N, Nt);
其中N是normal,Nt和Nb就是我们计算出的另外两个轴。我最开始看到代码中if的部分还愣了一下,没太搞懂这么做的动机。想了一会儿才意识到一开始计算Nt的时候,为了保证和N相互垂直,取得是向量N中的两个数,并将其中一个数取反,组成的新向量(这样可以保证N与Nt的点乘为0)。但有一种可能是取到的两个数全都是0,那么得到的Nt就会是全0的值。为了避免这一点,Nt中需要包含N里绝对值最大的值(最大的绝对值值可能不可能是0)。