/* inspired by https://mastodon.art/@smerp/105735717668944296 * (link was working 2021-04-09) */ /* gcc -Wall 10order.c -I /usr/include/SDL2 -lSDL2 -lm -pthread -O3 */ #include #include #include #include #include #include #include #include #define WIDTH 512 #define HEIGHT 512 typedef struct { SDL_Window *d; SDL_Surface *w; SDL_Surface *rgb; unsigned char *screen; float rand[52][52][52]; int height[52][520]; int a[52][52]; } display; volatile int frame; void *fps(void *_) { while (1) { printf("%d\n", frame); frame = 0; sleep(1); } return 0; } float interp(float a, float b, float x) { return (1 - x) * a + x * b; } float interp2(float a, float b, float x) { float t = x * 6 - 3; x = 1. / (1 + exp(-t)); return (1 - x) * a + x * b; } void draw_frame(display *d, double f) { #define PIXEL(x, y, r, g, b) do { \ if ((x) >= 0 && (x) < 512 && (y) >= 0 && (y) < 512) { \ d->screen[((y) * 512 + (x)) * 4] = (b); \ d->screen[((y) * 512 + (x)) * 4 + 1] = (g); \ d->screen[((y) * 512 + (x)) * 4 + 2] = (r); \ } \ } while (0) int i, j, k; memset(d->screen, 0, WIDTH*HEIGHT*4); int frame = (int)f % 52; float aleft, aright; if (frame < 13) { aleft = -1; aright = -1 + (frame % 13) * 2 / 13.; } else if (frame < 26) { aleft = -1 + (frame % 13) * 2 / 13.; aright = 1; } else if (frame < 26+13) { aleft = 1; aright = 1 - (frame % 13) * 2 / 13.; } else { aleft = 1 - (frame % 13) * 2 / 13.; aright = -1; } float plot[52][52]; float red[52][52]; float a; for (i = 0; i < 52; i++) { for (k = 0; k < 52; k++) { plot[i][k] = d->rand[i][k][frame]; float aa = aleft + k * (aright - aleft) / 51.2; a = d->a[i][k]; a = a * aa; red[i][k] = 0; if (a) { red[i][k] = (a + 1) / 2; } if (a && a >= plot[i][k]) { plot[i][k] += 2 * a; //1 * (a > 1 ? 1 : a); } } } for (i = 0; i < 52; i++) { int line = i * 10; for (k = 0; k < 52; k++) { for (j = 0; j < 10; j++) { float y = interp2(plot[i][(k+51) % 52], plot[i][k], j/10.); int ii; y *= 10; int yy = y; d->height[i][k*10+j] = line-yy; for (ii = i-1; ii >= 0; ii--) { if (d->height[ii][k*10+j] <= d->height[i][k*10+j]) break; PIXEL(j+k*10, d->height[ii][k*10+j], 0, 0, 0); PIXEL(j+k*10, d->height[ii][k*10+j]+1, 0, 0, 0); PIXEL(j+k*10, d->height[ii][k*10+j]+2, 0, 0, 0); d->height[ii][k*10+j] = d->height[i][k*10+j]; } float r = interp(red[i][(k+51) % 52], red[i][k], j/10.); PIXEL(j+k*10, line-yy, 128 + r * 127, 128 - r * 127, 128 - r * 127); PIXEL(j+k*10, line-yy+1, 128 + r * 127, 128 - r * 127, 128 - r * 127); PIXEL(j+k*10, line-yy+2, 128 + r * 127, 128 - r * 127, 128 - r * 127); } } } } char *_a = " " " " " " " " " " " " " " " ........... " " .................. " " ...................... " " ..... ...... ... " " ... ... .. ... " " ... .. .. ... " " ... .. .. ... " " .... . ... ... " " .... .. ... .. " " .. .. .. .. ... " " ... .. .. .. ..... " " .. ... ... ...... " " ... ... ... .... " " .. .. ... ........ " " .. .. .. ...... .. " " .. . .. ....... .. " " .. .... ................. .. " " .............................. .. " " ....................... .. .. " " .. ... ... .. " " .. ... .. .. " " .. ... .. .. " " .. .. .. .. " " ... ... .. .. " " .. .. .. . " " ... .. .. .. " " ... ... ... .. " " .. ... .. .. " " .. ... ... .. " " ..... .. ... " " .... .. ... " " ... ...... " " ....... ..... " " .. .................... " " .. ........... .. " " . .. " " . .. " " . . " " . " " " " " " " " " " " " " ; void usage(void) { printf("run with no option for display on your screen\n"); printf("options:\n"); printf(" -screenshot\n"); printf(" dump frame 20 to stdout\n"); printf(" so run: ./a.out -screenshot > rec.raw\n"); printf(" and use ffmpeg to make an image, for example:\n"); printf(" ffmpeg -f rawvideo -s 512x512 -pix_fmt bgr24 -i rec.raw 10order.png\n"); printf(" -dump-video\n"); printf(" dump all frames (from 0 to 51) to stdout\n"); printf(" so run: ./a.out -dump-video > rec.raw\n"); printf(" and use ffmpeg to make a movie, for example:\n"); printf(" ffmpeg -f rawvideo -s 512x512 -r 30 -pix_fmt bgra -i rec.raw 10order.gif\n"); exit(0); } int main(int n, char **v) { int screenshot = 0; int dump_video = 0; display d; int i, j, k, l; for (i = 1; i < n; i++) { if (!strcmp(v[i], "-screenshot")) { screenshot = 1; continue; } if (!strcmp(v[i], "-dump-video")) { dump_video = 1; continue; } usage(); } for (i = 0; i < 52; i++) for (j = 0; j < 52; j++) { float gain[4]; float phase[4]; for (k = 0; k < 4; k++) { gain[k] = ((float)rand() / (float)RAND_MAX) * 2. - 1.; phase[k] = ((float)rand() / (float)RAND_MAX) * 2. * M_PI; } float max = 0; for (k = 0; k < 52; k++) { float v = 0; for (l = 0; l < 4; l++) v += gain[l] * cos(phase[l] + 2. * M_PI / 52 * k * (l+1)); d.rand[i][j][k] = v; if (fabs(v) > max) max = fabs(v); } for (k = 0; k < 52; k++) d.rand[i][j][k] /= max; } for (i = 0; i < 52; i++) for (j = 0; j < 52; j++) { int z = _a[i*52+j] == ' ' ? 0 : 1; d.a[i][j] = z; } if (screenshot) { /* ./a.out > rec.raw * ffmpeg -f rawvideo -s 512x512 -pix_fmt bgr24 -i rec.raw 10order.png */ d.screen = malloc(512*512*4); if (d.screen == NULL) abort(); draw_frame(&d, 20); for (i = 0; i < 512*512; i++) fwrite(d.screen + i * 4, 3, 1, stdout); exit(0); } if (dump_video) { /* ./a.out > rec.raw * ffmpeg -f rawvideo -s 512x512 -r 30 -pix_fmt bgra -i rec.raw 10order.gif */ d.screen = malloc(512*512*4); if (d.screen == NULL) abort(); for (i = 0; i < 52; i++) { draw_frame(&d, i); fwrite(d.screen, 512*512*4, 1, stdout); } exit(0); } if (SDL_Init( SDL_INIT_VIDEO) < 0) exit(1); d.d = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN ); if (d.d == NULL) { printf("error: %s\n", SDL_GetError()); exit(1); } d.w = SDL_GetWindowSurface(d.d); d.screen = d.w->pixels; pthread_t tht; pthread_create(&tht, NULL, fps, NULL); struct timespec t; clock_gettime(CLOCK_MONOTONIC_RAW, &t); uint64_t start_time = (uint64_t)t.tv_sec * 1000000000 + t.tv_nsec; while(1) { clock_gettime(CLOCK_MONOTONIC_RAW, &t); uint64_t cur_time = (uint64_t)t.tv_sec * 1000000000 + t.tv_nsec; double fps = 30; double f = (cur_time - start_time) / 1000000000. * fps; draw_frame(&d, f); //g); SDL_UpdateWindowSurface(d.d); frame++; } }