在OpenGL中绘制对象数组

时间:2013-09-08 00:55:47

标签: c++ opengl

我现在在我的程序中有什么: - 单击鼠标时,将创建一个形状对象并将其存储在数组中。构造函数还将刚创建的对象绘制到屏幕上。第一次单击生成一个矩形,第二次单击生成一个圆,第三次单击生成一个矩形,等等。 - 数组是圆形的,所以当它达到最大值时,它会返回并用下一个替换第一个形状。

我的程序是我试图使用for循环一次显示25个这样的形状,如下所示:

for (int i = 0; i < obj_count; i++) {
  if (objects[i].type == 0) {
      objects[i].drawRect();
  } else if (objects[i].type == 1) {
      objects[i].drawCirc();
  }
}

但是当我运行它时,有很多闪烁,只有一个矩形,一些圆圈一次出现。如果我只是尝试使用if语句一次显示一个形状来绘制数组中的最后一个形状,它可以正常工作,所以我不确定问题来自哪里。

其余的相关代码在这里:

void my_display(void) {
glClear(GL_COLOR_BUFFER_BIT) ;

for (int i = 0; i < obj_count; i++) {
      if (objects[i].type == 0) {
      objects[i].drawRect();
     } else if (objects[i].type == 1) {
      objects[i].drawCirc();
     }
 }  

glutSwapBuffers();  
return ;
}

void my_TimeOut(int id) { 
time += 1;
my_display();
glutTimerFunc(25, my_TimeOut, 0);
}

(计时器最终将用于使形状移动)

在对象类中:

void A1_Object::drawRect() {
//   glClear(GL_COLOR_BUFFER_BIT) ;
         glColor3f(0,0,1) ;
         glRectf(vertices[0], vertices[1], vertices[2], vertices[3]);
         glutSwapBuffers();
}

void A1_Object::drawCirc() {
//   glClear(GL_COLOR_BUFFER_BIT) ;
         glColor3f(1,0,0) ;

         int triangles = 50;
         GLfloat radius = 0.05; 
         GLfloat twoPi = 2 * 3.14159f;

         glBegin(GL_TRIANGLE_FAN);
            glVertex2f(center_x, center_y); 

            for (int i = 0; i <= triangles; i++) {
                glVertex2f(center_x + radius*cos(i*twoPi/triangles),     center_y + radius*sin(i*twoPi/triangles));
            }

        glEnd();            
//      glutSwapBuffers();
}

如果有人能指出我正确的方向,那就太好了!如果需要,我也可以发布完整的代码。

1 个答案:

答案 0 :(得分:2)

更新和绘制你的场景是两个非常不同的东西。您需要了解每个框架如何处理这两个应用程序事件。在某些情况下,OpenGL在自己的线程中运行,调用任何&#34; gl&#34;另一个线程的方法会破坏调用。

但我离题了。在你的冲突问题上,这是我的$ .02:

顺序,结构和形式很重要!

glutTimerFunc - 专为你的循环的UPDATE部分而设计 - 在那里调用glutSwapBuffers充其量是值得怀疑的。

使用GLUT时通常的回调订阅就像

glutDisplayFunc(display);           // opengl drawing goes here
glutTimerFunc(33, update_world, 0); // physics, ai, other stuff here

// .. callbacks ..

glutMainLoop();

在更新方法结束时,请调用 glutPostRedisplay()

void update_world(int data) 
{
    glutTimerFunc(33, update, 69); // call update() every 33ms

    // code to update the world

    // ..

    glutPostRedisplay(); // <== !
}

glutPostRedisplay()的工作原理是设置一个标志,告诉 glutMainLoop 在下一个迭代步骤中执行注册的 display()方法。如果没有明确指定,GLUT不会正确绘制下一帧。

想象一下,从示例中省略了update_world(data)中的glutPostRedisplay。即使你的矢量/缓冲区的位置会发生变化,你的世界也会显得冻结,没有动画! (我听到一分钱掉落了吗?:))

glutPostRedisplay使展开的glutMainLoop像

一样运行
update_world(69);
display();
update_world(69);
display();
update_world(69);
display();
没有它,glutMainLoop只会调用

update_world(69);
update_world(69);
update_world(69);