Created
May 24, 2013 01:18
-
-
Save tai2/5640702 to your computer and use it in GitHub Desktop.
"With four parameters I can fit an elephant, and with five I can make him wiggle his trunk."
c.f. http://java-srv1.mpi-cbg.de/publications/getDocument.html?id=ff8080812daff75c012dc1b7bc10000c, http://www.physics.utoronto.ca/~phy326/python/vonNeumann_elephant.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <math.h> | |
| #include <time.h> | |
| #include <GLUT/glut.h> | |
| #define KEY_ESC 27 | |
| #define WINDOW_POS_X 100 | |
| #define WINDOW_POS_Y 100 | |
| #define DEF_SCREEN_WIDTH 200 | |
| #define DEF_SCREEN_HEIGHT 200 | |
| struct complex { | |
| double r; | |
| double i; | |
| }; | |
| static int curr_width = 0; | |
| static int curr_height = 0; | |
| static GLubyte *screen_buf = NULL; | |
| static int fullscreen = 0; | |
| static clock_t c_orig = 0; | |
| // The five parameters | |
| static struct complex p[5] = {{50, -30}, {18, 8}, {12, -10}, {-14, -60}, {40, 20}}; | |
| static void | |
| keyboard(unsigned char c, int x, int y) | |
| { | |
| switch (c) { | |
| case KEY_ESC: | |
| exit(0); | |
| break; | |
| case 'f': | |
| if (fullscreen) { | |
| glutReshapeWindow(DEF_SCREEN_WIDTH, DEF_SCREEN_HEIGHT); | |
| glutPositionWindow(WINDOW_POS_X, WINDOW_POS_Y); | |
| fullscreen = 0; | |
| } else { | |
| glutFullScreen(); | |
| fullscreen = 1; | |
| } | |
| break; | |
| } | |
| } | |
| void | |
| idle() | |
| { | |
| glutPostRedisplay(); | |
| } | |
| static void | |
| reshape(int w, int h) | |
| { | |
| curr_width = w; | |
| curr_height = h; | |
| if (screen_buf) { | |
| free(screen_buf); | |
| } | |
| screen_buf = (GLubyte *)malloc(curr_width * curr_height * 4); | |
| if (!screen_buf) { | |
| abort(); | |
| } | |
| } | |
| static void | |
| draw_pixel(int x, int y, GLubyte r, GLubyte g, GLubyte b) | |
| { | |
| int base = 4 * ((curr_height - 1 - y) * curr_width + x); | |
| if (0 <= x && x < curr_width && 0 <= y && y < curr_height) { | |
| screen_buf[base + 0] = r; | |
| screen_buf[base + 1] = g; | |
| screen_buf[base + 2] = b; | |
| screen_buf[base + 3] = 255; | |
| } | |
| } | |
| static double | |
| fourier(double t, double a[], double b[]) | |
| { | |
| int k; | |
| double r = 0; | |
| for (k = 0; k < 6; k++) { | |
| r += a[k] * cos(k * t) + b[k] * sin(k * t); | |
| } | |
| return r; | |
| } | |
| static void | |
| display() | |
| { | |
| double ax[6] = {0, 0, 0, p[2].r, 0, p[3].r}; | |
| double bx[6] = {0, p[0].r, p[1].r, 0, 0, 0 }; | |
| double ay[6] = {0, p[3].i, 0, 0, 0, 0 }; | |
| double by[6] = {0, p[0].i, p[1].i, p[2].i, 0, 0 }; | |
| double t, tstart, tend; | |
| double x0, y0; | |
| double past = (double)(clock() - c_orig) / CLOCKS_PER_SEC; | |
| memset(screen_buf, 0, curr_width * curr_height * 4); | |
| tstart = 0.4 + 1.3 * M_PI; | |
| tend = 2 * M_PI + 0.9 * M_PI; | |
| for (t = tstart; t < tend; t += (tend - tstart) / 1000) { | |
| double x = fourier(t, ax, bx); | |
| double y = fourier(t, ay, by); | |
| draw_pixel(y + curr_width / 2, x + curr_height / 2, 255, 255, 255); | |
| } | |
| tstart = 2 * M_PI + 0.9 * M_PI; | |
| tend = 0.4 + 3.3 * M_PI; | |
| x0 = fourier(tstart, ax, bx); | |
| y0 = fourier(tstart, ay, by); | |
| for (t = tstart; t < tend; t += (tend - tstart) / 1000) { | |
| double x = fourier(t, ax, bx); | |
| double y = fourier(t, ay, by); | |
| x += sin((y - y0) * M_PI / 1000) * sin(past) * p[4].r; | |
| draw_pixel(y + curr_width / 2, x + curr_height / 2, 255, 255, 255); | |
| } | |
| draw_pixel(p[4].i + curr_width / 2, -p[4].i + curr_height / 2, 255, 255, 255); | |
| glWindowPos2i(0, 0); | |
| glDrawPixels(curr_width, curr_height, GL_RGBA, GL_UNSIGNED_BYTE, screen_buf); | |
| glutSwapBuffers(); | |
| } | |
| int | |
| main(int argc, char** argv) | |
| { | |
| srand(0); | |
| glutInit(&argc, argv); | |
| glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH ); | |
| glutInitWindowSize(DEF_SCREEN_WIDTH, DEF_SCREEN_HEIGHT); | |
| glutInitWindowPosition(WINDOW_POS_X, WINDOW_POS_Y); | |
| glutCreateWindow(argv[0]); | |
| glutKeyboardFunc(keyboard); | |
| glutIdleFunc(idle); | |
| glutReshapeFunc(reshape); | |
| glutDisplayFunc(display); | |
| c_orig = clock(); | |
| glShadeModel(GL_FLAT); | |
| glutMainLoop(); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment