bcf22504d1117aae50c98f03c602c7e9866cc3e5
[voxscape] / src / main.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <math.h>
5 #include <assert.h>
6 #include <GL/glut.h>
7 #include "glfb.h"
8 #include "voxscape.h"
9 #include "lut.h"
10
11 enum {
12         INP_FWD         = 0x01,
13         INP_BACK        = 0x02,
14         INP_LEFT        = 0x04,
15         INP_RIGHT       = 0x08,
16         INP_LTURN       = 0x10,
17         INP_RTURN       = 0x20
18 };
19
20 int init(void);
21 void cleanup(void);
22 void display(void);
23 void idle(void);
24 void reshape(int x, int y);
25 void keyb(unsigned char key, int x, int y);
26 void keyb_up(unsigned char key, int x, int y);
27 void mouse(int bn, int st, int x, int y);
28 void motion(int x, int y);
29
30 int win_width, win_height;
31
32 #define FB_W    640
33 #define FB_H    480
34 unsigned int fb[FB_W * FB_H];
35
36 int mouse_x, mouse_y, mwarp, mbstate[3];
37 int hfilt = VOX_LINEAR, cfilt = VOX_LINEAR;
38
39 unsigned int input;
40 int32_t pos[2], angle;
41
42 struct voxscape *vox;
43
44 #define COLOR_HORIZON   0xcc77ff
45 #define COLOR_ZENITH    0x5588cc
46
47
48 int main(int argc, char **argv)
49 {
50         glutInit(&argc, argv);
51         glutInitWindowSize(1280, 960);
52         glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
53         glutCreateWindow("voxel landscape test");
54
55         glutDisplayFunc(display);
56         glutIdleFunc(idle);
57         glutReshapeFunc(reshape);
58         glutKeyboardFunc(keyb);
59         glutKeyboardUpFunc(keyb_up);
60         glutMouseFunc(mouse);
61         glutMotionFunc(motion);
62
63         if(init() == -1) {
64                 return 1;
65         }
66         atexit(cleanup);
67
68         glutMainLoop();
69         return 0;
70 }
71
72
73 int init(void)
74 {
75         init_lut();
76
77         pos[0] = 512 << 16;
78         pos[1] = 512 << 16;
79
80         if(!(vox = vox_open("data/height.png", "data/color.png"))) {
81                 return -1;
82         }
83         vox_framebuf(vox, FB_W, FB_H, fb, -1);
84         vox_proj(vox, 45, 1, 300);
85         vox_fog(vox, 260, COLOR_HORIZON);
86         vox_filter(vox, hfilt, cfilt);
87
88         glfb_setup(FB_W, FB_H, GLFB_RGBA32, FB_W * 4);
89         return 0;
90 }
91
92 void cleanup(void)
93 {
94         vox_free(vox);
95 }
96
97 #define WALK_SPEED      0x40000
98 #define TURN_SPEED      0x100
99
100 void update(void)
101 {
102         int32_t fwd[2], right[2];
103
104         if(input & INP_LTURN) angle += TURN_SPEED;
105         if(input & INP_RTURN) angle -= TURN_SPEED;
106
107         fwd[0] = -SIN(angle);
108         fwd[1] = COS(angle);
109         right[0] = fwd[1];
110         right[1] = -fwd[0];
111
112         if(input & INP_FWD) {
113                 pos[0] += fwd[0];
114                 pos[1] += fwd[1];
115         }
116         if(input & INP_BACK) {
117                 pos[0] -= fwd[0];
118                 pos[1] -= fwd[1];
119         }
120         if(input & INP_RIGHT) {
121                 pos[0] += right[0];
122                 pos[1] += right[1];
123         }
124         if(input & INP_LEFT) {
125                 pos[0] -= right[0];
126                 pos[1] -= right[1];
127         }
128
129         vox_view(vox, pos[0], pos[1], -30, angle);
130 }
131
132 void display(void)
133 {
134         update();
135
136         memset(fb, 0, sizeof fb);
137
138         vox_render(vox);
139         vox_sky_grad(vox, COLOR_HORIZON, COLOR_ZENITH);
140
141         glfb_update(fb);
142         glfb_display();
143
144         glutSwapBuffers();
145         assert(glGetError() == GL_NO_ERROR);
146
147         if(mbstate[0]) {
148                 mwarp = 1;
149                 glutWarpPointer(win_width / 2, win_height / 2);
150         }
151 }
152
153 void idle(void)
154 {
155         glutPostRedisplay();
156 }
157
158 void reshape(int x, int y)
159 {
160         glViewport(0, 0, x, y);
161
162         win_width = x;
163         win_height = y;
164 }
165
166 void keyb(unsigned char key, int x, int y)
167 {
168         switch(key) {
169         case 27:
170                 exit(0);
171
172         case 'w':
173                 input |= INP_FWD;
174                 break;
175         case 's':
176                 input |= INP_BACK;
177                 break;
178         case 'a':
179                 input |= INP_LEFT;
180                 break;
181         case 'd':
182                 input |= INP_RIGHT;
183                 break;
184         case 'q':
185                 input |= INP_LTURN;
186                 break;
187         case 'e':
188                 input |= INP_RTURN;
189                 break;
190
191         case 'h':
192                 hfilt ^= 1;
193                 printf("filtering: height(%s) color(%s)\n", hfilt ? "linear" : "nearest",
194                                 cfilt ? "linear" : "nearest");
195                 vox_filter(vox, hfilt, cfilt);
196                 break;
197
198         case 'c':
199                 cfilt ^= 1;
200                 vox_filter(vox, hfilt, cfilt);
201                 printf("filtering: height(%s) color(%s)\n", hfilt ? "linear" : "nearest",
202                                 cfilt ? "linear" : "nearest");
203                 break;
204
205         default:
206                 break;
207         }
208 }
209
210 void keyb_up(unsigned char key, int x, int y)
211 {
212         switch(key) {
213         case 'w':
214                 input &= ~INP_FWD;
215                 break;
216         case 's':
217                 input &= ~INP_BACK;
218                 break;
219         case 'a':
220                 input &= ~INP_LEFT;
221                 break;
222         case 'd':
223                 input &= ~INP_RIGHT;
224                 break;
225         case 'q':
226                 input &= ~INP_LTURN;
227                 break;
228         case 'e':
229                 input &= ~INP_RTURN;
230                 break;
231
232         default:
233                 break;
234         }
235 }
236
237 void mouse(int bn, int st, int x, int y)
238 {
239         int bidx = bn - GLUT_LEFT_BUTTON;
240
241         if(bidx < 3) {
242                 mbstate[bidx] = st == GLUT_DOWN;
243         }
244         mouse_x = x;
245         mouse_y = y;
246
247         if(st == GLUT_DOWN) {
248                 glutSetCursor(GLUT_CURSOR_NONE);
249         } else {
250                 glutSetCursor(GLUT_CURSOR_LEFT_ARROW);
251         }
252 }
253
254 void motion(int x, int y)
255 {
256         int dx = x - mouse_x;
257         int dy = y - mouse_y;
258         mouse_x = x;
259         mouse_y = y;
260
261         if(mwarp) {
262                 mwarp = 0;
263                 return;
264         }
265         if(!(dx | dy)) return;
266
267         if(mbstate[0]) {
268                 angle -= dx << 6;
269         }
270 }