2012-10-29 1 views
5

원근감 행렬의 원거리 평면 거리를 1,000,000,000으로 정의하면 해당 범위 내의 모든 객체가 잘립니다. 범위는 100,000,000입니다. 누구나 설명 할 수 있습니까? 내 말은, 여전히 플로트 수의 최대 범위에 근접하지 않는다는 것입니다. 아니면 내가 잘못 했니? 관점을 계산하기 위해 GLM 라이브러리를 사용합니다. 고정 된 파이프 라인 딱딱함이 없습니다.OpenGL Far Plane의 값이 매우 큰 클립 모두

UPDATE : (JAVA) 관점 매트릭스 계산 : 부동 소수점 숫자를 매우 유한 정밀도에

public static Mat4 perspective(float fovy, float aspect, float zNear, float zFar) { 
    float range = (float) (Math.tan(Math.toRadians(fovy/2.0f)) * zNear); 
    float left = -range * aspect; 
    float right = range * aspect; 
    float bottom = -range; 
    float top = range; 

    Mat4 res = new Mat4(0.0f); 

    res.matrix[0] = (2.0f * zNear)/(right - left); 
    res.matrix[5] = (2.0f * zNear)/(top - bottom); 
    res.matrix[10] = -(zFar + zNear)/(zFar - zNear); 
    res.matrix[11] = -1.0f; 
    res.matrix[14] = -(2.0f * zFar * zNear)/(zFar - zNear); 

    return res; 
    } 
+2

내가 질문을 이해하지만, 단 정밀도 부동 소수점 7 개 소수점 자리를 통해 조금을 표시 할 수 없습니다. 귀하의 전화 번호는 10 자리 숫자이므로 마지막 3 자리 숫자 만 다른 좌표는 "같은"것입니다. 따라서 999,999,950이 클리핑 될 수 있습니다. 그게 니가 궁금해 한거야? – Damon

+1

반올림 문제 또는 이와 유사한 것 같습니다. 물론 float 범위를 넘지 않습니다 (32 비트 int 범위를 넘지 않습니다). 그러나 큰 숫자로 나누면 모든 것이 0으로 바뀔 수 있습니다. 마찬가지로 행 수가 계산되는 동안'near + far' 또는'near-far' 에서처럼이 큰 숫자에 아주 작은 숫자를 추가 할 때 그 수는 아마도 변하지 않게 유지하십시오. 이것이 매트릭스의 계산에 어떤 영향을 미치는지 분석 할 필요가 있습니다. –

+0

대답 해줘서 고마워.하지만 너보다 위의 남자가 그 반대라고 했어. –

답변

8

당신이보고있는 것은 반올림 문제입니다.

부동 소수점 숫자는 거대한 (대부분의 실제 응용 프로그램에서 "무한") 범위를 갖지만 같은 크기의 정수보다 훨씬 작은 제한된 정밀도를 갖습니다. 단일 정밀도 (32 비트) float은 소수점 이하 7 자릿수를 거의 나타낼 수 없습니다. 당신은 매우 작거나 큰 (당신이 상상할 수있는 것보다 더 크고 더 큽니다) 숫자를 가질 수 있습니다, 그러나 그들은 여전히 ​​단지 7.22의 유효 십진수를 가지고 있습니다. 999999872가, 999999936, 1000000000, 그리고 1000000064. 당신은 쉽게 float 변수에 캐스팅하는 for 루프의 정수 변수를 계산하여 확인할 수 있으며, :

유일한 번호

는 999,999,900과 1,000,000,100 사이의 단 정밀도 float로서 표현할 수는 있습니다 인쇄.

예를 들어 999,999,950과 999,999,951 및 999,999,999가 정확히 같은 숫자이므로 999,999,950이 클리핑 기준면에서 "명백하게"보이더라도 잘릴 수 있습니다.

편집 : 출력

리틀 데모 프로그램 :

#include <stdio.h> 

int main() 
{ 
    float f = 0.0f; 
    for(int i = 999999900; i < 1000000100; ++i) 
    { 
     f = i; 
     printf("%d\t%f\n", i, f); 
    } 
    return 0; 
} 

999999900  999999872.000000 
999999901  999999872.000000 
999999902  999999872.000000 
999999903  999999872.000000 
999999904  999999872.000000 
999999905  999999936.000000 
999999906  999999936.000000 
999999907  999999936.000000 
... 
[some lines omitted] 
... 
999999967  999999936.000000 
999999968  1000000000.000000 
999999969  1000000000.000000 
999999970  1000000000.000000 
999999971  1000000000.000000 
999999972  1000000000.000000 
... 
[some lines omitted] 
... 
1000000028  1000000000.000000 
1000000029  1000000000.000000 
1000000030  1000000000.000000 
1000000031  1000000000.000000 
1000000032  1000000000.000000 
1000000033  1000000064.000000 
1000000034  1000000064.000000 
1000000035  1000000064.000000 
1000000036  1000000064.000000 
1000000037  1000000064.000000 
1000000038  1000000064.000000 
1000000039  1000000064.000000 
1000000040  1000000064.000000 
1000000041  1000000064.000000 
1000000042  1000000064.000000 
1000000043  1000000064.000000