如何在曲线上为实体球体设置动画

Posted

技术标签:

【中文标题】如何在曲线上为实体球体设置动画【英文标题】:How to animate a solid sphere over a curve 【发布时间】:2011-05-10 11:23:21 【问题描述】:

我正在用 opengl 编写一个程序来为曲线上的实体球体设置动画 就像 //显示函数

void display()  
  
    glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);  
    glLoadIdentity();  
    //set of condition   
    loop:j=1 to 5  
        loop:i=1 to 3  
            if(j==1)
              
                animate(x,y,z)  
                glutSwapBuffers();
            
            elseif(j==5)
              
                animate(x,y,z)  
                glutSwapBuffers();
              
            else //for all value j between 1 and 5
              
                animate(x,y,z);  
                glutSwapBuffers();
              
  

//animate function  
void animate(float x, float y, float z)  
  
    glLoadIdentity();  
    glTranslatef(0,0,-20);  
    glPushMatrix();  
    glTranslatef (x, y, z);  
    glutSolidSphere (0.3, 10, 10);  

    int i, j;  

    for(i = 0; i < 10000; i++) //for introducing delay  
        for(j = 0; j < 5000; j++);


    glPopMatrix();  
    glutSwapBuffers();  
  

问题:实心球体在曲线上平移,但对于它的每一个下一个 位置我无法删除它以前的位置...例如 如果球体从 P1,P2,P3,P4 AND THEN P5..after 等位置序列开始 来到位置 P5 它在所有其他先前位置仍然可见(P1,P2,P3,P4) 但我希望它在翻译时仅在当前位置显示球体 我该怎么做?

【问题讨论】:

使用 Sleep(miliseconds) 而不是那些嵌套循环。它在 windows.h 头文件中。 【参考方案1】:

您没有清除帧缓冲区,这意味着您将每一帧都绘制在前一帧的顶部。尝试将glClearColor(0.0f, 0.0f, 0.0f, 1.0f ); 与您想要的颜色搭配使用。

【讨论】:

你能告诉我在上面的代码中我应该在哪里使用这一行 @fluty:不幸的是,它并不能解决你真正的问题。到目前为止,您还没有以有用的方式实现 OpenGL 动画。看我的回答。【参考方案2】:

OpenGL 不是场景图。它所做的只是为像素着色。在您向 OpenGL 发送一些几何图形并对其进行处理后,它就消失了,被遗忘了,剩下的就是它在帧缓冲区中的痕迹。请注意,顶点缓冲区对象的内容本身不是几何图形。只有绘图调用(glDrawElementsglDrawArrays)将顶点缓冲区中的值转换为几何图形。

您的程序也不遵循典型的动画循环。您现在的操作方式不允许用户交互或动画期间的任何其他类型的事件处理。你应该把你的代码改成这样:

static timeval delta_T = 0., 0.;

struct AnimationState 
    // ...
    float sphere_position[3];
;

AnimationState animation;

void display()  


    // Start time, frame rendering begins:
    timeval time_begin_frame;
    gettimeofday(&time_begin_frame, 0);

    animate(delta_T.tv_sec + delta_T.tv_usec * 1.e6);

    glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);  

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    set_projection();

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    apply_camera_transform();

    draw_sphere(animation.sphere_position[0], 
                animation.sphere_position[1], 
                animation.sphere_position[2])

    glutSwapBuffers();

    // frame render end time
    timeval time_end_frame;
    gettimeofday(&time_end_frame, 0);
    timersub(&time_end_frame, &time_begin_frame, &delta_time);

  

void draw_sphere(float x, float y, float z)  
  

    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();  
    glTranslatef (x, y, z);  
    glutSolidSphere (0.3, 10, 10);  

    glPopMatrix();

  

void animate(float dT)

    // advance animation by timestep dT


void idle()

    glutPostRedisplay();

编辑完整的工作代码示例

/* sinsphere.c */
#include <GL/glut.h>

#include <stdlib.h>

#include <sys/time.h>
#include <math.h>

#define M_PI    3.1415926535897932384626433832795029L
#define M_PI_2  1.5707963267948966192313216916397514L

# define timersub(a, b, result)                                               \
  do                                                                         \
    (result)->tv_sec = (a)->tv_sec - (b)->tv_sec;                             \
    (result)->tv_usec = (a)->tv_usec - (b)->tv_usec;                          \
    if ((result)->tv_usec < 0)                                               \
      --(result)->tv_sec;                                                     \
      (result)->tv_usec += 1000000;                                           \
                                                                             \
   while (0)

void idle(void);
void animate(float dT);
void display(void);
void init_sphere(unsigned int rings, unsigned int sectors);
void draw_sphere(void);

