wonky sweep
[gbajam21] / tools / tungen.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdint.h>
4 #include <math.h>
5
6 struct vec2 {
7         float x, y;
8 };
9
10 int main(int argc, char **argv)
11 {
12         int i, j, frm, imgrad, out_nlines, xsz = 240, ysz = 160, texsz = 128;
13         int half_y = 0;
14         int center = 0;
15         struct vec2 *tunbuf, *tun;
16         float prev_r;
17         struct vec2 *buf, *ptr;
18         char *endp;
19         int num_frames = 1;
20
21         for(i=1; i<argc; i++) {
22                 if(argv[i][0] == '-') {
23                         if(argv[i][2] != 0) goto invalopt;
24                         switch(argv[i][1]) {
25                         case 's':
26                                 if(sscanf(argv[++i], "%dx%d", &xsz, &ysz) != 2 || xsz <= 1 || ysz <= 1) {
27                                         fprintf(stderr, "-s must be followed by WxH\n");
28                                         return 1;
29                                 }
30                                 break;
31
32                         case 't':
33                                 if(!(texsz = atoi(argv[++i])) || texsz > 256) {
34                                         fprintf(stderr, "-t must be followed by the texture size (1-256)\n");
35                                         return 1;
36                                 }
37                                 break;
38
39                         case 'y':
40                                 half_y = 1;
41                                 break;
42
43                         case 'c':
44                                 if(!argv[++i]) {
45                                         fprintf(stderr, "-c must be followed by a center pixel\n");
46                                         return 1;
47                                 }
48                                 center = strtol(argv[i], &endp, 10);
49                                 if(endp == argv[i]) {
50                                         fprintf(stderr, "-c invalid center position: %s\n", argv[i]);
51                                         return 1;
52                                 }
53                                 break;
54
55                         case 'n':
56                                 if(!argv[++i]) {
57                                         fprintf(stderr, "-n must be followed by the number of frames\n");
58                                         return 1;
59                                 }
60                                 if(!(num_frames = atoi(argv[i]))) {
61                                         fprintf(stderr, "-n invalid number of frames: %s\n", argv[i]);
62                                         return 1;
63                                 }
64                                 break;
65
66                         default:
67                                 goto invalopt;
68                         }
69                 } else {
70 invalopt:       fprintf(stderr, "invalid argument: %s\n", argv[i]);
71                         return 1;
72                 }
73         }
74
75         out_nlines = half_y ? ysz / 2 : ysz;
76
77         if(!(buf = malloc(xsz * ysz * sizeof *buf))) {
78                 perror("failed to allocate buffer");
79                 return 1;
80         }
81         imgrad = sqrt(xsz * xsz + ysz * ysz);
82
83         FILE *fp = fopen("tun_preview.ppm", "wb");
84         if(fp) {
85                 fprintf(fp, "P6\n%d %d\n255\n", xsz, out_nlines * num_frames);
86         }
87
88
89         for(frm=0; frm<num_frames; frm++) {
90                 int coffs = num_frames > 1 ? frm * center / (num_frames - 1) : center;
91
92 #define UDIV    2048
93 #define VDIV    32768
94                 prev_r = 0.0f;
95 #pragma omp parallel for private(i, j, prev_r, ptr) schedule(dynamic)
96                 for(i=0; i<VDIV; i++) {
97                         float v = (float)(VDIV - i) / (float)VDIV;
98                         float r = 4.0 / v + 16;
99                         float z = v * coffs;
100
101                         /* don't bother drawing rings < 1 pixel apart */
102                         if(fabs(r - prev_r) < 0.05) continue;
103
104                         for(j=0; j<UDIV; j++) {
105                                 float u = (float)j / (float)(UDIV - 1);
106                                 float theta = 2.0f * u * M_PI;
107
108                                 int x = (int)(cos(theta) * r - z) + xsz / 2;
109                                 int y = (int)(sin(theta) * r) + ysz / 2;
110
111                                 if(x >= 0 && x < xsz && y >= 0 && y < ysz) {
112                                         ptr = buf + y * xsz + x;
113                                         ptr->x = u;
114                                         ptr->y = v * 8;
115                                 }
116                         }
117                         prev_r = r;
118                 }
119
120                 ptr = buf;
121                 for(i=0; i<out_nlines; i++) {
122                         for(j=0; j<xsz; j++) {
123                                 float u = ptr->x;
124                                 float v = ptr->y;
125                                 int r = (int)(u * 8.0 * 255.0f) & 0xff;
126                                 int g = (int)(v * 8.0 * 255.0f) & 0xff;
127                                 int b = (~(int)(v * 0.5 * 255.0f) & 0xff) + 105;
128                                 if(b > 255) b = 255;
129                                 if(b < 0) b = 0;
130
131                                 /*if(v > 2.0) r = g = b = 0;*/
132
133                                 ptr++;
134
135                                 uint16_t out = ((uint16_t)(u * 255.0f) & 0xff) |
136                                         (((uint16_t)(v * 255.0f) & 0xff) << 8);
137                                 fwrite(&out, sizeof out, 1, stdout);
138
139                                 if(fp) {
140                                         fputc(r, fp);
141                                         fputc(g, fp);
142                                         fputc(b, fp);
143                                 }
144                         }
145                 }
146
147         }
148         fflush(stdout);
149
150         if(fp) fclose(fp);
151         return 0;
152 }