如何连续更新过剩窗口?

Posted

技术标签:

【中文标题】如何连续更新过剩窗口?【英文标题】:How to update glut window continuously? 【发布时间】:2011-07-23 12:57:52 【问题描述】:

我有一个真正的机器人,它在 open gl 中订购我的虚拟机器人。我想在线显示我的主机器人(真实机器人)在奴隶(open gl中的虚拟机器人)中的每一个动作,所以我需要不断更新我的过剩窗口,实际上只要真实机器人移动我的虚拟机器人也会移动,所有这些运动应该是在线的。

我总是使用获取数据功能从主控器获取数据,但我不知道应该如何更新窗口。

这是我的代码:

************* *************** ****************强>/

  void OnIdle(void)  
    initSocket();

  printf("\n  Defining Step Time Parameters and Initial Conditions for solving Dynamic equations\n");

  xi=0;
  xf=0.1;
  printf("\n    end value x         : %f ",xf); 
  i=0;  yi[i]=0; 
  i++;yi[i]=-1.570796;
  i++;yi[i]=-1.570796;
  i++;yi[i]=0;
  i++;yi[i]=0;
  i++;yi[i]=0;
  ndata=2; fi=1;

  double counter=0.1;

  Eqdifp(v1,v2,v3,v4,v5,v6,xi,xf,yi,ndata,p,fi);


  for(int i=0;i<50;i++)
    //while(1)
  

      getData();

      printf("\n");
      for(int i=0;i<6; i++)
      

          printf("%d = %.3f\n", i,drecvbuf[i]);
      
      printf("\n");

   yi[0]=v1[ndata];
   yi[1]=v2[ndata];
   yi[2]=v3[ndata];
   yi[3]=v4[ndata];
   yi[4]=v5[ndata];
   yi[5]=v6[ndata];
    printf("my nadata %f\n",v1[ndata]);
    counter=counter+0.1;

    Eqdifp(v1,v2,v3,v4,v5,v6,xi,xf,yi,ndata,p,fi);
    glutPostRedisplay();
 
  
/////////////////////////////////////////////////////
  int main(int argc, char **argv)

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    glutInitWindowSize(900,500);
    int u=glutCreateWindow("3DOF robot");
    myinit();
    createMenu();
    glutIdleFunc (OnIdle);
    glutDisplayFunc(Display);
    glutReshapeFunc(reshape);
    glutKeyboardFunc(KeyDown);

    glutMainLoop(); 

    System::Timers::Timer^ aTimer = gcnew System::Timers::Timer( 100 );

      // Hook up the Elapsed event for the timer.
    aTimer->Elapsed += gcnew System::Timers::ElapsedEventHandler( OnTimedEvent );

      // Set the Interval to 2 seconds (2000 milliseconds).
    aTimer->Enabled = true;
    return 0;

  

【问题讨论】:

不想这样标记它,因为我不熟悉,但System::Timers::Timer^ aTimer = gcnew System::Timers::Timer( 100 ); 对我来说似乎是 C++/CLI? @Bart 一看到^,那肯定是C++/CLI。 实际上,gcnew 是 C++/CLI 更强大的指标。 ^ 是标准 C++ 中的有效运算符。 @Ben 是的,你是对的,没有考虑过异或。 【参考方案1】:

您可以在更新后调用 glutPostRedisplay,它会安排窗口在返回消息队列后立即重绘(当然是使用 GLUT 的显示函数),我想。

但如果您在无限循环中不断轮询机器人数据,这将不起作用,因为这会不断阻塞程序。您应该做的是使用计时器来安排机器人在较短的时间间隔内更新,以便在这些更新之间程序可以返回到主事件循环并重绘窗口。或者你可以调用一些函数,告诉框架访问事件循环。您的代码示例目前并没有真正解释您是如何做到的(或者我只是不熟悉您调用的函数)。

【讨论】:

