2014-09-08 2 views
-1

저는 C++에서 OpenGL과 GLUT (이것은 취미 프로젝트입니다)를 사용하여 움직이는 중력 n- 바디 시뮬레이션을 작성하고 있습니다. 깊이 테스트가 활성화되어OpenGL 깊이 테스트를 궤도에 적용하기

  • 있지만, 그것은 작동하지 예상대로 및
  • : 애니메이션 그러나 나는 두 가지 주요 해결하기 위해 제가 드릴 수 없습니다 문제를 했어, 대부분의 경우 잘 작동 표면은 ... 음, 지저분 해.

제 질문은 어떻게 수정합니까?

두 가지 문제는 다음 이미지에서 볼 수 있습니다 (링크에 사과하지만 이미지 게시에 대한 담당자가 충분하지 않음). 이것은 간단한 궤도의 시뮬레이션에서 찍은 스냅 샷으로 가장자리를 볼 수 있습니다.

Here 보라색 구형 앞에 보라색 구가 그려져 있습니다.

After half an orbit 더 멀리 있어도 노란색 구가 여전히 앞에 그려져 있습니다.

애니메이션을 만드는 데 사용 된 코드는 다음과 같습니다.

#include <GL/glut.h> 
#include "Cluster.h" // My own class. 

// Scale for animation. Each unit in the animation = 1/SCALE m. 
const double SCALE = 1e-10; 
// Size of spheres for animation. 
const double SPHERE_SIZE = 2e10*SCALE; 

// Cluster object contains bodies and updates their positions. 
Cluster cluster(); 

// Array of rgb colors for spheres. 
GLfloat colorArr[4][4] = 
{ 
    {0.7, 0.7, 0.0, 1.0}, 
    {0.73, 0.24, 0.95, 1.0}, 
} 

void display() 
{ 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    gluLookAt(0.0*SCALE, 5e11*SCALE, 0.0*SCALE // eye is on y-axis outside orbit. 
      , 0.0, 0.0, 0.0 
      , 0.0, 0.0, 1.0); 

    for (int i=0; i<N; i++) // N is the number of bodies in cluster. 
    { 
     glPushMatrix(); 
     glTranslated(SCALE*cluster.getX(i)  // Get coordinate of ith body. 
        , SCALE*cluster.getY(i) 
        , SCALE*cluster.getZ(i)); 
     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, colorArr[i]); 
     glutSolidSphere(SPHERE_SIZE, 50, 50); 
     glCullFace(GL_BACK); 
     glPopMatrix(); 
    } 

    glutSwapBuffers(); 
} 

void reshape(GLint w, GLint h) 
{ 
    glViewport(0, 0, w, h); 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    gluPerspective(30.0, (GLfloat)w/(GLfloat)h, SCALE, 5e11*SCALE); 
    glMatrixMode(GL_MODELVIEW); 
} 

void animate() 
{ 
    // Update positions and redraw. 
    cluster.update(); 
    display(); 
} 

void init() 
{ 
    GLfloat black[] = {0.0, 0.0, 0.0, 1.0}; 
    GLfloat white[] = {1.0, 1.0, 1.0, 0.5}; 
    GLfloat direction[] = {1.0, 1.0, 1.0, 0.0}; 

    glMaterialfv(GL_FRONT, GL_SPECULAR, white); 
    glMaterialf(GL_FRONT, GL_SHININESS, 10); 

    glLightfv(GL_LIGHT0, GL_AMBIENT, black); 
    glLightfv(GL_LIGHT0, GL_DIFFUSE, white); 
    glLightfv(GL_LIGHT0, GL_SPECULAR, white); 
    glLightfv(GL_LIGHT0, GL_POSITION, direction); 

    glEnable(GL_LIGHTING); 
    glEnable(GL_LIGHT0); 
    glEnable(GL_DEPTH_TEST); 
} 

int main(int argc, char** argv) 
{ 
    glutInit(&argc, argv); 
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); 
    glutInitWindowSize(800, 600); 
    glutCreateWindow("Test Orbit"); 
    glutDisplayFunc(display); 
    glutReshapeFunc(reshape); 
    glutIdleFunc(animate); 
    init(); 
    glutMainLoop(); 
} 
+0

깊이 투쟁에 대한 내 대답은 http://stackoverflow.com/questions/25580397/opengl-java-rendering-issue-polygons-flickering-and-disappearing/25588811#25588811을 참조하십시오. –

+0

감사합니다. 나를 위해 몇 가지 사항을 정리 한 훌륭한 답변입니다. 그러나 심도있는 투쟁을 피하기 위해 이미 코드에 스케일링을 포함 시켰습니다. 구체의 반경이 2.0이고 카메라가 y = 50에 위치하며 근거리 및 원거리 자르기 평면은 1e-10 및 50.0입니다. 이 글을 쓰면서 나는 far/near 비율이 너무 높다는 것을 알았다! 나는 그것을 고칠 것이고 당신에게 돌아갈 것이다. – Chronos

+0

클리핑면의 원근 비율을 100 미만으로 줄였습니다. 두 문제가 모두 수정되었습니다. 고맙습니다!! 내 질문을 게시하기 전에 비슷한 질문을 검색하는 데 몇 시간을 보냈지 만 자신을 찾지 못했습니다. – Chronos

답변

0

OpenGL의 깊이 버퍼에는 정밀도가 제한되어 있으며 사용하는 숫자가 충분히 정밀도 한계에 도달 할만큼 커야합니다. this article about depth-buffer optimization을 읽거나 천문학적 거리를 나타내는 데 미터보다 큰 단위를 사용하는 것이 좋습니다.

+0

예, 정밀도가 문제였습니다. 나는 애니메이션 이전에 모든 거리를 줄 였지만, 가까운 거리의 클리핑 비행기를 작게 만들었습니다. 이로 인해 원거리 또는 가까운 배급량이 너무 커서 심도 깊은 전투가 발생했습니다. 귀하의 답변에 감사드립니다. – Chronos

관련 문제