2012-08-03 5 views
0

몇 가지 간단한 경계 상자 테스트를 수행하기 위해 절두체를 계산하려고합니다.OpenGL/GLM - 절두체 문제 계산

void CFrustum::calculateFrustum(glm::mat4* mat) 
{ 
    // Calculate the LEFT side 
    m_Frustum[LEFT][A] = *glm::value_ptr(mat[0][3]) + *glm::value_ptr(mat[0][0]); 
    m_Frustum[LEFT][B] = *glm::value_ptr(mat[1][3]) + *glm::value_ptr(mat[1][0]); 
    m_Frustum[LEFT][C] = *glm::value_ptr(mat[2][3]) + *glm::value_ptr(mat[2][0]); 
    m_Frustum[LEFT][D] = *glm::value_ptr(mat[3][3]) + *glm::value_ptr(mat[3][0]); 

    // Calculate the RIGHT side 
    m_Frustum[RIGHT][A] = *glm::value_ptr(mat[0][3]) - *glm::value_ptr(mat[0][0]); 
    m_Frustum[RIGHT][B] = *glm::value_ptr(mat[1][3]) - *glm::value_ptr(mat[1][0]); 
    m_Frustum[RIGHT][C] = *glm::value_ptr(mat[2][3]) - *glm::value_ptr(mat[2][0]); 
    m_Frustum[RIGHT][D] = *glm::value_ptr(mat[3][3]) - *glm::value_ptr(mat[3][0]); 

    // Calculate the TOP side 
    m_Frustum[TOP][A] = *glm::value_ptr(mat[0][3]) - *glm::value_ptr(mat[0][1]); 
    m_Frustum[TOP][B] = *glm::value_ptr(mat[1][3]) - *glm::value_ptr(mat[1][1]); 
    m_Frustum[TOP][C] = *glm::value_ptr(mat[2][3]) - *glm::value_ptr(mat[2][1]); 
    m_Frustum[TOP][D] = *glm::value_ptr(mat[3][3]) - *glm::value_ptr(mat[3][1]); 

    // Calculate the BOTTOM side 
    m_Frustum[BOTTOM][A] = *glm::value_ptr(mat[0][3]) + *glm::value_ptr(mat[0][1]); 
    m_Frustum[BOTTOM][B] = *glm::value_ptr(mat[1][3]) + *glm::value_ptr(mat[1][1]); 
    m_Frustum[BOTTOM][C] = *glm::value_ptr(mat[2][3]) + *glm::value_ptr(mat[2][1]); 
    m_Frustum[BOTTOM][D] = *glm::value_ptr(mat[3][3]) + *glm::value_ptr(mat[3][1]); 

    // Calculate the FRONT side 
    m_Frustum[FRONT][A] = *glm::value_ptr(mat[0][3]) + *glm::value_ptr(mat[0][2]); 
    m_Frustum[FRONT][B] = *glm::value_ptr(mat[1][3]) + *glm::value_ptr(mat[1][2]); 
    m_Frustum[FRONT][C] = *glm::value_ptr(mat[2][3]) + *glm::value_ptr(mat[2][2]); 
    m_Frustum[FRONT][D] = *glm::value_ptr(mat[3][3]) + *glm::value_ptr(mat[3][2]); 

    // Calculate the BACK side 
    m_Frustum[BACK][A] = *glm::value_ptr(mat[0][3]) - *glm::value_ptr(mat[0][2]); 
    m_Frustum[BACK][B] = *glm::value_ptr(mat[1][3]) - *glm::value_ptr(mat[1][2]); 
    m_Frustum[BACK][C] = *glm::value_ptr(mat[2][3]) - *glm::value_ptr(mat[2][2]); 
    m_Frustum[BACK][D] = *glm::value_ptr(mat[3][3]) - *glm::value_ptr(mat[3][2]); 

    // Normalize all the sides 
    NormalizePlane(m_Frustum, LEFT); 
    NormalizePlane(m_Frustum, RIGHT); 
    NormalizePlane(m_Frustum, TOP); 
    NormalizePlane(m_Frustum, BOTTOM); 
    NormalizePlane(m_Frustum, FRONT); 
    NormalizePlane(m_Frustum, BACK); 
} 

이제 누군가가 내가 열/행에 대한 잘못된 순서를 하더군요 전에, 나는 운이 그들 모두를 시도 :

여기 내 기능입니다.

내가 이렇게 내 행렬을 얻기의 고정 기능 모드로 전환 :

glGetFloatv(GL_PROJECTION_MATRIX, proj); 

glGetFloatv(GL_MODELVIEW_MATRIX, modl); 

실제로 매트릭스를 전달하기 위해. 이 시점에서 렌더링하는 유일한 것은 월드 버텍스입니다. 문제는 내 경계 상자 위치가 내가 차지하는 세계의 오프셋을 고려하지 않는다는 것입니다. 지금 렌더링하고있는 유일한 것은 절대 위치 글로벌 정점, 나는 아무것도 모델 매트릭스를 사용하지 않는 때문에

cameraMatrix = glm::lookAt(position, position+direction, up); 
projectionMatrix = glm::perspective(50.0f, 4.0f/3.0f, 0.1f, 1000.f); 
viewMatrix = projectionMatrix * cameraMatrix; 

:

여기 내 행렬 생성합니다.

내 상자 대 frustum 코드가 맞다고 확신합니다. 누구든지 내 계산 코드에 오류가 있거나 실제로 바인딩 상자 정점을 변환해야한다는 것을 알고 있습니까?

감사합니다.

답변

1

월드 좌표로 테두리 상자를 사용하는 경우에는 viewsMatrix를 calculateFrustum에 전달해야합니다.

Fustum에 viewMatrix를 전달하면 세계 공간에서 평면이 생성됩니다.

calculateFrustum 대신 projectionMatrix를 전달하는 경우 교차 테스트를 수행하기 전에 cameraMatrix를 경계 상자에 적용해야합니다.

+0

그래서, 그냥 그렇게 우리가 용어에 분명, 내보기 매트릭스 카메라 번역, 회전 및 결합 투영 행렬 모두이다. 나는 그것을 지나쳤다. 나는 여전히 오류가있는 것 같다. 어떤 행렬을 전달했는지에 상관없이, 세계 공간에서 경계 상자를 분석하지 않는 것 같습니다. –

+0

우리는 용어에 동의합니다. 이전 포스트에서 게시 한 논문에 따르면 다음과 같이 말합니다. "행렬이 결합 투영 및 모델 뷰 행렬과 같으면 알고리즘이 모델 공간에서 클리핑 평면을 제공합니다 (예 : V * P = M , 여기서 V는 모델 뷰 행렬이고 P는 투영법 행렬입니다.) " 귀하의 경우에 M은 viewMatrix이며 작동해야합니다. – brano

+0

알겠습니다. 고맙습니다. 나는 계속 지킬 것이다. –

0

나는 똑같은 일을 시도하고이 코드를 사용하려고 시도하여 문제를 발견했습니다. 일반적인 포인터 혼동입니다.

이 해결 방법의 첫 번째 라인 :

m_Frustum[LEFT][A] = (*mat)[0][3] + (*mat)[0][0];