【问题标题】:Animating a Fractal Via OpenGL通过 OpenGL 动画分形
【发布时间】:2015-10-07 04:02:03
【问题描述】:

我正在逐帧制作分形(三角形分形)动画。我知道我需要使用回调方法来执行此操作,但我不确定如何实现它。我希望通过鼠标左键单击使其工作,因此我有以下代码:

void mouse(int button, int state, int x, int y){
  if(button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN){ 
    glClear(GL_COLOR_BUFFER_BIT);
    divide_triangle(v[0], v[1], v[2], n);
  }
  //Closes the window on right button
  if(button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN){
  exit(0);
  }
}

这是我的鼠标点击回调,但这不会在每次绘制三角形时重新为三角形设置动画。每次递归绘制三角形的时候,怎么显示绘制的过程呢?

void divide_triangle(point2 a, point2 b, point2 c, int m)
{
  /* triangle subdivision using vertex coordinates */
  point2 v0, v1, v2;
  int j;
  if(m>0){
    for(j=0; j<2; j++) v0[j]=(a[j]+b[j])/2;
    for(j=0; j<2; j++) v1[j]=(a[j]+c[j])/2;
    for(j=0; j<2; j++) v2[j]=(b[j]+c[j])/2;
    divide_triangle(a, v0, v1, m-1);
    divide_triangle(c, v1, v2, m-1);
    divide_triangle(b, v2, v0, m-1);
  }
  else(triangle(a,b,c));
  glutPostRedisplay();
/* draw triangle at end of recursion */
}

我想在这里绘制新三角形后重新显示,让它看起来像一个动画,所以我想我需要在重新显示之间有一个延迟。我该如何设置?但我也想让它在我可以绘制它而不是每次都动画的地方,即我单击一个特定的鼠标键:说“F1”或一些未保留的键,它只会显示最终的递归三角形。

Here is my full code for your viewing:

#ifdef __APPLE__ //For use with OS X
#include <GLUT/glut.h>
#else            //Linux
#include <GL/glut.h>
#endif

#include <stdlib.h>
#include <GL/glut.h>

typedef GLfloat point2[2];
/* initial triangle – global variables */
point2 v[]={{-2.0, -1.5}, {2.0, -1.5},
{0.0, 1.5}};
int n; /* number of recursive steps */
int windowX, windowY; //Window size parameters.

float red = .25;
float green = .25; 
float blue = .70;
bool color_state = true;

void mouse(int button, int state, int x, int y);
void triangle( point2 a, point2 b, point2 c);
void divide_triangle(point2 a, point2 b, point2 c, int m);
void swap_colors();

void display(void){
  glClear(GL_COLOR_BUFFER_BIT);
  divide_triangle(v[0], v[1], v[2], n);
  glFlush();
}

void init(){
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluOrtho2D(-2.0, 2.0, -2.0, 2.0);
  glMatrixMode(GL_MODELVIEW);
  glClearColor (0.10, 0.10, 0.10 ,1.0);
  glColor3f(red, green, blue);
}

int main(int argc, char **argv){
  if(argc <= 1){
    windowX = 500;
    windowY = 500;
    n = 4;
  }

  else if(argc > 1){
    windowX = atoi(argv[1]);  //atoi converts char to int
    windowY = atoi(argv[2]);
    n = atoi(argv[3]);
  }
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
  glutInitWindowSize(windowX, windowY);
  glutCreateWindow("N-Force");
  glutDisplayFunc(display);
  glutTimerFunc(30, recurse, -1)
  glutMouseFunc(mouse);
  init();
  glutMainLoop();
}

void mouse(int button, int state, int x, int y){
  if(button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN){ //Swap colors
    glClear(GL_COLOR_BUFFER_BIT);
    divide_triangle(v[0], v[1], v[2], n);
  }
  //Closes the window on right button
  if(button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN){
  exit(0);
  }
}

