Отбор работает с извлечением плоскостей из матрицы проекции вида, но не с матрицей проекции - PullRequest
0 голосов
/ 06 декабря 2018

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

В статье упоминается, что если матрица является матрицей проекции, то будут видны плоскости-пространство.Поэтому мне нужно преобразовать мои координаты 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
}

Result Похоже, это отбраковка слишком большая.Также обратите внимание: это ненормальное отбраковка происходит только тогда, когда я смотрю в положительном направлении 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
}

enter image description here Идеально

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

1 Ответ

0 голосов
/ 06 декабря 2018

Что на самом деле означает преобразование 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 вокруг этого.Но работа с плоскостями отбора в мировом пространстве в большинстве случаев также абсолютно подходит.

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

...