Только что изучив эту же самую тему, я обнаружил, что для выполнения этой операции не было ничего очень умного.
Прежде всего, можно определить ближнюю и дальнюю плоскости, затем отрезать отрезокна этих плоскостях ( см. пример ).
Хотя это работает нормально, я хотел избежать дополнительных вычислений в верхней части проекции.Это может быть очевидно для всех, кто знаком с матрицами проекций, мне пришлось дважды проверить, чтобы убедиться, что это будет работать правильно.
Как выясняется, вы можете выполнять обрезку ближней / дальней линии с помощью простой логики.
Умножьте позицию на матрицу перспективы, чтобы получить вектор 4D. Сравните 4-й компонент с расстояниями ближнего / дальнего отсечения. При необходимости обрежьте сегмент.
Это можно оптимизировать, рассчитав 4-й компонент вектора перед вычислением полной проекции.
Это также означает, что вам не нужно повторно вычислять компоненты 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],
]
}
Поскольку это трехмерная позиция, мы можем предположить, что 4-й компонент равен 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],
]
}
Чтобы избежать полного расчета, выделите отдельную функцию для получения 4-го компонента.
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).