void divide_triangle(point2 a, point2 b, point2 c, int m)
{
  /* triangle subdivision using vertex coordinates */
  point2 v0, v1, v2;
  int j;
  if(m>0){
    for(j=0; j<2; j++) v0[j]=(a[j]+b[j])/2;
    for(j=0; j<2; j++) v1[j]=(a[j]+c[j])/2;
    for(j=0; j<2; j++) v2[j]=(b[j]+c[j])/2;
    divide_triangle(a, v0, v1, m-1);
    divide_triangle(c, v1, v2, m-1);
    divide_triangle(b, v2, v0, m-1);
  }
  else(triangle(a,b,c));
  glutPostRedisplay();
/* draw triangle at end of recursion */
}

void triangle( point2 a, point2 b, point2 c){
  glBegin(GL_TRIANGLES);
  glVertex2fv(a);
  glVertex2fv(b);
  glVertex2fv(c);
  glEnd();
}

void swap_colors(){  //maybe add parameters x and y to change colors based on coordinates
  if(color_state == true){
    red = blue = green = .1;
    color_state = false;
  }
  else{
    red = 0.25;
    green = .25;
    blue = 0.70;
    color_state = true;
  }
}


/* TO DO:

   1. add cmd line args, (width, depth, and recursive depth) (CHECK)
   2. add color swap
   3. add exit callback (check> right mouse)
   4. Idle callback for animation
 */

【问题讨论】:

    标签: opengl animation recursion callback


    【解决方案1】:

    使用带有布尔标志的glutTimerFunc() callback 来增加递归深度值并重新显示:

    bool animating = false;
    unsigned int n = 4;
    void timer( int value )
    {
        if( !animating )
            return;
    
        n++;
        if( n > 6 )
            n = 0;
    
        glutTimerFunc( 200, timer, 0 );
        glutPostRedisplay();
    }
    
    void mouse(int button, int state, int x, int y)
    {
        if(button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
        {
            animating = !animating;
            glutTimerFunc( 0, timer, 0 );
        }
    }
    

    大家一起:

    #include <GL/glut.h>
    
    bool animating = false;
    unsigned int n = 4;
    void timer( int value )
    {
        if( !animating )
            return;
    
        n++;
        if( n > 6 )
            n = 0;
    
        glutTimerFunc( 200, timer, 0 );
        glutPostRedisplay();
    }
    
    void mouse(int button, int state, int x, int y)
    {
        if(button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
        {
            animating = !animating;
            glutTimerFunc( 0, timer, 0 );
        }
    }
    
    typedef GLfloat point2[2];
    void divide_triangle(point2 a, point2 b, point2 c, int m)
    {
        /* triangle subdivision using vertex coordinates */
        if(m>0)
        {
            point2 v0, v1, v2;
            for( int j=0; j<2; j++) v0[j]=(a[j]+b[j])/2;
            for( int j=0; j<2; j++) v1[j]=(a[j]+c[j])/2;
            for( int j=0; j<2; j++) v2[j]=(b[j]+c[j])/2;
            divide_triangle(a, v0, v1, m-1);
            divide_triangle(c, v1, v2, m-1);
            divide_triangle(b, v2, v0, m-1);
        }
        else
        {
            glVertex2fv(a);
            glVertex2fv(b);
            glVertex2fv(c);
        }
    }
    
    void display(void)
    {
        glClearColor (0.10, 0.10, 0.10 ,1.0);
        glClear(GL_COLOR_BUFFER_BIT);
    
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluOrtho2D(-2.0, 2.0, -2.0, 2.0);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
    
        float red = .25;
        float green = .25; 
        float blue = .70;
        glColor3f(red, green, blue);
    
        /* initial triangle – global variables */
        point2 v[]={{-2.0, -1.5}, {2.0, -1.5}, {0.0, 1.5}};
        glBegin(GL_TRIANGLES);
        divide_triangle(v[0], v[1], v[2], n);
        glEnd();
    
        glFlush();
    }
    
    int main(int argc, char **argv)
    {
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
        glutInitWindowSize(500, 500);
        glutCreateWindow("N-Force");
        glutDisplayFunc(display);
        glutMouseFunc(mouse);
        glutMainLoop();
    }
    

    【讨论】:

      【解决方案2】:

      我猜你想要一个 idle() 回调函数,只有在你的动画标志打开时才执行 PostRedisplay。 (idle 被 glut 反复调用)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-06
        • 2011-11-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多