Тест видимости OpenGL Frustum со сферой: дальняя плоскость не работает

Я делаю программу для проверки пересечения сферы и усечённости и могу определить видимость сферы. Я извлекаю плоскости отсечения фрустума в пространство камеры и проверяю на пересечение. Он отлично работает для всех самолетов, кроме дальнего, и я не могу понять, почему. Я продолжаю тянуть камеру назад, но моя программа все еще утверждает, что сфера видна, несмотря на то, что она была обрезана давно. Если я зайду достаточно далеко, это в конечном итоге определит, что его не видно, но это какое-то расстояние после выхода из усеченного конуса.

Я использую единичную сферу в начале координат для теста. Я использую библиотеку математики OpenGL (GLM) для векторных и матричных структур данных и для ее встроенных математических функций. Вот мой код для функции видимости:

void visibilityTest(const struct MVP *mvp) {
static bool visLastTime = true;
bool visThisTime;
const glm::vec4 modelCenter_worldSpace = glm::vec4(0,0,0,1);    //at origin
const int negRadius = -1;   //unit sphere

//Get cam space model center
glm::vec4 modelCenter_cameraSpace = mvp->view * mvp->model * modelCenter_worldSpace;
//---------Get Frustum Planes--------
//extract projection matrix row vectors
//NOTE: since glm stores their mats in column-major order, we extract columns
glm::vec4 rowVec[4];
for(int i = 0; i < 4; i++) {
rowVec[i] = glm::vec4( mvp->projection[0][i], mvp->projection[1][i], mvp->projection[2][i], mvp->projection[3][i] );
}

//determine frustum clipping planes (in camera space)
glm::vec4 plane[6];
//NOTE: recall that indices start at zero. So M4 + M3 will be rowVec[3] + rowVec[2]
plane[0] = rowVec[3] + rowVec[2];   //near
plane[1] = rowVec[3] - rowVec[2];   //far
plane[2] = rowVec[3] + rowVec[0];   //left
plane[3] = rowVec[3] - rowVec[0];   //right
plane[4] = rowVec[3] + rowVec[1];   //bottom
plane[5] = rowVec[3] - rowVec[1];   //top

//extend view frustum by 1 all directions; near/far along local z, left/right among local x, bottom/top along local y
// -Ax' -By' -Cz' + D = D'
plane[0][3] -= plane[0][2];     // <x',y',z'> = <0,0,1>
plane[1][3] += plane[1][2];         // <0,0,-1>
plane[2][3] += plane[2][0];         // <-1,0,0>
plane[3][3] -= plane[3][0];         // <1,0,0>
plane[4][3] += plane[4][1];         // <0,-1,0>
plane[5][3] -= plane[5][1];         // <0,1,0>

//----------Determine Frustum-Sphere intersection--------
//if any of the dot products between model center and frustum plane is less than -r, then the object falls outside the view frustum
visThisTime = true;
for(int i = 0; i < 6; i++) {
if( glm::dot(plane[i], modelCenter_cameraSpace) < static_cast<float>(negRadius) ) {
visThisTime = false;
}
}
if(visThisTime != visLastTime) {
printf("Sphere is %s visible\n", (visThisTime) ? "" : "NOT " );
visLastTime = visThisTime;
}
}

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

Расчеты, которые конкретно относятся к дальней плоскости отсечения:

plane[1] = rowVec[3] - rowVec[2];   //far

а также

plane[1][3] += plane[1][2];         // <0,0,-1>

Я устанавливаю плоскость, равную 4-й строке (или в данном случае столбцу) матрицы проекции — 3-й строке матрицы проекции. Затем я расширяю дальнюю плоскость еще на одну единицу (из-за радиуса сферы, равного единице; D ‘= D — C (-1))

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

РЕДАКТИРОВАТЬ:
Я не могу ответить на свой вопрос, так как у меня нет представителя, поэтому я опубликую его здесь.
Проблема заключалась в том, что я не нормализовал уравнения плоскости. Похоже, что это не имело большого значения для какой-либо из плоскостей зажима, кроме далекой, поэтому я даже не учел это (но это не сделало его менее неправильным). После нормализации все работает нормально.

3

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]