Извлечение плоскостей усеченного зрения (метод Гартмана и Гриббса)
Я боролся с методом Гартмана / Гриббса для извлечения плоскостей Фрустума в течение некоторого времени, но с небольшим успехом. Я хочу создать камеру, чтобы убрать мою сцену.
Я работаю с матрицами основных столбцов в правой системе координат. (Стиль OpenGL - я использую C# и Playstation Mobile, но математика должна быть одинаковой)
Я хочу получить свои самолеты в World-Space, поэтому я строю свое усеченное строение из матрицы проекции вида (это projectionMatrix * viewMatrix). Матрица обзора является обратной к трансформации мира камеры.
Проблема в; независимо от того, что я настраиваю, я не могу получить правильный усеченный конус. Я думаю, что я могу упустить что-то очевидное.
Если я "поверну" свою камеру влево или вправо, продолжая смотреть вниз по оси z, нормали к моим плоскостям изменятся так, что они всегда будут указывать на начало сцены - что заставляет меня думать, что они не находятся в мировом пространстве...
2 ответа
Плоскости из матрицы проекции могут быть извлечены с использованием метода Гартмана / Гриббса следующим образом (основной столбец):
void extract_planes_from_projmat(
const float mat[4][4],
float left[4], float right[4], float top[4], float bottom[4],
float near[4], float far[4])
{
for (int i = 4; i--; ) left[i] = mat[i][3] + mat[i][0];
for (int i = 4; i--; ) right[i] = mat[i][3] - mat[i][0];
for (int i = 4; i--; ) bottom[i] = mat[i][3] + mat[i][1];
for (int i = 4; i--; ) top[i] = mat[i][3] - mat[i][1];
for (int i = 4; i--; ) near[i] = mat[i][3] + mat[i][2];
for (int i = 4; i--; ) far[i] = mat[i][3] - mat[i][2];
}
Увидеть:
- https://fgiesen.wordpress.com/2012/08/31/frustum-planes-from-the-projection-matrix/
- http://www8.cs.umu.se/kurser/5DV051/HT12/lab/plane_extraction.pdf
Примечание: если компоненты матрицы не нормализованы, и вам требуется плоскость Нормальной формы Гессиана, то вам нужно будет нормализовать результирующие плоскости.
Недостающая часть:
comboMatrix = projection_matrix * Matrix4_Transpose(modelview_matrix)
Тогда извлечение плоскости усеченного мира для OpenGL в точности соответствует методу Хартмана / Гриббса:
p_planes[0].a = comboMatrix._41 + comboMatrix._11;
p_planes[0].b = comboMatrix._42 + comboMatrix._12;
p_planes[0].c = comboMatrix._43 + comboMatrix._13;
p_planes[0].d = comboMatrix._44 + comboMatrix._14;
// Right clipping plane
p_planes[1].a = comboMatrix._41 - comboMatrix._11;
p_planes[1].b = comboMatrix._42 - comboMatrix._12;
p_planes[1].c = comboMatrix._43 - comboMatrix._13;
p_planes[1].d = comboMatrix._44 - comboMatrix._14;
// Top clipping plane
p_planes[2].a = comboMatrix._41 - comboMatrix._21;
p_planes[2].b = comboMatrix._42 - comboMatrix._22;
p_planes[2].c = comboMatrix._43 - comboMatrix._23;
p_planes[2].d = comboMatrix._44 - comboMatrix._24;
// Bottom clipping plane
p_planes[3].a = comboMatrix._41 + comboMatrix._21;
p_planes[3].b = comboMatrix._42 + comboMatrix._22;
p_planes[3].c = comboMatrix._43 + comboMatrix._23;
p_planes[3].d = comboMatrix._44 + comboMatrix._24;
// Near clipping plane
p_planes[4].a = comboMatrix._41 + comboMatrix._31;
p_planes[4].b = comboMatrix._42 + comboMatrix._32;
p_planes[4].c = comboMatrix._43 + comboMatrix._33;
p_planes[4].d = comboMatrix._44 + comboMatrix._34;
// Far clipping plane
p_planes[5].a = comboMatrix._41 - comboMatrix._31;
p_planes[5].b = comboMatrix._42 - comboMatrix._32;
p_planes[5].c = comboMatrix._43 - comboMatrix._33;
p_planes[5].d = comboMatrix._44 - comboMatrix._34;
Эти самолеты теперь находятся в мировом пространстве и могут быть использованы для разрушения объектов мирового пространства.
for(int i = 0; i < 6; i++)
{
var dist = dot3(world_space_point.xyz, p_planes[i].xyz) + p_planes[i].d + sphere_radius;
if(dist < 0) return false; // sphere culled
}