2015-12-27 3 views
0

Я написал этот код, чтобы анимировать аттрактор Лоренца:C++ OpenGL с freeglut непрерывного пересчитанного графом мерцающего

#include <iostream> 
#include <GL/freeglut.h> 
double x = 1, y = 1, z = 1, a = 10, b = 28, c = 8/3, precision = 0.000001, lastx = x, lasty = y, lastz = z; 
int counter = 0; 
void draw() { 
    glBegin(GL_LINES); 
     glVertex2d(lastx, lasty); 
     glVertex2d(x, y); 
    glEnd(); 
    lastx = x; 
    lasty = y; 
    double dxdt = a*(y-x); 
    double dydt = x*(b-z)-y; 
    double dzdt = x*y-c*z; 
    x += precision*dxdt; 
    y += precision*dydt; 
    z += precision*dzdt; 
    counter++; 
    if (counter == 40000) 
    { 
     glutSwapBuffers(); 
     counter = 0; 
    } 
    glutPostRedisplay(); 
} 
void mykey(unsigned char mychar, int x, int y) { 
    if (mychar == 27) { 
     exit(0); 
    } 
} 
int main(int argc, char **argv) { 
    glutInit(&argc, argv); 
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); 
    glutInitWindowSize(1000, 1000); 
    glutCreateWindow("Lorenz Attractor"); 
    glutDisplayFunc(draw); 
    glutKeyboardFunc(mykey); 
    glClearColor(0, 0, 0, 1); 
    glColor4d(0, 0, 1, 1); 
    glViewport(0, 0, 1000, 1000); 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    gluOrtho2D(-30, 30, -30, 30); 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    glEnable(GL_BLEND); 
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
    glEnable(GL_POINT_SMOOTH); 
    glPointSize(1); 
    glutFullScreen(); 
    glutMainLoop(); 
} 

Проблема заключается в том, я не имею ни малейшего представления о том, как рисовать непрерывный график, кроме сшивания тысячи линий с 2 точки. Он начинает мерцать через некоторое время, и я думаю, что это причина. Любые идеи о том, как исправить? Благодаря!

P.S. Кроме того, если вы чувствуете себя более щедрым, бросьте мне несколько советов о том, как реализовать масштабирование и белую точку на движущемся конце графика. Если вы видите что-то, что может быть улучшено, сообщите мне. Еще раз спасибо!

EDIT:

Использование одного буфера с glFlush() исправлена ​​проблема, двойной буфер будет работать только, если есть способ, чтобы скопировать передний буфер для возврата в буфер перед сменой. Если есть такой способ, дайте мне знать.

+2

Вы должны безоговорочно вызвать 'glutSwapBuffers()' в конце функции 'draw()'. В противном случае 39999 из 40000 кадров, которые вы оказываете, никогда не отображаются. –

+0

Если я меняю буфер каждый раз, он очень медленно рисуется, так как моя точность равна 0,000001. Если я использую большее число, график становится неточным. – DDomjosa

ответ

1

Вы используете окно с двойным буферизацией opengl. Если вы хотите сделать анимацию в этом случае, вы должны

  • сделать полный кадр, который будет отображаться на заднем буфер
  • подкачки буферов для отображения кадра
  • сделать следующий кадр из начать

ключевым моментом здесь является то, что после SwapBuffers вызова, содержимое заднего буфера становится неопределенную. Ваша реализация происходит, чтобы переключаться между некоторыми предыдущими фреймбуферами. Это означает, что вы рисуете 40000 строк, поменяйте буферы так, чтобы они были показаны, нарисуйте следующие 40000 строк в другой буфер, не содержащий 40000 предыдущих строк, и так далее, чтобы вы получили мерцание.

Если вы хотите, чтобы ваш рисунок, чтобы «расширить» каждый кадр, у вас есть несколько вариантов:

  1. фактически хранить свои строки в некоторой структуре данных и перерисовать весь образ каждый кадр
  2. скопировать результат вашего последнего кадра в новый буфер обратно после обмена. (Более эффективным способом будет рендеринг текстуры).
  3. Использование одного буферизация (замените GLUT_DOUBLE флаг на GLUT_SINGLE и использовать glFlush вместо glutSwapBuffers)

Третий вариант может показаться, что лучший (и самый простой) решение для Вас, но концептуально, это самый худший. Вы должны переосмыслить способ реализации анимаций в OpenGL.

+0

Спасибо за ответ. Второй вариант звучит неплохо, есть ли функция, которая копирует кадр в другой буфер? Я не смог найти что-либо в Google. – DDomjosa

+0

Я не уверен, но 'glBlitFramebuffer' _might_ даже способен копировать содержимое переднего буфера в задний буфер, если вы установите соответственно' glReadBuffer' и 'glDrawBuffer'. – derhass

+0

Он говорит, что glBlitFramebuffer не объявлен ... Я просто буду придерживаться единого буфера, это только для школьного проекта. – DDomjosa

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

  • Нет связанных вопросов^_^