curved tunnel
[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, imgrad, xsz = 240, ysz = 160, texsz = 128;
13         struct vec2 *tunbuf, *tun;
14         float aspect, prev_r;
15         struct vec2 *buf, *ptr;
16
17         for(i=1; i<argc; i++) {
18                 if(argv[i][0] == '-') {
19                         if(argv[i][2] != 0) goto invalopt;
20                         switch(argv[i][1]) {
21                         case 's':
22                                 if(sscanf(argv[++i], "%dx%d", &xsz, &ysz) != 2 || xsz <= 1 || ysz <= 1) {
23                                         fprintf(stderr, "-s must be followed by WxH\n");
24                                         return 1;
25                                 }
26                                 break;
27
28                         case 't':
29                                 if(!(texsz = atoi(argv[++i])) || texsz > 256) {
30                                         fprintf(stderr, "-t must be followed by the texture size (1-256)\n");
31                                         return 1;
32                                 }
33                                 break;
34
35                         default:
36                                 goto invalopt;
37                         }
38                 } else {
39 invalopt:       fprintf(stderr, "invalid argument: %s\n", argv[i]);
40                         return 1;
41                 }
42         }
43
44         if(!(buf = malloc(xsz * ysz * sizeof *buf))) {
45                 perror("failed to allocate buffer");
46                 return 1;
47         }
48         imgrad = sqrt(xsz * xsz + ysz * ysz);
49
50 #define UDIV    2048
51 #define VDIV    32768
52         prev_r = 0.0f;
53         for(i=0; i<VDIV; i++) {
54                 float v = (float)(VDIV - i) / (float)VDIV;
55                 float r = 4.0 / v + 16;
56                 float z = v * 400.0f;
57
58                 /* don't bother drawing rings < 1 pixel apart */
59                 if(fabs(r - prev_r) < 0.05) continue;
60
61                 for(j=0; j<UDIV; j++) {
62                         float u = (float)j / (float)(UDIV - 1);
63                         float theta = 2.0f * u * M_PI;
64
65                         int x = (int)(cos(theta) * r - z) + xsz / 2;
66                         int y = (int)(sin(theta) * r) + ysz / 2;
67
68                         if(x >= 0 && x < xsz && y >= 0 && y < ysz) {
69                                 ptr = buf + y * xsz + x;
70                                 ptr->x = u;
71                                 ptr->y = v * 8;
72                         }
73                 }
74                 prev_r = r;
75         }
76
77         FILE *fp = fopen("tun_preview.ppm", "wb");
78         if(fp) {
79                 fprintf(fp, "P6\n%d %d\n255\n", xsz, ysz);
80         }
81
82         aspect = (float)xsz / (float)ysz;
83
84         ptr = buf;
85         for(i=0; i<ysz; i++) {
86                 for(j=0; j<xsz; j++) {
87                         float u = ptr->x;
88                         float v = ptr->y;
89                         int r = (int)(u * 8.0 * 255.0f) & 0xff;
90                         int b = (int)(v * 8.0 * 255.0f) & 0xff;
91
92                         ptr++;
93
94                         uint16_t out = ((uint16_t)(u * 255.0f) & 0xff) |
95                                 (((uint16_t)(v * 255.0f) & 0xff) << 8);
96                         fwrite(&out, sizeof out, 1, stdout);
97
98                         if(fp) {
99                                 fputc(r, fp);
100                                 fputc(0, fp);
101                                 fputc(b, fp);
102                         }
103                 }
104         }
105         fflush(stdout);
106
107         if(fp) fclose(fp);
108         return 0;
109 }