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