刚刚研究了这个问题,发现执行此操作并不需要什么高深的技巧。
首先,可以定义近平面和远平面,然后通过这些平面剪裁线段(请参见示例)。
虽然这样做很好用,但我想避免在投影之上进行额外的计算。对于熟悉投影矩阵的人来说,这可能是显而易见的,但我还是要再次确认这样做是否有效。
事实证明,您可以使用简单的逻辑执行近/远线剪裁。
- 将位置与透视矩阵相乘,以获得4D向量。
- 将第四个分量与近/远剪裁距离进行比较。
- 如果需要,则剪裁线段。
可以通过在计算完整个投影之前计算向量的第四个分量来优化此过程。
这也意味着您无需在剪裁后重新计算XYZ分量。
例如:这将一个4D向量与4x4矩阵相乘。
pub fn mul_m4v4(m: &[[f64; 4]; 4], v: &[f64; 4]) -> [f64; 4] {
[
v[0] * m[0][0] + v[1] * m[1][0] + v[2] * m[2][0] + m[3][0] * v[3],
v[0] * m[0][1] + v[1] * m[1][1] + v[2] * m[2][1] + m[3][1] * v[3],
v[0] * m[0][2] + v[1] * m[1][2] + v[2] * m[2][2] + m[3][2] * v[3],
v[0] * m[0][3] + v[1] * m[1][3] + v[2] * m[2][3] + m[3][3] * v[3],
]
}
由于这是一个三维位置,我们可以假设第四个分量为1.0。
pub fn mul_m4v3_as_v4(m: &[[f64; 4]; 4], v: &[f64; 3]) -> [f64; 4] {
[
v[0] * m[0][0] + v[1] * m[1][0] + v[2] * m[2][0] + m[3][0],
v[0] * m[0][1] + v[1] * m[1][1] + v[2] * m[2][1] + m[3][1],
v[0] * m[0][2] + v[1] * m[1][2] + v[2] * m[2][2] + m[3][2],
v[0] * m[0][3] + v[1] * m[1][3] + v[2] * m[2][3] + m[3][3],
]
}
为了避免进行完整的计算,将一个单独的函数拆分出来以获取第四个组件。
pub fn mul_project_m4_v3_zfac(m: &[[f64; 4]; 4], v: &[f64; 3]) -> [f64; 4] {
v[0] * m[0][3] + v[1] * m[1][3] + v[2] * m[2][3] + m[3][3]
}
这里有一个提交,它实现了上述所描述的剪辑。
注意:矩阵是列主序(像OpenGL一样)。