Реализация задержки / обновления в анимации OpenGL - PullRequest
2 голосов
/ 29 марта 2012

Я изучаю некоторые очень простые 3D-рендеринг с использованием opengl, но мой учитель использует компьютер, на котором вы можете использовать функцию sleep () для рендеринга каждого из кадров анимации.

Однако, когда я пытаюсь сделать то же самое на моем Mac, я получаю только последний кадр.если я использую функцию sleep (), мой mac буквально переходит в спящий режим.

Я читал кое-что о NSTimer, но я не знаю, как это реализовать.

Вот мой код, он отлично работает на ПК, я только хочу заменить закомментированный sleep () на эквивалент Mac, который позволяет мне видеть каждый кадр во время этой задержки

#include<OpenGL/gl.h>
#include<OpenGL/glu.h>
#include<GLUT/glut.h>
#include <stdlib.h>

void init (void)
{
glClearColor(0.5,0.5,0.5,0);
glMatrixMode(GL_MODELVIEW);
gluLookAt(0,4,4,0,0,0,0,1,0);
glMatrixMode(GL_PROJECTION);
gluPerspective(90,1,1,12);
}
void Cubes(void)
{
int i=0;
glMatrixMode(GL_MODELVIEW);
glutInitDisplayMode(GL_DEPTH);
for (i=0; i<360;i++)
{
    glRotated(1,1,0,0);
    glClear(GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1,0,0);
    glutSolidSphere(1,20,20);
    glColor3f(0.8,0.8,0);
    glutWireSphere(1,20,20);
    glColor3f(0,0,1);
    glutSolidTorus(1,2,40,40);
    glFlush();
    glDisable(GL_DEPTH_TEST);
    //Sleep(20);
}
}
int main (int argc, char** argv)
{
glutInit(&argc, argv);
glutInitWindowSize(600,600);
glutCreateWindow("Depth Buffer");
init();
glutDisplayFunc(Cubes);
glutMainLoop();
}

Ответы [ 2 ]

3 голосов
/ 29 марта 2012

Пожалуйста, скажите своему учителю, что он делает это неправильно! Чтобы сделать анимацию с GLUT, не помещайте цикл анимации в функцию отображения, но зарегистрируйте функцию ожидания, которая переиздает дисплей. Также этот код пропускает замену буфера (которая обязательна в MacOS X, если она не работает в полноэкранном режиме, чтобы сообщить композитору, что вы завершили рендеринг).

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


Обновление: исправлен код

#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <GLUT/glut.h>
#include <stdlib.h>
#include <sys/time.h>
#include <math.h>
#include <stdio.h>

double getftime(
    void )
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec + tv.tv_usec*1e-6;
}

static double lasttime;

void display(
    void )
{
    int width, height;
    double finishtime, delta_t;

    static float angle = 0;

    width = glutGet(GLUT_WINDOW_WIDTH);
    height = glutGet(GLUT_WINDOW_HEIGHT);

    glClearColor( 0.5, 0.5, 0.5, 1.0 );
    /* combine the clearing flags for more efficient operation */
    glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );

    glViewport(0, 0, width, height);

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    gluPerspective( 90, (float)width/(float)height, 1, 12 );

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
    gluLookAt( 0, 4, 4, 0, 0, 0, 0, 1, 0 );

    glEnable( GL_DEPTH_TEST );

    glRotated( angle, 1, 0, 0 );
    glColor3f( 1, 0, 0 );
    glutSolidSphere( 1, 20, 20 );
    glColor3f( 0.8, 0.8, 0 );
    glutWireSphere( 1, 20, 20 );
    glColor3f( 0, 0, 1 );
    glutSolidTorus( 1, 2, 40, 40 );
    glDisable( GL_DEPTH_TEST );

    glutSwapBuffers();

    finishtime = getftime();
    delta_t = finishtime - lasttime;

    angle = fmodf(angle + 10*delta_t, 360);

    lasttime = finishtime;
}
int main(
    int argc,
    char **argv )
{
    glutInit( &argc, argv );
    glutInitWindowSize( 600, 600 );
    /* glutInitDisplayMode must be called before glutCreateWindow, flags are prefixed with GLUT_ not GL */
    glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
    glutCreateWindow( "Depth Buffer" );
    glutDisplayFunc( display );
    /* register glutPostRedisplay for continuous animation */
    glutIdleFunc(glutPostRedisplay);

    lasttime = getftime();
    glutMainLoop(  );
}
0 голосов
/ 29 марта 2012

Я согласен с приведенными выше постами, что ваш учитель не прав.Однако, чтобы ответить на ваш вопрос, используйте usleep (useconds_t useconds), чтобы спать на Mac OS X.вот справочная страница:

https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/usleep.3.html

обратите внимание, что время ожидания в микросекундах, а не в миллисекундах, как в WindowsТакже обратите внимание, что, как и в Windows, он будет спать как минимум указанное время.Он может спать намного дольше, что является одной из многих причин, по которой вам не следует его использовать, но следует измерить время между кадрами и соответствующим образом обновить.

...