conworlds

annotate src/game.cc @ 12:778ed91cb7fd

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