vrheights

view src/game.cc @ 4:690ef7fa791f

foo
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 26 Sep 2014 13:19:22 +0300
parents 316ec8250af2
children 053a52f0cb64
line source
1 #include <stdio.h>
2 #include <assert.h>
3 #include <algorithm>
4 #include <vmath/vmath.h>
5 #include "opengl.h"
6 #include "game.h"
7 #include "goatvr.h"
8 #include "teapot.h"
10 static void draw_scene();
11 static void material(float r, float g, float b, float roughness);
12 static void toggle_hmd_fullscr();
13 static void create_rtarg(int x, int y);
14 static int next_pow2(int x);
16 static int win_width, win_height;
17 static unsigned int fb_tex;
18 static unsigned int fbo, fb_depth;
19 static int fb_xsz, fb_ysz;
20 static int fb_tex_xsz, fb_tex_ysz;
22 static float cam_theta, cam_phi;
23 static Vector3 cam_pos;
24 static bool keystate[256];
26 bool game_init()
27 {
28 init_opengl();
30 if(vr_init() == -1) {
31 return false;
32 }
34 glEnable(GL_DEPTH_TEST);
35 glEnable(GL_CULL_FACE);
36 glEnable(GL_LIGHTING);
38 return true;
39 }
41 void game_cleanup()
42 {
43 vr_shutdown();
44 }
46 void game_update(long tm)
47 {
48 static long prev_upd;
49 float dt = (tm - prev_upd) / 1000.0;
50 prev_upd = tm;
52 float offs = dt * 1.0;
53 Vector3 dir;
55 if(keystate['d'] || keystate['D']) {
56 dir += Vector3(offs, 0, 0);
57 }
58 if(keystate['a'] || keystate['A']) {
59 dir += Vector3(-offs, 0, 0);
60 }
61 if(keystate['w'] || keystate['W']) {
62 dir += Vector3(0, 0, -offs);
63 }
64 if(keystate['s'] || keystate['S']) {
65 dir += Vector3(0, 0, offs);
66 }
68 cam_pos.x += dir.x * cos(cam_theta) - dir.y * sin(cam_theta);
69 cam_pos.z += dir.x * sin(cam_theta) + dir.y * cos(cam_theta);
70 }
72 void game_display()
73 {
74 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
75 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
77 for(int i=0; i<2; i++) {
78 glViewport(i == 0 ? 0 : fb_xsz / 2, 0, fb_xsz / 2, fb_ysz);
79 vr_begin(i);
81 float proj[16];
82 if(vr_proj_matrix(i, 0.5, 500.0, proj)) {
83 glMatrixMode(GL_PROJECTION);
84 glLoadMatrixf(proj);
85 }
87 glMatrixMode(GL_MODELVIEW);
89 float view[16];
90 vr_view_matrix(i, view);
91 glLoadMatrixf(view);
92 glRotatef(cam_phi, 1, 0, 0);
93 glRotatef(cam_theta, 0, 1, 0);
94 /* move the camera to the eye level of the user */
95 glTranslatef(0, -vr_getf_def(VR_EYE_HEIGHT, 1.65), 0);
96 glTranslatef(-cam_pos.x, -cam_pos.y, -cam_pos.z);
98 draw_scene();
100 vr_end();
101 }
103 glBindFramebuffer(GL_FRAMEBUFFER, 0);
104 glViewport(0, 0, win_width, win_height);
106 vr_swap_buffers();
107 assert(glGetError() == GL_NO_ERROR);
108 }
110 void game_reshape(int x, int y)
111 {
112 win_width = x;
113 win_height = y;
115 create_rtarg(vr_geti_def(VR_RENDER_XRES, x), vr_geti_def(VR_RENDER_YRES, y));
116 vr_output_texture(fb_tex, 0, 0, (float)fb_xsz / (float)fb_tex_xsz, (float)fb_ysz / (float)fb_tex_ysz);
118 /* these might be overriden in VR mode (see game_display) */
119 glViewport(0, 0, x, y);
120 glMatrixMode(GL_PROJECTION);
121 glLoadIdentity();
122 gluPerspective(50.0, (float)x / (float)y, 0.5, 500.0);
123 }
125 void game_keyboard(int key, bool pressed)
126 {
127 if(pressed) {
128 switch(key) {
129 case 27:
130 exit_game();
131 break;
133 case 'f':
134 toggle_hmd_fullscr();
135 break;
137 case 'r':
138 vr_recenter();
139 break;
141 default:
142 break;
143 }
144 }
146 if(key < 256) {
147 keystate[key] = pressed;
148 }
149 }
152 static int prev_x, prev_y;
153 static bool bnstate[32];
155 void game_mouse_button(int bn, bool state, int x, int y)
156 {
157 bnstate[bn] = state;
158 prev_x = x;
159 prev_y = y;
160 }
162 void game_mouse_motion(int x, int y)
163 {
164 int dx = x - prev_x;
165 int dy = y - prev_y;
166 prev_x = x;
167 prev_y = y;
169 if(!dx && !dy) {
170 return;
171 }
172 if(bnstate[0]) {
173 cam_theta += dx * 0.5;
174 cam_phi += dy * 0.5;
176 if(cam_phi < -90) cam_phi = -90;
177 if(cam_phi > 90) cam_phi = 90;
178 }
179 }
181 static void draw_scene()
182 {
183 float lpos[][4] = {
184 {-0.7, 0.7, 1, 0},
185 {1, 0, 1, 0}
186 };
187 float lcol[][4] = {
188 {0.9, 0.7, 0.6, 1},
189 {0.3, 0.4, 0.75, 1}
190 };
191 for(int i=0; i<2; i++) {
192 glEnable(GL_LIGHT0 + i);
193 glLightfv(GL_LIGHT0 + i, GL_POSITION, lpos[i]);
194 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, lcol[i]);
195 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, lcol[i]);
196 }
198 glMatrixMode(GL_MODELVIEW);
200 material(1, 1, 1, 1);
201 glBegin(GL_QUADS);
202 glNormal3f(0, 1, 0);
203 glVertex3f(-10, 0, 10);
204 glVertex3f(10, 0, 10);
205 glVertex3f(10, 0, -10);
206 glVertex3f(-10, 0, -10);
207 glEnd();
209 material(1, 1, 1, 0.4);
210 glPushMatrix();
211 glTranslatef(0, 1.3, -10);
212 glFrontFace(GL_CW);
213 bezier_teapot(2.0);
214 glFrontFace(GL_CCW);
215 glPopMatrix();
216 }
218 static void material(float r, float g, float b, float roughness)
219 {
220 float gloss = 1.0 - roughness;
221 float diffuse[] = {r * roughness, g * roughness, b * roughness, 1.0};
222 float specular[] = {gloss, gloss, gloss, 1.0};
223 float shin = gloss * 128.0;
225 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, diffuse);
226 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
227 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shin);
228 }
231 static void toggle_hmd_fullscr()
232 {
233 static bool fullscr;
234 static int prev_x, prev_y;
235 //static int prev_xsz, prev_ysz;
237 fullscr = !fullscr;
238 if(fullscr) {
239 /* entering fullscreen on the HMD */
240 int xoffs = vr_geti_def(VR_WIN_XOFFS, -1);
241 int yoffs = vr_geti_def(VR_WIN_YOFFS, -1);
242 if(xoffs != -1) {
243 get_window_pos(&prev_x, &prev_y);
244 move_window(xoffs, yoffs);
245 }
247 int xsz = vr_geti_def(VR_DISPLAY_WIDTH, -1);
248 int ysz = vr_geti_def(VR_DISPLAY_HEIGHT, -1);
249 if(xsz != -1) {
250 //prev_xsz = win_width;
251 //prev_ysz = win_height;
252 resize_window(xsz, ysz);
253 }
254 enter_fullscreen();
256 } else {
257 /* leaving fullscreen */
258 leave_fullscreen();
259 /*move_window(prev_x, prev_y);
260 resize_window(prev_xsz, prev_ysz);*/
261 }
262 }
264 static void create_rtarg(int x, int y)
265 {
266 if(x == fb_xsz && y == fb_ysz) {
267 return; // nothing changed
268 }
270 fb_xsz = x;
271 fb_ysz = y;
272 fb_tex_xsz = next_pow2(fb_xsz);
273 fb_tex_ysz = next_pow2(fb_ysz);
275 if(!fbo) {
276 glGenFramebuffers(1, &fbo);
278 glGenTextures(1, &fb_tex);
279 glBindTexture(GL_TEXTURE_2D, fb_tex);
280 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
281 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
283 glGenRenderbuffers(1, &fb_depth);
284 }
286 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
288 glBindTexture(GL_TEXTURE_2D, fb_tex);
289 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fb_tex_xsz, fb_tex_ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
290 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb_tex, 0);
292 glBindRenderbuffer(GL_RENDERBUFFER, fb_depth);
293 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, fb_tex_xsz, fb_tex_ysz);
294 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fb_depth);
296 assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
297 glBindFramebuffer(GL_FRAMEBUFFER, 0);
298 }
300 static int next_pow2(int x)
301 {
302 x -= 1;
303 x |= x >> 1;
304 x |= x >> 2;
305 x |= x >> 4;
306 x |= x >> 8;
307 x |= x >> 16;
308 return x + 1;
309 }