dostunnel

view src/tunnel.c @ 5:0f984156753e

fixed the jerkiness
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 16 Mar 2013 07:10:53 +0200
parents ba868d348de8
children
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <math.h>
5 #include <conio.h>
6 #include "wvga.h"
7 #include "texture.h"
8 #include "palman.h"
9 #include "timer.h"
11 #ifndef M_PI
12 #define M_PI 3.14159265
13 #endif
15 #define WIDTH 320
16 #define HEIGHT 200
18 int init(void);
19 void cleanup(void);
20 void display(void);
21 int calc_tunnel_mapping(void);
22 int parse_args(int argc, char **argv);
24 static unsigned char *fbuf;
25 static struct texture *tex;
26 static int colrange;
28 static char *tex_fname;
30 static unsigned long *umap, *vmap;
32 static unsigned long frames;
33 static unsigned long start_time;
35 static int under_windows;
38 int main(int argc, char **argv)
39 {
40 if(parse_args(argc, argv) == -1) {
41 return 1;
42 }
44 if(init() == -1) {
45 return 1;
46 }
48 while(!kbhit() || getch() != 27) {
49 display();
50 }
51 cleanup();
52 return 0;
53 }
55 int init(void)
56 {
57 int i;
58 struct palm_color *pal;
60 if(!(fbuf = malloc(WIDTH * HEIGHT))) {
61 fprintf(stderr, "failed to allocate framebuffer\n");
62 return -1;
63 }
65 if(calc_tunnel_mapping() == -1) {
66 fprintf(stderr, "failed to precalc tunnel mapping\n");
67 return 1;
68 }
70 if(tex_fname) {
71 if(!(tex = load_texture(tex_fname))) {
72 fprintf(stderr, "failed to load texture: %s\n", tex_fname);
73 free(fbuf);
74 return -1;
75 }
76 } else {
77 fprintf(stderr, "you must specify a texture to use\n");
78 return -1;
79 }
81 set_video_mode(0x13);
83 palm_build();
84 get_texture_pixels(tex);
86 pal = palm_palette();
87 for(i=0; i<palm_palette_size(); i++) {
88 set_pal_entry(i, pal[i].r, pal[i].g, pal[i].b);
89 }
90 colrange = palm_color_range();
92 init_timer(under_windows ? 0 : 120);
93 start_time = get_msec();
95 return 0;
96 }
98 void cleanup(void)
99 {
100 unsigned long sec = (get_msec() - start_time) / 1000ul;
102 free_texture(tex);
103 free(fbuf);
104 set_video_mode(0x3);
106 if(sec) {
107 printf("avg fps: %lu\n", frames / sec);
108 }
109 }
111 void display(void)
112 {
113 unsigned long msec = get_msec() - start_time;
115 unsigned int i;
116 unsigned char offs = msec >> 3;
118 unsigned char *fbptr = fbuf;
119 unsigned long *uptr = umap;
120 unsigned long *vptr = vmap;
122 for(i=0; i<64000; i++) {
123 unsigned long u = *uptr++;
124 unsigned long v = *vptr++;
125 unsigned long tx = ((((unsigned long)((u << 3) - offs)) & 0xff) * tex->width) >> 8;
126 unsigned long ty = (((unsigned long)(v + offs) & 0xff) * tex->height) >> 8;
128 unsigned long base = tex->pixels[ty * tex->width + tx];
129 long zcue_shift = colrange - (v >> 6);
130 if(zcue_shift < 0) {
131 zcue_shift = 0;
132 }
133 *fbptr++ = (unsigned char)(base + zcue_shift);
134 }
136 copy_frame(fbuf);
137 frames++;
138 }
140 int calc_tunnel_mapping(void)
141 {
142 int i, j;
143 unsigned long *uptr, *vptr;
144 float diag_dist = sqrt(1.33333 * 1.33333 + 1.0);
146 if(!(umap = malloc(WIDTH * HEIGHT * sizeof *umap))) {
147 return -1;
148 }
149 if(!(vmap = malloc(WIDTH * HEIGHT * sizeof *umap))) {
150 free(umap);
151 return -1;
152 }
154 uptr = umap;
155 vptr = vmap;
157 for(i=0; i<HEIGHT; i++) {
158 for(j=0; j<WIDTH; j++) {
159 float x = ((float)j / WIDTH * 2.0 - 1.0) * 1.33333;
160 float y = (float)i / HEIGHT * 2.0 - 1.0;
161 float angle, z, dist;
163 if(fabs(x) > 0.00001) {
164 angle = atan2(y, x) + M_PI;
165 } else {
166 angle = y < 0.0 ? M_PI / 2.0 : 3.0 * M_PI / 2.0;
167 }
168 dist = sqrt(x * x + y * y);
169 z = 2.0 / dist;
171 *uptr++ = (unsigned int)(angle * 0.5 / M_PI * 255.0);
172 *vptr++ = (unsigned int)(z * 255.0);
173 }
174 }
175 return 0;
176 }
178 int parse_args(int argc, char **argv)
179 {
180 int i;
182 for(i=1; i<argc; i++) {
183 if(argv[i][0] == '-') {
184 if(strcmp(argv[i], "-win") == 0) {
185 under_windows = 1;
186 } else {
187 fprintf(stderr, "invalid option: %s\n", argv[i]);
188 return -1;
189 }
190 } else {
191 if(tex_fname) {
192 fprintf(stderr, "unexpected argument: %s\n", argv[i]);
193 return -1;
194 }
195 tex_fname = argv[i];
196 }
197 }
199 if(!tex_fname) {
200 tex_fname = "data/wall2.ppm";
201 }
202 return 0;
203 }