conworlds

annotate src/game.cc @ 20:782ff06817fb

merged ...
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 26 Aug 2014 18:42:53 +0300
parents e4257df067a1 c814f77d177e
children
rev   line source
nuclear@15 1 #include <math.h>
nuclear@2 2 #include "game.h"
nuclear@13 3 #include "gameopt.h"
nuclear@2 4 #include "opengl.h"
nuclear@2 5 #include "camera.h"
nuclear@2 6 #include "texture.h"
nuclear@4 7 #include "vr/vr.h"
nuclear@2 8
nuclear@7 9 static void game_render_eye(int eye);
nuclear@2 10 static void draw_scene();
nuclear@6 11 static bool setup_rtarg(int x, int y);
nuclear@15 12 static void draw_box(float sz);
nuclear@15 13 static void draw_pyramid(float basesz, float height);
nuclear@15 14
nuclear@6 15
nuclear@7 16 static Texture *rtarg;
nuclear@6 17 static unsigned int fbo, rtarg_depth;
nuclear@7 18 static int rtwidth, rtheight;
nuclear@2 19
nuclear@2 20 static const float move_speed = 10.0f;
nuclear@2 21
nuclear@2 22 static int fb_width, fb_height;
nuclear@2 23 static FlyCamera cam;
nuclear@2 24 static Texture floor_tex;
nuclear@2 25 static bool keystate[256];
nuclear@13 26 static float player_height = 1.68;
nuclear@2 27
nuclear@2 28 bool game_init()
nuclear@2 29 {
nuclear@13 30 if(opt.vr) {
nuclear@13 31 vr_init();
nuclear@13 32 if(opt.vr_module) {
nuclear@13 33 vr_use_module_named(opt.vr_module);
nuclear@13 34 }
nuclear@13 35
nuclear@13 36 player_height = vr_get_optf(VR_OPT_EYE_HEIGHT);
nuclear@13 37 }
nuclear@4 38
nuclear@2 39 glEnable(GL_DEPTH_TEST);
nuclear@2 40 glEnable(GL_CULL_FACE);
nuclear@2 41 glEnable(GL_LIGHTING);
nuclear@2 42 glEnable(GL_LIGHT0);
nuclear@12 43 glEnable(GL_NORMALIZE);
nuclear@2 44
nuclear@2 45 glClearColor(0.1, 0.1, 0.1, 1);
nuclear@2 46
nuclear@6 47
nuclear@2 48 if(!floor_tex.load("data/tiles.png")) {
nuclear@2 49 return false;
nuclear@2 50 }
nuclear@2 51
nuclear@13 52 cam.input_move(0, player_height, 0);
nuclear@2 53 return true;
nuclear@2 54 }
nuclear@2 55
nuclear@2 56 void game_cleanup()
nuclear@2 57 {
nuclear@2 58 floor_tex.destroy();
nuclear@13 59 if(opt.vr) {
nuclear@13 60 vr_shutdown();
nuclear@13 61 }
nuclear@6 62
nuclear@6 63 if(fbo) {
nuclear@6 64 glDeleteFramebuffers(1, &fbo);
nuclear@6 65 glDeleteRenderbuffers(1, &rtarg_depth);
nuclear@7 66 delete rtarg;
nuclear@6 67 }
nuclear@2 68 }
nuclear@2 69
nuclear@2 70 void game_update(unsigned int msec)
nuclear@2 71 {
nuclear@2 72 static unsigned int prev_msec;
nuclear@2 73 float dt = (msec - prev_msec) / 1000.0f;
nuclear@2 74 float offs = dt * move_speed;
nuclear@2 75 prev_msec = msec;
nuclear@2 76
nuclear@2 77 Vector3 move;
nuclear@2 78 float roll = 0.0f;
nuclear@2 79
nuclear@2 80 if(keystate['d'] || keystate['D']) {
nuclear@2 81 move.x += offs;
nuclear@2 82 }
nuclear@2 83 if(keystate['a'] || keystate['A']) {
nuclear@2 84 move.x -= offs;
nuclear@2 85 }
nuclear@2 86 if(keystate['s'] || keystate['S']) {
nuclear@2 87 move.z += offs;
nuclear@2 88 }
nuclear@2 89 if(keystate['w'] || keystate['W']) {
nuclear@2 90 move.z -= offs;
nuclear@2 91 }
nuclear@2 92 if(keystate['e'] || keystate['E']) {
nuclear@2 93 roll += dt;
nuclear@2 94 }
nuclear@2 95 if(keystate['q'] || keystate['Q']) {
nuclear@2 96 roll -= dt;
nuclear@2 97 }
nuclear@2 98
nuclear@2 99 cam.input_move(move.x, move.y, move.z);
nuclear@2 100 cam.input_rotate(0, 0, roll);
nuclear@2 101 }
nuclear@2 102
nuclear@7 103 void game_render()
nuclear@2 104 {
nuclear@13 105 if(opt.vr) {
nuclear@13 106 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
nuclear@13 107 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
nuclear@6 108
nuclear@13 109 glViewport(0, 0, rtwidth / 2.0, rtheight);
nuclear@13 110 vr_begin(VR_EYE_LEFT);
nuclear@13 111 game_render_eye(-1);
nuclear@13 112 vr_end();
nuclear@7 113
nuclear@13 114 glViewport(rtwidth / 2, 0, rtwidth / 2.0, rtheight);
nuclear@13 115 vr_begin(VR_EYE_RIGHT);
nuclear@13 116 game_render_eye(1);
nuclear@13 117 vr_end();
nuclear@7 118
nuclear@13 119 glBindFramebuffer(GL_FRAMEBUFFER, 0);
nuclear@13 120 glViewport(0, 0, fb_width, fb_height);
nuclear@8 121
nuclear@13 122 vr_output_texture(rtarg->get_texture_id(), 0, 0, (float)rtwidth / (float)rtarg->get_width(),
nuclear@13 123 (float)rtheight / (float)rtarg->get_height());
nuclear@13 124 } else {
nuclear@13 125 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
nuclear@13 126
nuclear@13 127 game_render_eye(0);
nuclear@13 128 }
nuclear@9 129
nuclear@9 130 vr_swap_buffers();
nuclear@7 131 }
nuclear@7 132
nuclear@7 133 static void game_render_eye(int eye)
nuclear@7 134 {
nuclear@4 135 float mat[16];
nuclear@2 136 Matrix4x4 view_matrix = cam.get_matrix().inverse();
nuclear@2 137
nuclear@2 138 glMatrixMode(GL_PROJECTION);
nuclear@2 139 glLoadIdentity();
nuclear@11 140 if(eye == 0 || !vr_proj_matrix(eye < 0 ? 0 : 1, 0.5, 500.0, mat)) {
nuclear@4 141 gluPerspective(60.0, (float)fb_width / (float)fb_height, 0.5, 500.0);
nuclear@11 142 } else {
nuclear@7 143 glLoadMatrixf(mat);
nuclear@11 144 }
nuclear@2 145
nuclear@2 146 glMatrixMode(GL_MODELVIEW);
nuclear@11 147 if(eye == 0 || !vr_view_matrix(eye < 0 ? 0 : 1, mat)) {
nuclear@4 148 glLoadIdentity();
nuclear@11 149 } else {
nuclear@18 150 glLoadMatrixf(mat);
nuclear@11 151 }
nuclear@4 152 glMultTransposeMatrixf(view_matrix[0]);
nuclear@2 153
nuclear@2 154 draw_scene();
nuclear@2 155 }
nuclear@2 156
nuclear@2 157 void game_reshape(int x, int y)
nuclear@2 158 {
nuclear@2 159 glViewport(0, 0, x, y);
nuclear@2 160 fb_width = x;
nuclear@2 161 fb_height = y;
nuclear@6 162
nuclear@7 163 int lxres = vr_get_opti(VR_OPT_LEYE_XRES);
nuclear@7 164 if(lxres) {
nuclear@7 165 int lyres = vr_get_opti(VR_OPT_LEYE_YRES);
nuclear@7 166 int rxres = vr_get_opti(VR_OPT_REYE_XRES);
nuclear@7 167 int ryres = vr_get_opti(VR_OPT_REYE_YRES);
nuclear@7 168
nuclear@7 169 rtwidth = lxres + rxres;
nuclear@7 170 rtheight = lyres > ryres ? lyres : ryres;
nuclear@7 171 } else {
nuclear@7 172 rtwidth = x;
nuclear@7 173 rtheight = y;
nuclear@7 174 }
nuclear@7 175
nuclear@7 176 setup_rtarg(rtwidth, rtheight);
nuclear@2 177 }
nuclear@2 178
nuclear@17 179 void game_keyboard(int key, bool pressed)
nuclear@2 180 {
nuclear@2 181 if(pressed) {
nuclear@2 182 switch(key) {
nuclear@2 183 case 27:
nuclear@2 184 exit(0);
nuclear@9 185
nuclear@9 186 case ' ':
nuclear@9 187 vr_recenter();
nuclear@9 188 break;
nuclear@2 189 }
nuclear@2 190 }
nuclear@2 191
nuclear@2 192 if(key < 256) {
nuclear@2 193 keystate[key] = pressed;
nuclear@2 194 }
nuclear@2 195 }
nuclear@2 196
nuclear@2 197 static int prev_x, prev_y;
nuclear@2 198 static bool bnstate[32];
nuclear@2 199
nuclear@2 200 void game_mouse(int bn, bool pressed, int x, int y)
nuclear@2 201 {
nuclear@2 202 bnstate[bn] = pressed;
nuclear@2 203 prev_x = x;
nuclear@2 204 prev_y = y;
nuclear@2 205 }
nuclear@2 206
nuclear@2 207 void game_motion(int x, int y)
nuclear@2 208 {
nuclear@2 209 int dx = x - prev_x;
nuclear@2 210 int dy = y - prev_y;
nuclear@2 211 prev_x = x;
nuclear@2 212 prev_y = y;
nuclear@2 213
nuclear@2 214 if(!dx && !dy) return;
nuclear@2 215
nuclear@2 216 if(bnstate[0]) {
nuclear@2 217 float xrot = dy * 0.5;
nuclear@2 218 float yrot = dx * 0.5;
nuclear@2 219 cam.input_rotate(DEG_TO_RAD(xrot), 0, 0);
nuclear@2 220 cam.input_rotate(0, DEG_TO_RAD(yrot), 0);
nuclear@2 221 }
nuclear@2 222 }
nuclear@2 223
nuclear@3 224 void game_mwheel(int dir)
nuclear@3 225 {
nuclear@3 226 cam.input_move(0, dir * 0.1, 0);
nuclear@3 227 }
nuclear@3 228
nuclear@2 229 void game_6dof_move(float x, float y, float z)
nuclear@2 230 {
nuclear@2 231 cam.input_move(x, y, z);
nuclear@2 232 }
nuclear@2 233
nuclear@2 234 void game_6dof_rotate(float x, float y, float z)
nuclear@2 235 {
nuclear@2 236 cam.input_rotate(x, y, z);
nuclear@2 237 }
nuclear@2 238
nuclear@2 239 static void draw_scene()
nuclear@2 240 {
nuclear@2 241 float lpos[] = {-20, 30, 10, 1};
nuclear@2 242 glLightfv(GL_LIGHT0, GL_POSITION, lpos);
nuclear@2 243
nuclear@2 244 glEnable(GL_TEXTURE_2D);
nuclear@13 245 bind_texture(&floor_tex);
nuclear@2 246
nuclear@2 247 glMatrixMode(GL_TEXTURE);
nuclear@2 248 glScalef(8, 8, 8);
nuclear@2 249
nuclear@2 250 glBegin(GL_QUADS);
nuclear@2 251 glNormal3f(0, 1, 0);
nuclear@2 252 glTexCoord2f(0, 0); glVertex3f(-25, 0, 25);
nuclear@2 253 glTexCoord2f(1, 0); glVertex3f(25, 0, 25);
nuclear@2 254 glTexCoord2f(1, 1); glVertex3f(25, 0, -25);
nuclear@2 255 glTexCoord2f(0, 1); glVertex3f(-25, 0, -25);
nuclear@2 256 glEnd();
nuclear@2 257 glDisable(GL_TEXTURE_2D);
nuclear@2 258 glLoadIdentity();
nuclear@2 259
nuclear@2 260 glMatrixMode(GL_MODELVIEW);
nuclear@2 261
nuclear@12 262 for(int i=0; i<4; i++) {
nuclear@12 263 glPushMatrix();
nuclear@12 264 glTranslatef(i & 1 ? -10 : 10, 0, i & 2 ? -10 : 10);
nuclear@15 265 draw_pyramid(2.0, 2.0);
nuclear@12 266 glPopMatrix();
nuclear@12 267 }
nuclear@2 268 }
nuclear@6 269
nuclear@6 270 static bool setup_rtarg(int x, int y)
nuclear@6 271 {
nuclear@6 272 int tex_width = next_pow2(x);
nuclear@6 273 int tex_height = next_pow2(y);
nuclear@6 274
nuclear@6 275 /* create render targets for each eye */
nuclear@6 276 if(!fbo) {
nuclear@6 277 glGenFramebuffers(1, &fbo);
nuclear@6 278 glGenRenderbuffers(1, &rtarg_depth);
nuclear@7 279 rtarg = new Texture;
nuclear@6 280 }
nuclear@6 281
nuclear@6 282 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
nuclear@6 283
nuclear@6 284 glBindRenderbuffer(GL_RENDERBUFFER, rtarg_depth);
nuclear@6 285 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, tex_width, tex_height);
nuclear@6 286 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rtarg_depth);
nuclear@6 287
nuclear@7 288 rtarg->create2d(tex_width, tex_height);
nuclear@7 289 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
nuclear@7 290 rtarg->get_texture_id(), 0);
nuclear@6 291
nuclear@6 292 if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
nuclear@6 293 fprintf(stderr, "incomplete framebuffer!\n");
nuclear@6 294 return false;
nuclear@6 295 }
nuclear@6 296 glBindFramebuffer(GL_FRAMEBUFFER, 0);
nuclear@7 297
nuclear@7 298 printf("created render target %dx%d (texture: %dx%d)\n", x, y, tex_width, tex_height);
nuclear@6 299 return true;
nuclear@6 300 }
nuclear@15 301
nuclear@15 302 static void draw_box(float sz)
nuclear@15 303 {
nuclear@15 304 float hsz = sz / 2.0;
nuclear@15 305
nuclear@15 306 glBegin(GL_QUADS);
nuclear@15 307 glNormal3f(0, 0, 1);
nuclear@15 308 glVertex3f(-hsz, -hsz, hsz);
nuclear@15 309 glVertex3f(hsz, -hsz, hsz);
nuclear@15 310 glVertex3f(hsz, hsz, hsz);
nuclear@15 311 glVertex3f(-hsz, hsz, hsz);
nuclear@15 312 glNormal3f(1, 0, 0);
nuclear@15 313 glVertex3f(hsz, -hsz, hsz);
nuclear@15 314 glVertex3f(hsz, -hsz, -hsz);
nuclear@15 315 glVertex3f(hsz, hsz, -hsz);
nuclear@15 316 glVertex3f(hsz, hsz, hsz);
nuclear@15 317 glNormal3f(0, 0, -1);
nuclear@15 318 glVertex3f(hsz, -hsz, -hsz);
nuclear@15 319 glVertex3f(-hsz, -hsz, -hsz);
nuclear@15 320 glVertex3f(-hsz, hsz, -hsz);
nuclear@15 321 glVertex3f(hsz, hsz, -hsz);
nuclear@15 322 glNormal3f(-1, 0, 0);
nuclear@15 323 glVertex3f(-hsz, -hsz, -hsz);
nuclear@15 324 glVertex3f(-hsz, -hsz, hsz);
nuclear@15 325 glVertex3f(-hsz, hsz, hsz);
nuclear@15 326 glVertex3f(-hsz, hsz, -hsz);
nuclear@15 327 glNormal3f(0, 1, 0);
nuclear@15 328 glVertex3f(-hsz, hsz, hsz);
nuclear@15 329 glVertex3f(hsz, hsz, hsz);
nuclear@15 330 glVertex3f(hsz, hsz, -hsz);
nuclear@15 331 glVertex3f(-hsz, hsz, -hsz);
nuclear@15 332 glNormal3f(0, -1, 0);
nuclear@15 333 glVertex3f(-hsz, -hsz, -hsz);
nuclear@15 334 glVertex3f(hsz, -hsz, -hsz);
nuclear@15 335 glVertex3f(hsz, -hsz, hsz);
nuclear@15 336 glVertex3f(-hsz, -hsz, hsz);
nuclear@15 337 glEnd();
nuclear@15 338 }
nuclear@15 339
nuclear@15 340 static void draw_pyramid(float basesz, float height)
nuclear@16 341 {
nuclear@16 342 float hsz = basesz / 2.0;
nuclear@16 343 float theta = atan(hsz / height);
nuclear@16 344 float nx = cos(theta);
nuclear@16 345 float ny = sin(theta);
nuclear@16 346
nuclear@15 347 glBegin(GL_TRIANGLES);
nuclear@15 348 glNormal3f(0, ny, nx);
nuclear@15 349 glVertex3f(-hsz, 0, hsz);
nuclear@15 350 glVertex3f(hsz, 0, hsz);
nuclear@15 351 glVertex3f(0, height, 0);
nuclear@15 352 glNormal3f(nx, ny, 0);
nuclear@15 353 glVertex3f(hsz, 0, hsz);
nuclear@15 354 glVertex3f(hsz, 0, -hsz);
nuclear@15 355 glVertex3f(0, height, 0);
nuclear@15 356 glNormal3f(0, ny, -nx);
nuclear@15 357 glVertex3f(hsz, 0, -hsz);
nuclear@15 358 glVertex3f(-hsz, 0, -hsz);
nuclear@15 359 glVertex3f(0, height, 0);
nuclear@15 360 glNormal3f(-nx, ny, 0);
nuclear@15 361 glVertex3f(-hsz, 0, -hsz);
nuclear@15 362 glVertex3f(-hsz, 0, hsz);
nuclear@15 363 glVertex3f(0, height, 0);
nuclear@15 364 glEnd();
nuclear@16 365 }