Рисование бесконечных циклов в OpenGL и ломаных линиях - PullRequest
2 голосов
/ 31 января 2012

Вопрос о бесконечном цикле

Я хочу добиться эффекта, как показано на рисунке:

enter image description here

Я генерирую это путем включения бесконечного цикла в функцию обратного вызова glutDisplayFunct, и это не хорошо, так как я не могу затем обработать любой ввод с клавиатуры. Другой способ, о котором я могу подумать, это, вероятно, использовать явные функции обновления окна перенасыщения.

Я хочу знать, как я могу вставить бесконечный цикл, а также проверить ввод с клавиатуры. Вот пример кода, который я сделал. Он просто реализует алгоритм DDA и пытается рисовать бесконечные линии, генерируя случайные координаты и цвета.

#include <stdio.h>
#include <GL/glut.h>

int width;
int height;

void dda (int x1, int y1, int x2, int y2)
{
  int del_x, del_y, sample_steps, i = 1;
  double x_incr, y_incr, x, y;

  del_x = x2 - x1;
  del_y = y2 - y1;
  sample_steps = (abs (del_x) > abs (del_y)) ? abs (del_x) : abs (del_y);

  x_incr = del_x / (double) sample_steps;
  y_incr = del_y / (double) sample_steps;

  x = x1;
  y = y1;


  glBegin (GL_POINTS);
  while (i<=sample_steps)
  {
    glVertex2f ((2.0 * x)/width, (2.0 * y)/height);
    x += x_incr;
    y += y_incr;
    i++;
  }
  glEnd ();

  glFlush ();
}

void keypress_handler (unsigned char key, int x, int y)
{
  if (key == 'q' || key == 'Q')
  {
    glutLeaveMainLoop ();
  }
}

void init_screen (void)
{
  glMatrixMode (GL_PROJECTION);
  glClearColor (0, 0, 0, 1);
  glClear (GL_COLOR_BUFFER_BIT);
  glLoadIdentity ();
  glMatrixMode (GL_MODELVIEW);
}

void test_dda (void)
{
  int x1, y1, x2, y2;
  float r, g, b;

  int i=1;

  glClear (GL_COLOR_BUFFER_BIT);
  srand (time(NULL));
  width = glutGet (GLUT_WINDOW_WIDTH);
  height = glutGet (GLUT_WINDOW_HEIGHT);

  while (i)
  {
    x1 = rand () % width  - (width  /2);  /* Global */
    y1 = rand () % height - (height /2); /* Global */
    x2 = rand () % width  - (width  /2);  /* Global */
    y2 = rand () % height - (height /2); /* Global */

    r = rand () / (float) RAND_MAX;
    g = rand () / (float) RAND_MAX;
    b = rand () / (float) RAND_MAX;

    glColor3f (r, g, b);
    dda (x1, y1, x2, y2);
    printf ("\r%d", i);
    i++;
  }

}

void reshape (int w, int h)
{
  glViewport (0, 0, w, h);
  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();
  gluOrtho2D (-1, 1, -1, 1);
  glMatrixMode (GL_MODELVIEW);
}

int main (int argc, char *argv[])
{
  glutInit (&argc, argv);
  glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
  init_screen ();
  glutCreateWindow ("DDA");
  glutDisplayFunc (test_dda);
  glutReshapeFunc (reshape);
  glutKeyboardFunc (keypress_handler);

  glutMainLoop ();

  printf ("\n");
  return 0;
}

Неровные линии при первом рисовании

Также у меня есть дополнительный вопрос, который выглядит так:

Когда я раскомментирую бесконечный цикл (while (i)) внутри функции test_dda и запускаю исполняемый файл с размером экрана 1280x960, каждая нарисованная линия отображается в виде ломаных линий, они выглядят как пунктирные линии. Но, если я не зацикливаюсь в этой функции и рисую линии другим способом, например, заставляю OpenGL перерисовывать линии, линии отображаются так, как они должны отображаться. Я заметил, что при рисовании в первый раз, линии показывают ломаные. Пунктирные линии, о которых я говорю, показаны ниже:

enter image description here

Чтобы понять, что я говорю, сделайте следующее, чтобы получить эффект. Измените while (i) на while (i<1000). Это нарисует 1000 линий на экране. Когда я запускаю это изменение с размером окна 1280x960, окно рисуется 2 раза. В первый раз, когда линии нарисованы, они выглядят такими же ломаными, как на изображении выше. В тот момент, когда нарисованы 1000 линий, окно снова очищается, и оно снова рисуется, но на этот раз линии отображаются в порядке. Почему это происходит?

Ответы [ 3 ]

3 голосов
/ 31 января 2012

Вам не нужно. Бесконечный цикл уже происходит внутри glutMainLoop(). Он будет вызывать вашу функцию отображения снова и снова, пока программа не закроется. Чтобы сохранить вывод предыдущих кадров (т. Е. Рисовать поверх них), не очищайте буфер цвета с помощью glClear().

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

То, что вы пытаетесь сделать здесь, это, по сути, попытка сделать программный рендеринг поверх аппаратно-ускоренного рендеринга, что просто странно и не очень рекомендуется.

1 голос
/ 31 января 2012

Функция «display» (test_dda в вашем случае) вызывается каждый раз, когда необходимо перерисовать окно.Код обработки событий в GLUT не изменится при выполнении, если вы находитесь в бесконечном цикле внутри функции отображения.

Вместо этого используйте таймер и нарисуйте одну линию в функции таймера, а затем вызовите функцию, чтобы вызвать GLUTперерисовать окно, где вы «очищаете» трубу GL.

0 голосов
/ 31 января 2012

Я думаю, что исходное решение, которое вы принимаете, концептуально неверно.

Не прими меня плохо:)

Если цель состоит в том, чтобы постоянно рисовать линии снова и снова, одним из возможных решений было бы сегментировать процесс следующим образом:

  • FRAME 1 ШАГ1: Вы рисуете линии на кадровом буфере, сопоставленные с текстурой поверх квада, содержащего рабочую текстуру
  • FRAME 1 ШАГ2: Вы рисуете квад с рабочей текстурой
  • ЗВОНОК ВСТРОЕННОГО ВХОДА
  • FRAME 2 ШАГ1: Вы рисуете линии на кадровом буфере, сопоставленные с текстурой поверх квада, содержащего рабочую текстуру
  • КАДР 1 ШАГ2: Вы рисуете четырехугольник с выходной рабочей текстурой
  • ЗВОНОК ВСТРОЕННОГО ВХОДА

и так далее .....

...