Culling работает с извлечением плоскостей из матрицы проекции, но не с матрицей проекции

Я реализовал отсечение усеченной пирамиды, используя метод извлечения плоскости, описанный в эту статью.

В статье упоминается, что если матрица является матрицей проекции, то плоскости будут в пространстве обзора. Поэтому мне нужно преобразовать мои координаты AABB, чтобы просмотреть пространство для выполнения тестов отбраковки. Однако это не работает.
Но если извлечь плоскости из матрицы проекции и протестировать с координатами AABB в пространстве модели, все будет работать нормально.

Единственное изменение, которое я сделал, - это обновление плоскостей усеченной кости с использованием матрицы проекции вида при каждом движении камеры и преобразование координат AABB в пространство модели вместо пространства обзора.

Вот соответствующий код. Строки с комментариями "diff" - единственные изменения между двумя версиями.

Код для отсечения усеченного конуса на основе матрицы проекции:

// called only at initialization
void camera_set_proj_matrix(camera *c, mat4 *proj_matrix)
{
    c->proj_matrix = *proj_matrix;
    // diff
    extract_frustum_planes(&c->frustum_planes, &c->proj_matrix); 
}

void camera_update_view_matrix(camera *c)
{
    mat4_init_look(&c->view_matrix, &c->pos, &c->dir, &VEC3_UNIT_Y);
    mat4_mul(&c->vp_matrix, &c->proj_matrix, &c->view_matrix);
    // diff
}

void chunk_render(const chunk *c, chunk_pos pos, const camera *camera, GLuint mvp_matrix_location)
{
    mat4 model_matrix;
    block_pos bp = chunk_pos_to_block_pos(pos);
    mat4_init_translation(&model_matrix, bp.x, bp.y, bp.z);
    mat4 mv_matrix;
    mat4_mul(&mv_matrix, &camera->view_matrix, &model_matrix);

    vec4 min = {0, 0, 0, 1};
    vec4 max = {CHUNK_SIDE, CHUNK_HEIGHT, CHUNK_SIDE, 1};
    // diff: using model view matrix here
    mat4_mul_vec4(&min, &mv_matrix, &min); 
    // diff: using model view matrix here
    mat4_mul_vec4(&max, &mv_matrix, &max); 
    AABB aabb = {{min.x, min.y, min.z}, {max.x, max.y, max.z}};
    if (AABB_outside_frustum(&aabb, &camera->frustum_planes)) return;

    //draw
}

Результат Похоже, слишком много отбраковок. Также обратите внимание: это ненормальное отсечение происходит только тогда, когда я смотрю в положительном направлении оси z.

Код для отсечения на основе проекции:

void camera_set_proj_matrix(camera *c, mat4 *proj_matrix)
{
    c->proj_matrix = *proj_matrix; 
    // diff
}

void camera_update_view_matrix(camera *c)
{
    mat4_init_look(&c->view_matrix, &c->pos, &c->dir, &VEC3_UNIT_Y);
    mat4_mul(&c->vp_matrix, &c->proj_matrix, &c->view_matrix);
    // diff: update frustum planes based on view projection matrix now
    extract_frustum_planes(&c->frustum_planes, &c->vp_matrix);
}

void chunk_render(const chunk *c, chunk_pos pos, const camera *camera, GLuint mvp_matrix_location)
{
    mat4 model_matrix;
    block_pos bp = chunk_pos_to_block_pos(pos);
    mat4_init_translation(&model_matrix, bp.x, bp.y, bp.z);
    mat4 mv_matrix;
    mat4_mul(&mv_matrix, &camera->view_matrix, &model_matrix);

    vec4 min = {0, 0, 0, 1};
    vec4 max = {CHUNK_SIDE, CHUNK_HEIGHT, CHUNK_SIDE, 1};
    // diff: using model matrix now
    mat4_mul_vec4(&min, &model_matrix, &min); 
    // diff: using model matrix now
    mat4_mul_vec4(&max, &model_matrix, &max); 
    AABB aabb = {{min.x, min.y, min.z}, {max.x, max.y, max.z}};
    if (AABB_outside_frustum(&aabb, &camera->frustum_planes)) return;

    // draw
}

введите описание изображения здесь Идеально

Я понятия не имею, почему метод только проекции будет работать странным образом, когда я соответствующим образом трансформирую aabb: /


person wingerse    schedule 06.12.2018    source источник
comment
Вы не трансформируете AABB. Вы трансформируете два угла AABB и перестраиваете новый AABB на основе результата.   -  person Frank    schedule 06.12.2018
comment
На каком языке это должно быть? Не помечайте два разных языка.   -  person too honest for this site    schedule 06.12.2018
comment
@Frank ohhh, я не думал об этом .. Вращение камеры сделало бы перестроенный aabb недействительным .. Спасибо, вы можете дать ответ.   -  person wingerse    schedule 06.12.2018
comment
@toohonestforthissite Это C, но я думаю, он должен работать в равной степени и для C ++. Это не конкретный вопрос C.   -  person wingerse    schedule 06.12.2018


Ответы (1)


Что на самом деле означает преобразование AABB?

Давайте посмотрим на проблему в 2D. Скажем, у меня есть 2D AABB (определяемый нижним левым и верхним правым углами), и я хочу повернуть его на 45 градусов.

---------
|       |
|       |   ->   ???
|       |
---------

Фактическая область пространства, которую это представляет, очевидно, будет выглядеть как ромб:

    / \
  /     \
/         \
\         /
  \     /
    \ /

Однако, поскольку мы хотим закодировать это как AABB, результирующий AABB должен будет выглядеть следующим образом:

-------------
|    / \    |
|  /     \  |
|/         \|
|\         /|
|  \     /  |
|    \ /    |
-------------

Однако, глядя на ваш код:

mat4_mul_vec4(&min, &model_matrix, &min); 
// diff: using model matrix now
mat4_mul_vec4(&max, &model_matrix, &max); 
AABB aabb = {{min.x, min.y, min.z}, {max.x, max.y, max.z}};

Что вы делаете, так это создаете AABB, BL и TR которого являются преобразованными BL и TR из исходного AABB:

    / \    
  /     \  
/         \
-----------
\         /
  \     /  
    \ /    

Что вам нужно сделать, так это преобразовать все 8 углов исходного AABB и построить вокруг него новый AABB. Но работа с самолетами отбраковки в мировом пространстве также абсолютно нормальна для большинства случаев.

В качестве альтернативы, если ваша проблема хорошо подходит для ограничивающих сфер, вы можете избавить себя от многих проблем, используя это вместо этого.

person Frank    schedule 06.12.2018
comment
Спасибо. Я натягивал на это волосы, упустив такую ​​тонкую, но важную деталь. - person wingerse; 06.12.2018