int main(int argc, char *argv[])
    
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
    glutCreateWindow("SinSphere");
    glutIdleFunc(idle);
    glutDisplayFunc(display);

    init_sphere(10, 30);

    glutMainLoop();

    return 0;


struct AnimationState

    float time;
        float sphere_speed;
    float sphere_path_radius;
    float sphere_path_bobbing;
    float sphere_position[3];
;

static struct AnimationState animation = 
    0.,
    0.1, 3., 1.,
    1., 0., 0.
;

void animate(float dT)

    animation.time += dT;

    animation.sphere_position[0] = animation.sphere_path_radius * cos(2*M_PI * animation.time * animation.sphere_speed);
    animation.sphere_position[1] = animation.sphere_path_bobbing * sin(2*M_PI * animation.time * 5 * animation.sphere_speed);
    animation.sphere_position[2] = animation.sphere_path_radius * sin(2*M_PI * animation.time * animation.sphere_speed);


GLfloat *sphere_vertices_normals;
unsigned int sphere_quads = 0;
GLushort *sphere_indices;

void init_sphere(unsigned int rings, unsigned int sectors)

    float const R = 1./(float)(rings-1);
    float const S = 1./(float)(sectors-1);
    int r, s;

    sphere_vertices_normals = malloc(sizeof(GLfloat)*3 * rings*sectors);

    GLfloat *v = sphere_vertices_normals;
    for(r = 0; r < rings; r++) for(s = 0; s < sectors; s++) 
        float const y = sin( -M_PI_2 + M_PI * r * R );

        float const x = cos(2*M_PI * s * S) * sin( M_PI * r * R );

        float const z = sin(2*M_PI * s * S) * sin( M_PI * r * R );

        v[0] = x;
        v[1] = y;
        v[2] = z;

        v+=3;
    

    sphere_indices = malloc(sizeof(GLushort) *  rings * sectors * 4);
    GLushort *i = sphere_indices;
    for(r = 0; r < rings; r++) for(s = 0; s < sectors; s++) 
        *i++ = r * sectors + s;
        *i++ = r * sectors + (s+1);
        *i++ = (r+1) * sectors + (s+1);
        *i++ = (r+1) * sectors + s; 
        sphere_quads++;
    


void draw_sphere()

    glTranslatef(animation.sphere_position[0], animation.sphere_position[1], animation.sphere_position[2]);

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);

    glVertexPointer(3, GL_FLOAT, 0, sphere_vertices_normals);
    glNormalPointer(GL_FLOAT, 0, sphere_vertices_normals);
    glDrawElements(GL_QUADS, sphere_quads*4, GL_UNSIGNED_SHORT, sphere_indices);


void idle()

    glutPostRedisplay();


static GLfloat const light_pos[4] = -1., 1., 1., 0.;
static GLfloat const light_color[4] = 1., 1., 1., 1.;

void display()

    static struct timeval delta_T = 0., 0.;
    struct timeval time_frame_begin, time_frame_end;

    int win_width, win_height;
    float win_aspect;

    gettimeofday(&time_frame_begin, 0);

    animate(delta_T.tv_sec + delta_T.tv_usec * 1.e-6);

    win_width = glutGet(GLUT_WINDOW_WIDTH);
    win_height = glutGet(GLUT_WINDOW_HEIGHT);
    win_aspect = (float)win_width/(float)win_height;

    glViewport(0, 0, win_width, win_height);
    glClearColor(0.6, 0.6, 1.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(-win_aspect, win_aspect, -1., 1., 1., 10.);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(0,0,-5.5);

    glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, light_color);

    glPushMatrix();

    glEnable(GL_DEPTH_TEST);

    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    draw_sphere();

    glPopMatrix();

    glutSwapBuffers();

    gettimeofday(&time_frame_end, 0);
    timersub(&time_frame_end, &time_frame_begin, &delta_T);


【讨论】:

datenwolf 你能不能给我一个工作的例子......或者一个链接,我可以从那里得到源代码。任何这样的例子,这样我就可以让我自己更加熟悉这个概念试验一下 @fluty:给你:homepages.physik.uni-muenchen.de/~Wolfgang.Draxinger/stuff/…

以上是关于如何在曲线上为实体球体设置动画的主要内容,如果未能解决你的问题,请参考以下文章

如何在画布上为路径设置动画 - android

如何在 Android 中的另一个视图上为文本设置动画?

如何在键盘外观上为 Flutter 布局设置动画

如何在click上为translateX()设置动画

如何在 iPhone、iOS 8 上为弹出框设置动画

如何在点击手势上为 UIImageView 设置动画?