射线-三角形相交
转载自最早发布在formu.ziyuesinicization.site的文章
其实就是Möller–Trumbore 相交算法,下面是我自己的推导。
三角形三个顶点设为$ \vec{V}_{0}, \vec{V}_{1}, \vec{V}_{2}$,摄像机的起点和方向设为 $\vec{O}, \vec{D}$。
三角形内任意一点用三角形重心坐标表示:
$$ \vec{P} = (1 - u - v) \vec{V}_{0} + u \vec{V}_{1} + v \vec{V}_{2} (u \ge 0 \ v \ge 0 \ (u + v) \le 1) $$
$$ \vec{P} = \vec{V}_{0} - u \vec{V}_{0} + u \vec{V}_{1} - v \vec{V}_{0} + v \vec{V}_{2}$$
$$ \vec{P} = \vec{V}_{0} - u (\vec{V}_{0} - u \vec{V}_{1}) - v (\vec{V}_{0} - v \vec{V}_{2})$$
我们令$ \vec{E}_{1} = \vec{V}_{0} - \vec{V}_{1}, \vec{E}_{2} = \vec{V}_{0} - \vec{V}_{2}$,式子变为:
$$ \vec{P} = \vec{V}_{0} - u \vec{E}_{1} - v \vec{E}_{2}$$
摄像机发出的一条条射线用射线方程写为:
$$ \vec{Cam} = \vec{O} + t \vec{D} (t \ge 0) $$
当摄像机发出的射线击中三角形时,公式可写为:
$$ \vec{P} = \vec{Cam} $$
$$ \vec{V}_{0} - u \vec{E}_{1} - v \vec{E}_{2} = \vec{O} + t \vec{D} $$
$$ \vec{V}_{0} - \vec{O} = u \vec{E}_{1} + v \vec{E}_{2} + t \vec{D} $$
令$ \vec{S} = \vec{V}_{0} - \vec{O} $
$$ u \vec{E}_{1} + v \vec{E}_{2} + t \vec{D} = \vec{S} $$
我们逐个去解u , v, t。
首先是u, 我们可以根据叉积的性质,去消掉无关项:
$$ u \vec{E}_{1} \cdot (\vec{E}_{2} \times \vec{D}) + v \vec{E}_{2} \cdot (\vec{E}_{2} \times \vec{D}) + t \vec{D} \cdot (\vec{E}_{2} \times \vec{D}) = \vec{S} \cdot (\vec{E}_{2} \times \vec{D}) $$
$$ u \vec{E}_{1} \cdot (\vec{E}_{2} \times \vec{D}) = \vec{S} \cdot (\vec{E}_{2} \times \vec{D}) $$
$$ u = \frac{\vec{S} \cdot (\vec{E}_{2} \times \vec{D})}{\vec{E}_{1} \cdot (\vec{E}_{2} \times \vec{D})} $$
同样的,v也是如此:
$$ u \vec{E}_{1} \cdot (\vec{E}_{1} \times \vec{D}) + v \vec{E}_{2} \cdot (\vec{E}_{1} \times \vec{D}) + t \vec{D} \cdot (\vec{E}_{1} \times \vec{D}) = \vec{S} \cdot (\vec{E}_{1} \times \vec{D}) $$
$$ v \vec{E}_{2} \cdot (\vec{E}_{1} \times \vec{D}) = \vec{S} \cdot (\vec{E}_{1} \times \vec{D}) $$
$$ v = \frac{\vec{S} \cdot (\vec{E}_{1} \times \vec{D})}{\vec{E}_{2} \cdot (\vec{E}_{1} \times \vec{D})} $$
然后是t:
$$ u \vec{E}_{1} \cdot (\vec{E}_{1} \times \vec{E}_{2}) + v \vec{E}_{2} \cdot (\vec{E}_{1} \times \vec{E}_{2}) + t \vec{D} \cdot (\vec{E}_{1} \times \vec{E}_{2}) = \vec{S} \cdot (\vec{E}_{1} \times \vec{E}_{2}) $$
$$ t \vec{D} \cdot (\vec{E}_{1} \times \vec{E}_{2}) = \vec{S} \cdot (\vec{E}_{1} \times \vec{E}_{2}) $$
$$ t = \frac{\vec{S} \cdot (\vec{E}_{1} \times \vec{2})}{\vec{D} \cdot (\vec{E}_{1} \times \vec{E}_{2})} $$
我们把$ \vec{D} \cdot (\vec{E}_{1} \times \vec{E}_{2}) $展开:
$$ \vec{D} \cdot (\vec{E}_{1} \times \vec{E}_{2}) = \\ D.x \cdot E_{1}.y \cdot E_{2}.z - D.x \cdot E_{2}.y \cdot E_{1}.z + \\ D.y \cdot E_{2}.x \cdot E_{1}.z - D.y \cdot E_{1}.x \cdot E_{2}.z + \\ D.z \cdot E_{1}.x \cdot E_{2}.y - D.z \cdot E_{2}.x \cdot E_{1}.y $$
想必你一定看出什么来了,如果你还看不出来,那么再把式子化为这样:
$$ \vec{D} \cdot (\vec{E}_{1} \times \vec{E}_{2}) = \\ D.x \cdot (E_{1}.y \cdot E_{2}.z - \cdot E_{2}.y \cdot E_{1}.z) \\ - D.y \cdot ( D.y \cdot E_{1}.x \cdot E_{2}.z - E_{2}.x \cdot E_{1}.z) \\ + D.z \cdot ( E_{1}.x \cdot E_{2}.y - \cdot E_{2}.x \cdot E_{1}.y) $$
根据行列式的拉普拉斯展开,我们可以得到行列式:
$$ \begin{vmatrix}
D.x & D.y & D.z \\
E_{1}.x & E_{1}.y & E_{1}.z \\
E_{2}.x & E_{2}.y & E_{2}.z
\end{vmatrix} $$
我们对换第一行和第二行,第二行和第三行,再重复刚刚的对换就可以得到:
$$ \begin{vmatrix}
D.x & D.y & D.z \\
E_{1}.x & E_{1}.y & E_{1}.z \\
E_{2}.x & E_{2}.y & E_{2}.z
\end{vmatrix}
=
\begin{vmatrix}
E_{1}.x & E_{1}.y & E_{1}.z \\
E_{2}.x & E_{2}.y & E_{2}.z\\
D.x & D.y & D.z
\end{vmatrix}
=
\begin{vmatrix}
E_{2}.x & E_{2}.y & E_{2}.z\\
D.x & D.y & D.z\\
E_{1}.x & E_{1}.y & E_{1}.z
\end{vmatrix} $$
于是,我们就可以得到:
$$ \vec{D} \cdot (\vec{E}_{1} \times \vec{E}_{2}) = \vec{E}_{1} \cdot (\vec{E}_{2} \times \vec{D}) = \vec{E}_{2} \cdot (\vec{D} \times \vec{E}_{1}) $$
我们直接令上面的结果为det,于是我们便可得到u, v, t:
$$
u = \frac{\vec{S} \cdot (\vec{E}_{2} \times \vec{D})}{det} \\
v = \frac{\vec{S} \cdot (\vec{E}_{1} \times \vec{D})}{\vec{E}_{2} \cdot (\vec{E}_{1} \times \vec{D})} = \frac{\vec{S} \cdot (\vec{D} \times \vec{E}_{1})}{\vec{E}_{2} \cdot (\vec{D} \times \vec{E}_{1})} = \frac{\vec{S} \cdot (\vec{D} \times \vec{E}_{1})}{det} \\
t = \frac{\vec{S} \cdot (\vec{E}_{1} \times \vec{E}_{2})}{det}
$$
--2026/6/13