Как постоянно обновлять окно glut?

У меня есть настоящий робот, который заказывает мой виртуальный робот в open gl. Я хочу показать каждое движение моего главного робота (реального робота) в slave (virtual one in open gl) онлайн, поэтому мне нужно постоянно обновлять окно перенасыщения, на самом деле, пока реальный робот движется, мой виртуальный тоже движется, и все эти движения должны быть онлайн.

Я получаю данные от мастера всегда с функцией get data, но я не знаю, как я должен обновить окно.

вот мой код:

********************************************/

  void OnIdle(void){  
    initSocket();

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

  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 = %.3fn", 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 %fn",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;

  }

3 ответов


вы можете вызвать glutPostRedisplay после обновления, которое планирует перерисовывать окно (используя функцию отображения GLUT, конечно), как только оно вернется в очередь сообщений, я думаю.

но это не будет работать, если вы постоянно опрашиваете данные робота в бесконечном цикле, поскольку это постоянно блокирует программу. Что вам нужно сделать, так это использовать таймер для планирования обновления робота в короткие промежутки времени, чтобы между этими обновлениями программа могла вернуться к основному циклу событий и перерисуйте окно. Или вы можете вызвать некоторую функцию, которая сообщает фреймворку посетить цикл событий. Ваш пример кода на самом деле не объясняет, как вы это делаете в данный момент (или я просто не знаком с функциями, которые вы вызываете).


GLUT предлагает вам простой обратный вызов (void (*)(void) подпись), установлен через glutIdleFunc. Получить входные данные робота в обработчике idle. Или используйте отдельный поток опроса данных, заполняя структуры данных; используйте семафор для разблокировки простоя после поступления новых данных, используйте блокировку с таймаутом, чтобы ваша программа оставалась интерактивной. Псевдокод:

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();
}

Я бы сделал следующее. Лечить glutMainLoop() как ваш цикл и каждый раз, когда вы обрабатываете один getData() вы его нарисуете, это будет быстрее, чем вы думаете.

что должно произойти, для вас, чтобы получить 'непрерывные обновления:

  1. обработка данных (getData() значит, твои расчеты)
  2. Redraw (Display() glut называет это каждый раз, когда он петляет)
  3. другие функции, определенные с помощью glut_____Func()
  4. назад к 1

перенасыщение продолжает работать, пока программа не выйдет.

//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;
}