2014-09-08 2 views
-1

Я пишу гравитационное моделирование n-тела на C++, которое анимируется с использованием OpenGL и GLUT (это хобби-проект). Анимация работает отлично, по большей части, однако у меня было две основных проблемы, которые я не в состоянии решить:Применение теста глубины 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/close слишком высоко! Я исправлю это и вернусь к вам. – Chronos

+0

Я уменьшил плоскость отсечения от расстояния до близкого к <100, и он исправил обе проблемы. Спасибо!! Я потратил несколько часов на поиск подобного вопроса, прежде чем публиковать свои собственные, но не нашел ваш. – Chronos

ответ

0

буфера глубина OpenGL имеет ограниченную точность, а также номера, которые вы используете достаточно велики, что может быть запущены в эту точности предел. Вы можете прочитать this article about depth-buffer optimization или просто использовать большую единицу, чем метры для представления астрономических расстояний.

+0

Да, точность была проблемой; Я уменьшил все расстояния до анимации, однако я также масштабировал мой ближний отсек, делая его крошечным. Это привело к тому, что мой дальний/ближний рацион оставался слишком большим, вызывая глубокие бои. Спасибо за Ваш ответ. – Chronos

Смежные вопросы