+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <math.h>
+
+int main(int argc, char **argv)
+{
+ int i, j, xsz = 240, ysz = 160, texsz = 128;
+ struct vec2 *tunbuf, *tun;
+ float aspect;
+
+ for(i=1; i<argc; i++) {
+ if(argv[i][0] == '-') {
+ if(argv[i][2] != 0) goto invalopt;
+ switch(argv[i][1]) {
+ case 's':
+ if(sscanf(argv[++i], "%dx%d", &xsz, &ysz) != 2 || xsz <= 1 || ysz <= 1) {
+ fprintf(stderr, "-s must be followed by WxH\n");
+ return 1;
+ }
+ break;
+
+ case 't':
+ if(!(texsz = atoi(argv[++i])) || texsz > 256) {
+ fprintf(stderr, "-t must be followed by the texture size (1-256)\n");
+ return 1;
+ }
+ break;
+
+ default:
+ goto invalopt;
+ }
+ } else {
+invalopt: fprintf(stderr, "invalid argument: %s\n", argv[i]);
+ return 1;
+ }
+ }
+
+ FILE *fp = fopen("tun_preview.ppm", "wb");
+ if(fp) {
+ fprintf(fp, "P6\n%d %d\n255\n", xsz, ysz);
+ }
+
+ aspect = (float)xsz / (float)ysz;
+
+ tun = tunbuf;
+ for(i=0; i<ysz; i++) {
+ float y = 2.0f * (float)i / (float)(ysz - 1) - 1.0f;
+ for(j=0; j<xsz; j++) {
+ float x = (2.0f * (float)j / (float)(xsz - 1) - 1.0f) * aspect;
+
+ float r = sqrt(x * x + y * y);
+ float theta = atan2(y, x);
+
+ float u = 0.5f * theta / M_PI + 0.5f;
+ float v = r;
+
+ uint32_t out = ((uint32_t)(u * 65535.0f) & 0xffff) |
+ (((uint32_t)(v * 65535.0f) & 0xffff) << 16);
+ fwrite(&out, sizeof out, 1, stdout);
+
+ if(fp) {
+ int cr = (int)(u * 2048.0f) & 0xff;
+ int cb = (int)(r * 2048.0f) & 0xff;
+ fputc(cr, fp);
+ fputc(0, fp);
+ fputc(cb, fp);
+ }
+ }
+ }
+ fflush(stdout);
+
+ if(fp) fclose(fp);
+ return 0;
+}