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