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