亲爱的克里斯汀,感谢您的回答 其实我是open gl甚至c++的新手,不是很专业。 所以,我更喜欢使用 opengl 的函数,就像你告诉的那个(glutPostRedisplay),但我不知道如何。我需要一些不那么复杂的东西! 我编辑了向上的代码,这是我尝试过的建议方式,但没有奏效,我很困惑:(( @bahare 顺便说一句,glutPostRedisplay 不属于 OpenGL,而是属于 GLUT。 OpenGL 是一个用于对图形硬件(显示事物)进行编程的接口,而 GLUT 是一个 GUI 抽象库,可以更轻松地创建简单的 OpenGL 程序。但是 OpenGL 与 GUI 或事件处理等任务没有任何关系。【参考方案2】:

GLUT 为您提供一个空闲回调(void (*)(void) 签名),通过 glutIdleFunc 设置。在空闲处理程序中检索机器人输入数据。或者使用单独的线程轮询数据,填充数据结构;在新数据到达后使用信号量解锁空闲,使用超时锁定,以便您的程序保持交互。伪代码:

Semaphore robot_data_semaphore;

void wait_for_data(void)

    SemaphoreLockStatus lock_status = 
        semaphore_raise_timeout(robot_data_semaphore, RobotDataTimeout);
    if( lock_status == SEMAPHORE_RAISED ) 
        update_scene_with_robot_data();
        semaphore_lower(robot_data_semaphore);
        glutPostRedisplay();
    


void main(int argc, char *argv[])

/* ... */
    semaphore_init(robot_data_semaphore);
    Thread thread_robot_data_poller = thread_create(robot_data_poller);
    glutIdleFunc(wait_for_data);

/* ... */
    thread_start(thread_robot_data_poller);
    glutMainLoop();

【讨论】:

我试过你说的,但没用,我改了up代码,用你的方式,你能看看,说什么吗?tnx很多:) @bahare:空闲处理程序必须在大约 50 毫秒内返回以保持程序响应。此外,在空闲处理程序返回之前,不会发生显示更新。 glutPostRedisplay 只是设置了一些标志。在空闲处理程序中,您应该将放置在事件处理循环的默认分支中的内容 - 没有循环。 你能按照你说的方式更正向上的代码吗?我尝试了很多方法,但都不起作用。 @bahare:为此我需要完整的源代码,因为您发布的部分不包含足够的信息。【参考方案3】:

我会做以下事情。把glutMainLoop()当作你的循环,每次你处理一个getData()你画它,它会比你想象的要快。

要获得“持续”更新,您需要做的是:

    处理数据(getData() 然后是您的计算) 重绘(Display() glut 每次循环时都会调用它) 使用glut_____Func()定义的其他函数 返回 1

Glut 一直运行到程序退出为止。

//called every time glutMainLoop
//do data processing
void OnIdle(void)
  
    getData();

    printf("\n");
    for(int i=0;i<6; i++)
    
        printf("%d = %.3f\n", i,drecvbuf[i]);
    
    printf("\n");

    yi[0]=v1[ndata];
    yi[1]=v2[ndata];
    yi[2]=v3[ndata];
    yi[3]=v4[ndata];
    yi[4]=v5[ndata];
    yi[5]=v6[ndata];
    printf("my nadata %f\n",v1[ndata]);

    Eqdifp(v1,v2,v3,v4,v5,v6,xi,xf,yi,ndata,p,fi);

//also called every loop of glutMainLoop
void Display()

    ...
    //Your previous Display() function just add this:
    glutPostRedisplay(); //everytime you are done 
                        // drawing you put it on the screen


int main(int argc, char **argv)

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    glutInitWindowSize(900,500);
    int u=glutCreateWindow("3DOF robot");
    myinit();
    createMenu();
    glutIdleFunc (OnIdle);
    glutDisplayFunc(Display);
    glutReshapeFunc(reshape);
    glutKeyboardFunc(KeyDown);

    ///////////////
    // SETUP YOUR INITIAL DATA
    System::Timers::Timer^ aTimer = gcnew System::Timers::Timer( 100 );

    // Hook up the Elapsed event for the timer.
    aTimer->Elapsed += gcnew System::Timers::ElapsedEventHandler( OnTimedEvent );

    // Set the Interval to 2 seconds (2000 milliseconds).
    aTimer->Enabled = true;

    initSocket();

    printf("\n  Defining Step Time Parameters and Initial Conditions for solving Dynamic equations\n");

    xi=0;
    xf=0.1;
    printf("\n    end value x         : %f ",xf); 
    i=0;  yi[i]=0; 
    i++;yi[i]=-1.570796;
    i++;yi[i]=-1.570796;
    i++;yi[i]=0;
    i++;yi[i]=0;
    i++;yi[i]=0;
    ndata=2; fi=1;

    Eqdifp(v1,v2,v3,v4,v5,v6,xi,xf,yi,ndata,p,fi);
    //////////////

    //Start the Main Loop
    glutMainLoop(); //This statement blocks, meaning that until you exit the 
                    // glut main loop no statments past this point will be executed.


    return 0;

【讨论】:

以上是关于如何连续更新过剩窗口?的主要内容,如果未能解决你的问题,请参考以下文章

css - 如何在调整窗口大小时连续制作弹性项目3并保持1:1的比例[重复]

怎么样才能在一个dos窗口连续telnet?

更新后如何连续刷新datagridview

如何将连续的行与它们之间越来越多的重叠结合起来(就像滚动窗口一样)?

如何连续刷新屏幕并实时更新[关闭]

如何在没有计时器的情况下连续获取 AudioQueue 的更新