2013-01-09 5 views
1

gluUnProject에서 문제가 발생합니다. 정확하지 않은 Z 좌표를 검색 중이기 때문입니다.일부 조건에서 gluUnProject가 정확하지 않은 Z 좌표를 반환합니다.

관련된 프로그램은 본질적으로 3d 뷰어입니다. 작은 함수를 구현하여 사용자가로드 된 모델을 클릭하고 두 점 사이의 거리를 검색 할 수있게했습니다.

// Declare variables for viewport, modelview and projection matrix 
int viewport[] = new int[4]; 
float modelview[] = new float[16]; 
float projection[] = new float[16]; 
// GL y-coordinate position 
int realY; 
// Returned [wx, wy, wz, 1] coordinates 
float worldCoordinates[] = new float[4]; 

gl2.glGetIntegerv(GL2.GL_VIEWPORT, viewport, 0); 
gl2.glGetFloatv(GL2.GL_MODELVIEW_MATRIX, modelview, 0); 
gl2.glGetFloatv(GL2.GL_PROJECTION_MATRIX, projection, 0); 

// Retrive the Y coordinate, note viewport[3] is height of window in pixels 
realY = viewport[3] - click.y - 1; 

// Allocate a buffer to store the result 
FloatBuffer fb = FloatBuffer.allocate(1); 

// Retrieve the Z coordinate, read a block of pixels from the frame buffer 
gl2.glReadPixels(click.x, realY, 1, 1, GL2.GL_DEPTH_COMPONENT, GL2.GL_FLOAT, fb); 

System.out.println("Depth: "+fb.get(0)); 

// Avoid centering if the click is on nothing 
if (fb.get(0) == 1.0f) { 
    return null; 
} 
// Map window coordinates to object coordinates, retrieve the world coordinates 
glu.gluUnProject(click.x, realY, fb.get(0), modelview, 0, projection, 0, 
      viewport, 0, worldCoordinates, 0); 

내가 두 점 사이의 거리가 사용자의 모든 수직 표면에 누워 측정하고 제대로 작동 :

는 코드입니다. 3 축 시스템을 이미지화하면 z가 사용자를 향하고 y가 위쪽을 향하며, 두 점은 XY 평면에 놓입니다. 그것은

enter image description here

예를 들어, 여기에 내가 작은 사각형 평면을 생성 Z. 주위에 어떤 회전에 관계없이 작동하고 모두 두 점은 같은 높이 (하나는 레이블로 가려)이 있습니다

세계 좌표를 P1 : (0.019062456, 0.03357359, 0.08333321는, 1)

세계 P2 좌표 : (0.025983132, 0.028048635, 0.08333321, 1)

을하지만 글로벌 X 축을 통해 전체 장면을 회전 할 경우, R 어떤 중요한 것은 Z 하나,

enter image description here

X 및 Y 좌표는 중요하지 않습니다 etrieved Z는 변화를 조정합니다. 더 이상 0.08333321이 아닙니다.

세계 P1 좌표 (0.020072304는 0.034560144는 0.08312501는, 1)

는 또한 글로벌 X 이상의 회전은 또한 줌이 영향을 후 (0.026863147는 0.027185505는 0.0831252 1)

세계 P2 좌표 포인트의 Z 좌표.

Ps : JOGL을 사용하고 있습니다. 줌 인/아웃은 glOrtho 평행 육면체를 확대/축소하여 수행됩니다. glReadPixels에 의해 생성 된 Z 깊이 fb.get (0)은 [0, 1]에 포함됩니다.

어디서 잘못 되었나요?

답변

1

비행기의 정확한 좌표를 볼 것으로 예상됩니까? 이 방법으로는 얻을 수 없습니다.

사각형을 렌더링하면 좌표가 3D로 변환되고 원시는 래스터 화 (즉 2D로 변환되고 보간)되어 화면 X, Y 및 (일반적으로) 24 비트 심도 값을 생성합니다. 이것은 정밀도의 손실입니다 (그리고 심지어 선형 적이 지 않습니다). 그래서 그것을 읽고 변환을 역전하면 원래 값에 근사 만 있습니다.

다각형이 뷰 방향에 수직 인 경우 보간법은 표면 전체에 일관된 z 값을 부여합니다 (변환 된 모든 Z 값은 동일하므로). 반드시 그렇지 않을 수도 있습니다. 오른쪽 z 값. 따라서 깊이를 변경하면 오류가 변경되고 평면이 수직이 아닌 경우 폴리에서 일관성이 없어집니다.

깊이는 기본적으로 너무 많은 오류없이 (그리고 그다지 그렇지 않은 경우에도) 그리기에 충분하지만 정확한 형상을 재구성하는 데는 충분하지 않습니다.

더 나은 결과를 얻으려면 실제 모델 공간 X, Y, Z를 셰이더가있는 (부동) FBO로 래스터 화 한 다음 다시 읽을 수 있습니다. 또는 광선을 소프트웨어에서 지오메트리와 교차 시키십시오.

+0

답장을 보내 주신 JasonD에게 감사드립니다. 근심/보간 오류입니다. 그러나 상황을 개선하기에 충분할 정도로 단지 FBO일까요? 나는 현재 어느 것을 사용하고 있는지 어떻게 확인할 수 있습니까? – elect

+0

명시 적으로 FBO를 작성하지 않았다면 창으로 렌더링됩니다. 그래서 아마도 채널당 8 비트 버퍼 일 것입니다. 어떤 경우 든 필요한 정보를 더 적절한 형식과 공간에 직접 저장할 수있는 추가 버퍼를 제안합니다. 가치가 있는지 여부 (또는 충분한 지 여부)는 정확한 요구 사항에 따라 다릅니다. – JasonD

+0

아니요, OpenGL 기본 FBO를 사용하고 있습니다. 따라서 특정 형식 (float)으로 추가 FBO를 만들 것을 제안합니다. 나는 지금 당장 인터넷 검색을하고 있지만 내 목적을 위해 유용하고 구체적인 것을 발견 할 수 없다. 아마도 이것에 관해 좋은 링크를 가지고있을 것인가? (float FBO의 생성) – elect