4 #include <cgmath/cgmath.h>
11 KEY_F1 = GLUT_KEY_F1 | 0x100,
12 KEY_F2 = GLUT_KEY_F2 | 0x100,
13 KEY_F3 = GLUT_KEY_F3 | 0x100,
14 KEY_F4 = GLUT_KEY_F4 | 0x100,
15 KEY_F5 = GLUT_KEY_F5 | 0x100,
16 KEY_F6 = GLUT_KEY_F6 | 0x100,
17 KEY_F7 = GLUT_KEY_F7 | 0x100,
18 KEY_F8 = GLUT_KEY_F8 | 0x100,
19 KEY_F9 = GLUT_KEY_F9 | 0x100,
20 KEY_F10 = GLUT_KEY_F10 | 0x100,
21 KEY_F11 = GLUT_KEY_F11 | 0x100,
22 KEY_F12 = GLUT_KEY_F12 | 0x100,
23 KEY_LEFT = GLUT_KEY_LEFT | 0x100,
24 KEY_UP = GLUT_KEY_UP | 0x100,
25 KEY_RIGHT = GLUT_KEY_RIGHT | 0x100,
26 KEY_DOWN = GLUT_KEY_DOWN | 0x100,
27 KEY_PGUP = GLUT_KEY_PAGE_UP | 0x100,
28 KEY_PGDN = GLUT_KEY_PAGE_DOWN | 0x100,
29 KEY_HOME = GLUT_KEY_HOME | 0x100,
30 KEY_END = GLUT_KEY_END | 0x100,
31 KEY_INS = GLUT_KEY_INSERT | 0x100
34 enum { INP_FWD, INP_BACK, INP_RIGHT, INP_LEFT, INP_FIRE, NUM_INPUTS };
36 static int init(void);
37 static void cleanup(void);
38 static void display(void);
39 static void idle(void);
40 static void reshape(int x, int y);
41 static void keydown(unsigned char key, int x, int y);
42 static void keyup(unsigned char key, int x, int y);
43 static void skeydown(int key, int x, int y);
44 static void skeyup(int key, int x, int y);
45 static void mouse(int bn, int st, int x, int y);
46 static void motion(int x, int y);
47 static unsigned int nextpow2(unsigned int x);
49 static float cam_theta, cam_phi;
50 static cgm_vec3 cam_pos = {0, 1.6, 0};
52 static int mouse_x, mouse_y;
53 static int bnstate[8];
55 static int inpstate[NUM_INPUTS];
57 static int keymap[NUM_INPUTS][2] = {
65 static unsigned int tex;
66 static int tex_width, tex_height;
67 static int tex_intfmt;
68 static float tex_xform[16];
70 static unsigned long nframes;
71 static unsigned long start_time;
74 int main(int argc, char **argv)
76 glutInit(&argc, argv);
78 if(init_options(argc, argv) == -1) {
82 glutInitWindowSize(opt.width, opt.height);
83 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
84 glutCreateWindow("cyberay");
86 glutDisplayFunc(display);
88 glutReshapeFunc(reshape);
89 glutKeyboardFunc(keydown);
90 glutKeyboardUpFunc(keyup);
91 glutSpecialFunc(skeydown);
92 glutSpecialUpFunc(skeyup);
94 glutMotionFunc(motion);
95 glutPassiveMotionFunc(motion);
102 start_time = glutGet(GLUT_ELAPSED_TIME);
108 static int init(void)
110 if(!(tpool = tpool_create(0))) {
111 fprintf(stderr, "failed to create thread pool\n");
115 glEnable(GL_CULL_FACE);
118 glGenTextures(1, &tex);
119 glBindTexture(GL_TEXTURE_2D, tex);
120 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
121 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
123 tex_intfmt = GL_RGB16F;
125 if(load_level(&lvl, "data/test.lvl") == -1) {
131 static void cleanup(void)
135 tsec = (glutGet(GLUT_ELAPSED_TIME) - start_time) / 1000.0f;
136 printf("avg framerate: %.2f fps\n", (float)nframes / tsec);
140 glDeleteTextures(1, &tex);
142 tpool_destroy(tpool);
145 #define WALK_SPEED 3.0f
146 static void update(void)
148 static unsigned int prev_upd;
150 float dt, vfwd, vright;
152 msec = glutGet(GLUT_ELAPSED_TIME) - start_time;
153 dt = (float)(msec - prev_upd) / 1000.0f;
158 if(inpstate[INP_FWD]) {
159 vfwd -= WALK_SPEED * dt;
161 if(inpstate[INP_BACK]) {
162 vfwd += WALK_SPEED * dt;
164 if(inpstate[INP_RIGHT]) {
165 vright += WALK_SPEED * dt;
167 if(inpstate[INP_LEFT]) {
168 vright -= WALK_SPEED * dt;
171 cam_pos.x += cos(cam_theta) * vright + sin(cam_theta) * vfwd;
172 cam_pos.z += -sin(cam_theta) * vright + cos(cam_theta) * vfwd;
174 cgm_midentity(view_xform);
175 cgm_mrotate_x(view_xform, cam_phi);
176 cgm_mrotate_y(view_xform, cam_theta);
177 cgm_mtranslate(view_xform, cam_pos.x, cam_pos.y, cam_pos.z);
180 static void display(void)
185 glBindTexture(GL_TEXTURE_2D, tex);
186 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, fb.width, fb.height, GL_RGB, GL_FLOAT, fb.pixels);
187 glEnable(GL_TEXTURE_2D);
201 assert(glGetError() == GL_NO_ERROR);
206 static void idle(void)
211 static void reshape(int x, int y)
213 glViewport(0, 0, x, y);
215 if(x > tex_width || y > tex_height) {
216 tex_width = nextpow2(x);
217 tex_height = nextpow2(y);
219 glBindTexture(GL_TEXTURE_2D, tex);
220 glTexImage2D(GL_TEXTURE_2D, 0, tex_intfmt, tex_width, tex_height, 0, GL_RGB, GL_FLOAT, 0);
223 cgm_mscaling(tex_xform, (float)x / tex_width, (float)y / tex_height, 1.0f);
225 glMatrixMode(GL_TEXTURE);
226 glLoadMatrixf(tex_xform);
229 static void keyb(int key, int press)
233 for(i=0; i<NUM_INPUTS; i++) {
234 if(keymap[i][0] == key || keymap[i][1] == key) {
240 static void keydown(unsigned char key, int x, int y)
242 if(key == 27) exit(0);
246 static void keyup(unsigned char key, int x, int y)
251 static void skeydown(int key, int x, int y)
253 keyb(key | 0x100, 1);
256 static void skeyup(int key, int x, int y)
258 keyb(key | 0x100, 0);
261 static void mouse(int bn, int st, int x, int y)
265 bnstate[bn - GLUT_LEFT_BUTTON] = st == GLUT_DOWN ? 1 : 0;
268 static void motion(int x, int y)
270 int dx = x - mouse_x;
271 int dy = y - mouse_y;
275 if(!(dx | dy)) return;
278 cam_theta -= dx * 0.01;
279 cam_phi -= dy * 0.01;
281 if(cam_phi < -M_PI) cam_phi = -M_PI;
282 if(cam_phi > M_PI) cam_phi = M_PI;
286 static unsigned int nextpow2(unsigned int x)