72cc76cb92601efaf81f7da628ea0d74152f3d3f
[cyberay] / src / main.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4 #include <cgmath/cgmath.h>
5 #include "miniglut.h"
6 #include "level.h"
7
8 enum {
9         KEY_F1          = GLUT_KEY_F1 | 0x100,
10         KEY_F2          = GLUT_KEY_F2 | 0x100,
11         KEY_F3          = GLUT_KEY_F3 | 0x100,
12         KEY_F4          = GLUT_KEY_F4 | 0x100,
13         KEY_F5          = GLUT_KEY_F5 | 0x100,
14         KEY_F6          = GLUT_KEY_F6 | 0x100,
15         KEY_F7          = GLUT_KEY_F7 | 0x100,
16         KEY_F8          = GLUT_KEY_F8 | 0x100,
17         KEY_F9          = GLUT_KEY_F9 | 0x100,
18         KEY_F10         = GLUT_KEY_F10 | 0x100,
19         KEY_F11         = GLUT_KEY_F11 | 0x100,
20         KEY_F12         = GLUT_KEY_F12 | 0x100,
21         KEY_LEFT        = GLUT_KEY_LEFT | 0x100,
22         KEY_UP          = GLUT_KEY_UP | 0x100,
23         KEY_RIGHT       = GLUT_KEY_RIGHT | 0x100,
24         KEY_DOWN        = GLUT_KEY_DOWN | 0x100,
25         KEY_PGUP        = GLUT_KEY_PAGE_UP | 0x100,
26         KEY_PGDN        = GLUT_KEY_PAGE_DOWN | 0x100,
27         KEY_HOME        = GLUT_KEY_HOME | 0x100,
28         KEY_END         = GLUT_KEY_END | 0x100,
29         KEY_INS         = GLUT_KEY_INSERT | 0x100
30 };
31
32 enum { INP_FWD, INP_BACK, INP_RIGHT, INP_LEFT, INP_FIRE, NUM_INPUTS };
33
34 static int init(void);
35 static void cleanup(void);
36 static void display(void);
37 static void idle(void);
38 static void reshape(int x, int y);
39 static void keydown(unsigned char key, int x, int y);
40 static void keyup(unsigned char key, int x, int y);
41 static void skeydown(int key, int x, int y);
42 static void skeyup(int key, int x, int y);
43 static void mouse(int bn, int st, int x, int y);
44 static void motion(int x, int y);
45 static unsigned int nextpow2(unsigned int x);
46
47 static long start_time;
48
49 static float cam_theta, cam_phi;
50 static cgm_vec3 cam_pos = {0, -1.6, 0};
51 static float pxform[16];
52
53 static int mouse_x, mouse_y;
54 static int bnstate[8];
55
56 static int inpstate[NUM_INPUTS];
57
58 static int keymap[NUM_INPUTS][2] = {
59         {'w', KEY_UP},
60         {'s', KEY_DOWN},
61         {'d', KEY_RIGHT},
62         {'a', KEY_LEFT},
63         {' ', 0}
64 };
65
66 static struct level lvl;
67
68 static unsigned int tex;
69 static int tex_width, tex_height;
70 static int tex_intfmt;
71 static float tex_xform[16];
72
73
74 int main(int argc, char **argv)
75 {
76         glutInit(&argc, argv);
77         glutInitWindowSize(1280, 800);
78         glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
79         glutCreateWindow("cyberay");
80
81         glutDisplayFunc(display);
82         glutIdleFunc(idle);
83         glutReshapeFunc(reshape);
84         glutKeyboardFunc(keydown);
85         glutKeyboardUpFunc(keyup);
86         glutSpecialFunc(skeydown);
87         glutSpecialUpFunc(skeyup);
88         glutMouseFunc(mouse);
89         glutMotionFunc(motion);
90         glutPassiveMotionFunc(motion);
91
92         if(init() == -1) {
93                 return 1;
94         }
95         atexit(cleanup);
96
97         glutMainLoop();
98         return 0;
99 }
100
101 static int init(void)
102 {
103         glEnable(GL_CULL_FACE);
104
105         /*
106         glEnable(GL_DEPTH_TEST);
107         glEnable(GL_LIGHTING);
108         glEnable(GL_LIGHT0);
109         */
110
111         glGenTextures(1, &tex);
112         glBindTexture(GL_TEXTURE_2D, tex);
113         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
114         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
115
116         tex_intfmt = GL_RGB16F;
117
118         if(load_level(&lvl, "data/test.lvl") == -1) {
119                 return -1;
120         }
121
122         start_time = glutGet(GLUT_ELAPSED_TIME);
123         return 0;
124 }
125
126 static void cleanup(void)
127 {
128         destroy_level(&lvl);
129
130         glDeleteTextures(1, &tex);
131 }
132
133 #define WALK_SPEED 3.0f
134 static void update(void)
135 {
136         static unsigned int prev_upd;
137         unsigned int msec;
138         float dt, vfwd, vright;
139
140         msec = glutGet(GLUT_ELAPSED_TIME) - start_time;
141         dt = (float)(msec - prev_upd) / 1000.0f;
142         prev_upd = msec;
143
144         vfwd = vright = 0;
145
146         if(inpstate[INP_FWD]) {
147                 vfwd -= WALK_SPEED * dt;
148         }
149         if(inpstate[INP_BACK]) {
150                 vfwd += WALK_SPEED * dt;
151         }
152         if(inpstate[INP_RIGHT]) {
153                 vright -= WALK_SPEED * dt;
154         }
155         if(inpstate[INP_LEFT]) {
156                 vright += WALK_SPEED * dt;
157         }
158
159         cam_pos.x += cos(cam_theta) * vright + sin(cam_theta) * vfwd;
160         cam_pos.z += sin(cam_theta) * vright - cos(cam_theta) * vfwd;
161
162         cgm_midentity(pxform);
163         cgm_mtranslate(pxform, cam_pos.x, cam_pos.y, cam_pos.z);
164         cgm_mrotate_y(pxform, cam_theta);
165         cgm_mrotate_x(pxform, cam_phi);
166 }
167
168 static void display(void)
169 {
170         update();
171
172         render();
173         glBindTexture(GL_TEXTURE_2D, tex);
174         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, fb.width, fb.height, GL_RGB, GL_FLOAT, fb.pixels);
175         glEnable(GL_TEXTURE_2D);
176
177         glBegin(GL_QUADS);
178         glTexCoord2f(0, 0);
179         glVertex2f(-1, -1);
180         glTexCoord2f(1, 0);
181         glVertex2f(1, -1);
182         glTexCoord2f(1, 1);
183         glVertex2f(1, 1);
184         glTexCoord2f(0, 1);
185         glVertex2f(-1, 1);
186         glEnd();
187
188         /*
189         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
190
191         glMatrixMode(GL_MODELVIEW);
192         glLoadMatrixf(pxform);
193
194         draw_level(&lvl);
195         */
196
197         glutSwapBuffers();
198         assert(glGetError() == GL_NO_ERROR);
199 }
200
201 static void idle(void)
202 {
203         glutPostRedisplay();
204 }
205
206 static void reshape(int x, int y)
207 {
208         /*
209         float proj[16];
210
211         cgm_mperspective(proj, cgm_deg_to_rad(50.0f), (float)x / (float)y, 0.5, 500.0);
212
213         glMatrixMode(GL_PROJECTION);
214         glLoadMatrixf(proj);
215         */
216
217         if(x > tex_width || y > tex_height) {
218                 tex_width = nextpow2(x);
219                 tex_height = nextpow2(y);
220
221                 glBindTexture(GL_TEXTURE_2D, tex);
222                 glTexImage2D(GL_TEXTURE_2D, 0, tex_intfmt, tex_width, tex_height, 0, GL_RGB, GL_FLOAT, 0);
223         }
224         fbsize(x, y);
225         cgm_mscaling(tex_xform, (float)x / tex_width, (float)y / tex_height, 1.0f);
226
227         glMatrixMode(GL_TEXTURE);
228         glLoadMatrixf(tex_xform);
229 }
230
231 static void keyb(int key, int press)
232 {
233         int i;
234
235         for(i=0; i<NUM_INPUTS; i++) {
236                 if(keymap[i][0] == key || keymap[i][1] == key) {
237                         inpstate[i] = press;
238                 }
239         }
240 }
241
242 static void keydown(unsigned char key, int x, int y)
243 {
244         if(key == 27) exit(0);
245         keyb(key, 1);
246 }
247
248 static void keyup(unsigned char key, int x, int y)
249 {
250         keyb(key, 0);
251 }
252
253 static void skeydown(int key, int x, int y)
254 {
255         keyb(key | 0x100, 1);
256 }
257
258 static void skeyup(int key, int x, int y)
259 {
260         keyb(key | 0x100, 0);
261 }
262
263 static void mouse(int bn, int st, int x, int y)
264 {
265         mouse_x = x;
266         mouse_y = y;
267         bnstate[bn - GLUT_LEFT_BUTTON] = st == GLUT_DOWN ? 1 : 0;
268 }
269
270 static void motion(int x, int y)
271 {
272         int dx = x - mouse_x;
273         int dy = y - mouse_y;
274         mouse_x = x;
275         mouse_y = y;
276
277         if(!(dx | dy)) return;
278
279         if(bnstate[0]) {
280                 cam_theta += dx * 0.01;
281                 cam_phi += dy * 0.01;
282
283                 if(cam_phi < -M_PI) cam_phi = -M_PI;
284                 if(cam_phi > M_PI) cam_phi = M_PI;
285         }
286 }
287
288 static unsigned int nextpow2(unsigned int x)
289 {
290         x--;
291         x |= x >> 1;
292         x |= x >> 2;
293         x |= x >> 4;
294         x |= x >> 8;
295         x |= x >> 16;
296         return x + 1;
297 }