2015-10-03 3 views
1

Я работаю над анимацией фрактального (фрактального треугольника) по кадру. Я знаю, что для этого нужно использовать метод обратного вызова, но я не уверен, как его реализовать. Я хочу, чтобы получить его работу с помощью левой кнопки мыши, так у меня есть этот код:Анимация фрактала через OpenGL

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

Я хочу чтобы снова, как только я рисовать новый треугольник здесь, и сделать это, как представляется, анимация, так что я думаю, я должен был бы задержку между вновь появится. Как я могу это настроить? Но я также хочу сделать это, когда я смогу нарисовать это без анимации каждый раз, I.e. Я нажимаю конкретную клавишу мыши: скажем «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 
*/ 

ответ

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

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