Итак, я реализовал Frustum Culling в своем игровом движке, и у меня возникла странная ошибка. Я визуализирую здание, которое сегментировано на куски, и я визуализирую только те куски, которые находятся в усеченной пирамиде. Моя камера начинается примерно с (-033, 11,65, 2,2), и все выглядит нормально. Я начинаю двигаться, и мерцания нет. Когда я устанавливаю точку останова в коде отсечения усеченной пирамиды, я вижу, что он действительно отсеивает некоторые из мешей. Вроде все отлично. Затем, когда я добираюсь до центра здания, меши вокруг (3.9, 4.17, 2.23) начинают исчезать, которые находятся в поле зрения. То же верно и для другой стороны. Я не могу понять, почему эта ошибка могла существовать.
Я реализую отсечение усеченного конуса, используя перечисленный здесь метод извлечения Извлечение Просмотреть самолеты Frustum (метод Грибба и Хартмана). Мне пришлось использовать glm :: inverse () вместо того, чтобы транспонировать, как он предлагал, и я думаю, что математическая матрица была дана для матриц с старшими строками, поэтому я перевернул это. В целом мой расчет усеченного самолета выглядит как
std::vector<Mesh*> render_meshes;
auto comboMatrix = proj * glm::inverse(view * model);
glm::vec4 p_planes[6];
p_planes[0] = comboMatrix[3] + comboMatrix[0]; //left
p_planes[1] = comboMatrix[3] - comboMatrix[0]; //right
p_planes[2] = comboMatrix[3] + comboMatrix[1]; //bottom
p_planes[3] = comboMatrix[3] - comboMatrix[1]; //top
p_planes[4] = comboMatrix[3] + comboMatrix[2]; //near
p_planes[5] = comboMatrix[3] - comboMatrix[2]; //far
for (int i = 0; i < 6; i++){
p_planes[i] = glm::normalize(p_planes[i]);
}
for (auto mesh : meshes) {
if (!frustum_cull(mesh, p_planes)) {
render_meshes.emplace_back(mesh);
}
}
Затем я решаю отбраковать каждую сетку на основе ее ограничивающего прямоугольника (рассчитанного с помощью ASSIMP с флагом aiProcess_GenBoundingBoxes) следующим образом (возвращение истинного означает отбракованное)
glm::vec3 vmin, vmax;
for (int i = 0; i < 6; i++) {
// X axis
if (p_planes[i].x > 0) {
vmin.x = m->getBBoxMin().x;
vmax.x = m->getBBoxMax().x;
}
else {
vmin.x = m->getBBoxMax().x;
vmax.x = m->getBBoxMin().x;
}
// Y axis
if (p_planes[i].y > 0) {
vmin.y = m->getBBoxMin().y;
vmax.y = m->getBBoxMax().y;
}
else {
vmin.y = m->getBBoxMax().y;
vmax.y = m->getBBoxMin().y;
}
// Z axis
if (p_planes[i].z > 0) {
vmin.z = m->getBBoxMin().z;
vmax.z = m->getBBoxMax().z;
}
else {
vmin.z = m->getBBoxMax().z;
vmax.z = m->getBBoxMin().z;
}
if (glm::dot(glm::vec3(p_planes[i]), vmin) + p_planes[i][3] > 0)
return true;
}
return false;
Любое руководство?
Обновление 1: нормализация полного вектора vec4, представляющего плоскость, неверна, поскольку только vec3 представляет нормаль к плоскости. Кроме того, в этом случае нормализация не требуется, поскольку нас интересует только знак расстояния (а не величина).
Также важно отметить, что я должен использовать строки матрицы, а не столбцы. Я добиваюсь этого, заменяя
p_planes[0] = comboMatrix[3] + comboMatrix[0];
с участием
p_planes[0] = glm::row(comboMatrix, 3) + glm::row(comboMatrix, 0);
во всех случаях.