rev |
line source |
nuclear@2
|
1 #include <stdio.h>
|
nuclear@2
|
2 #include <assert.h>
|
nuclear@2
|
3 #include <algorithm>
|
nuclear@2
|
4 #include "opengl.h"
|
nuclear@2
|
5 #include "game.h"
|
nuclear@2
|
6 #include "goatvr.h"
|
nuclear@3
|
7 #include "teapot.h"
|
nuclear@2
|
8
|
nuclear@2
|
9 static void draw_scene();
|
nuclear@2
|
10 static void toggle_hmd_fullscr();
|
nuclear@2
|
11 static void create_rtarg(int x, int y);
|
nuclear@2
|
12 static int next_pow2(int x);
|
nuclear@2
|
13
|
nuclear@2
|
14 static int win_width, win_height;
|
nuclear@2
|
15 static unsigned int fb_tex;
|
nuclear@2
|
16 static unsigned int fbo, fb_depth;
|
nuclear@2
|
17 static int fb_xsz, fb_ysz;
|
nuclear@2
|
18 static int fb_tex_xsz, fb_tex_ysz;
|
nuclear@2
|
19
|
nuclear@2
|
20 bool game_init()
|
nuclear@2
|
21 {
|
nuclear@2
|
22 init_opengl();
|
nuclear@2
|
23
|
nuclear@2
|
24 if(vr_init() == -1) {
|
nuclear@2
|
25 return false;
|
nuclear@2
|
26 }
|
nuclear@2
|
27
|
nuclear@2
|
28 glEnable(GL_DEPTH_TEST);
|
nuclear@2
|
29 glEnable(GL_CULL_FACE);
|
nuclear@3
|
30 glEnable(GL_LIGHTING);
|
nuclear@2
|
31
|
nuclear@2
|
32 return true;
|
nuclear@2
|
33 }
|
nuclear@2
|
34
|
nuclear@2
|
35 void game_cleanup()
|
nuclear@2
|
36 {
|
nuclear@2
|
37 vr_shutdown();
|
nuclear@2
|
38 }
|
nuclear@2
|
39
|
nuclear@2
|
40 void game_update(long tm)
|
nuclear@2
|
41 {
|
nuclear@2
|
42 }
|
nuclear@2
|
43
|
nuclear@2
|
44 void game_display()
|
nuclear@2
|
45 {
|
nuclear@2
|
46 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
nuclear@2
|
47 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
nuclear@2
|
48
|
nuclear@2
|
49 for(int i=0; i<2; i++) {
|
nuclear@2
|
50 glViewport(i == 0 ? 0 : fb_xsz / 2, 0, fb_xsz / 2, fb_ysz);
|
nuclear@2
|
51 vr_begin(i);
|
nuclear@2
|
52
|
nuclear@2
|
53 float proj[16];
|
nuclear@2
|
54 if(vr_proj_matrix(i, 0.5, 500.0, proj)) {
|
nuclear@2
|
55 glMatrixMode(GL_PROJECTION);
|
nuclear@2
|
56 glLoadMatrixf(proj);
|
nuclear@2
|
57 }
|
nuclear@2
|
58
|
nuclear@2
|
59 glMatrixMode(GL_MODELVIEW);
|
nuclear@2
|
60
|
nuclear@2
|
61 float view[16];
|
nuclear@2
|
62 vr_view_matrix(i, view);
|
nuclear@2
|
63 glLoadMatrixf(view);
|
nuclear@2
|
64 /* move the camera to the eye level of the user */
|
nuclear@2
|
65 glTranslatef(0, -vr_getf_def(VR_EYE_HEIGHT, 1.65), 0);
|
nuclear@2
|
66
|
nuclear@2
|
67 draw_scene();
|
nuclear@2
|
68
|
nuclear@2
|
69 vr_end();
|
nuclear@2
|
70 }
|
nuclear@2
|
71
|
nuclear@2
|
72 glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
nuclear@2
|
73 glViewport(0, 0, win_width, win_height);
|
nuclear@2
|
74
|
nuclear@2
|
75 vr_swap_buffers();
|
nuclear@2
|
76 assert(glGetError() == GL_NO_ERROR);
|
nuclear@2
|
77 }
|
nuclear@2
|
78
|
nuclear@2
|
79 void game_reshape(int x, int y)
|
nuclear@2
|
80 {
|
nuclear@2
|
81 win_width = x;
|
nuclear@2
|
82 win_height = y;
|
nuclear@2
|
83
|
nuclear@2
|
84 create_rtarg(vr_geti_def(VR_RENDER_XRES, x), vr_geti_def(VR_RENDER_YRES, y));
|
nuclear@2
|
85 vr_output_texture(fb_tex, 0, 0, (float)fb_xsz / (float)fb_tex_xsz, (float)fb_ysz / (float)fb_tex_ysz);
|
nuclear@2
|
86
|
nuclear@2
|
87 /* these might be overriden in VR mode (see game_display) */
|
nuclear@2
|
88 glViewport(0, 0, x, y);
|
nuclear@2
|
89 glMatrixMode(GL_PROJECTION);
|
nuclear@2
|
90 glLoadIdentity();
|
nuclear@2
|
91 gluPerspective(50.0, (float)x / (float)y, 0.5, 500.0);
|
nuclear@2
|
92 }
|
nuclear@2
|
93
|
nuclear@2
|
94 void game_keyboard(int key, bool pressed)
|
nuclear@2
|
95 {
|
nuclear@2
|
96 if(pressed) {
|
nuclear@2
|
97 switch(key) {
|
nuclear@2
|
98 case 27:
|
nuclear@2
|
99 exit_game();
|
nuclear@2
|
100 break;
|
nuclear@2
|
101
|
nuclear@2
|
102 case 'f':
|
nuclear@2
|
103 toggle_hmd_fullscr();
|
nuclear@2
|
104 break;
|
nuclear@2
|
105
|
nuclear@2
|
106 case 'r':
|
nuclear@2
|
107 vr_recenter();
|
nuclear@2
|
108 break;
|
nuclear@2
|
109
|
nuclear@2
|
110 default:
|
nuclear@2
|
111 break;
|
nuclear@2
|
112 }
|
nuclear@2
|
113 }
|
nuclear@2
|
114 }
|
nuclear@2
|
115
|
nuclear@2
|
116 void game_mouse_button(int bn, bool state, int x, int y)
|
nuclear@2
|
117 {
|
nuclear@2
|
118 }
|
nuclear@2
|
119
|
nuclear@2
|
120 void game_mouse_motion(int x, int y)
|
nuclear@2
|
121 {
|
nuclear@2
|
122 }
|
nuclear@2
|
123
|
nuclear@3
|
124 static void material(float r, float g, float b, float roughness)
|
nuclear@3
|
125 {
|
nuclear@3
|
126 float gloss = 1.0 - roughness;
|
nuclear@3
|
127 float diffuse[] = {r * roughness, g * roughness, b * roughness, 1.0};
|
nuclear@3
|
128 float specular[] = {gloss, gloss, gloss, 1.0};
|
nuclear@3
|
129 float shin = gloss * 128.0;
|
nuclear@3
|
130
|
nuclear@3
|
131 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, diffuse);
|
nuclear@3
|
132 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
|
nuclear@3
|
133 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shin);
|
nuclear@3
|
134 }
|
nuclear@3
|
135
|
nuclear@2
|
136 static void draw_scene()
|
nuclear@2
|
137 {
|
nuclear@3
|
138 float lpos[][4] = {
|
nuclear@3
|
139 {-0.7, 0.7, 1, 0},
|
nuclear@3
|
140 {1, 0, 1, 0}
|
nuclear@3
|
141 };
|
nuclear@3
|
142 float lcol[][4] = {
|
nuclear@3
|
143 {0.9, 0.7, 0.6, 1},
|
nuclear@3
|
144 {0.3, 0.4, 0.75, 1}
|
nuclear@3
|
145 };
|
nuclear@3
|
146 for(int i=0; i<2; i++) {
|
nuclear@3
|
147 glEnable(GL_LIGHT0 + i);
|
nuclear@3
|
148 glLightfv(GL_LIGHT0 + i, GL_POSITION, lpos[i]);
|
nuclear@3
|
149 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, lcol[i]);
|
nuclear@3
|
150 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, lcol[i]);
|
nuclear@3
|
151 }
|
nuclear@3
|
152
|
nuclear@3
|
153 glMatrixMode(GL_MODELVIEW);
|
nuclear@3
|
154
|
nuclear@3
|
155 material(1, 1, 1, 1);
|
nuclear@3
|
156 glBegin(GL_QUADS);
|
nuclear@3
|
157 glNormal3f(0, 1, 0);
|
nuclear@3
|
158 glVertex3f(-10, 0, 10);
|
nuclear@3
|
159 glVertex3f(10, 0, 10);
|
nuclear@3
|
160 glVertex3f(10, 0, -10);
|
nuclear@3
|
161 glVertex3f(-10, 0, -10);
|
nuclear@3
|
162 glEnd();
|
nuclear@3
|
163
|
nuclear@3
|
164 material(1, 1, 1, 0.4);
|
nuclear@3
|
165 glPushMatrix();
|
nuclear@3
|
166 glTranslatef(0, 1.3, -10);
|
nuclear@3
|
167 glFrontFace(GL_CW);
|
nuclear@3
|
168 bezier_teapot(2.0);
|
nuclear@3
|
169 glFrontFace(GL_CCW);
|
nuclear@3
|
170 glPopMatrix();
|
nuclear@2
|
171 }
|
nuclear@2
|
172
|
nuclear@2
|
173 static void toggle_hmd_fullscr()
|
nuclear@2
|
174 {
|
nuclear@2
|
175 static bool fullscr;
|
nuclear@2
|
176 static int prev_x, prev_y;
|
nuclear@2
|
177 //static int prev_xsz, prev_ysz;
|
nuclear@2
|
178
|
nuclear@2
|
179 fullscr = !fullscr;
|
nuclear@2
|
180 if(fullscr) {
|
nuclear@2
|
181 /* entering fullscreen on the HMD */
|
nuclear@2
|
182 int xoffs = vr_geti_def(VR_WIN_XOFFS, -1);
|
nuclear@2
|
183 int yoffs = vr_geti_def(VR_WIN_YOFFS, -1);
|
nuclear@2
|
184 if(xoffs != -1) {
|
nuclear@2
|
185 get_window_pos(&prev_x, &prev_y);
|
nuclear@2
|
186 move_window(xoffs, yoffs);
|
nuclear@2
|
187 }
|
nuclear@2
|
188
|
nuclear@2
|
189 int xsz = vr_geti_def(VR_DISPLAY_WIDTH, -1);
|
nuclear@2
|
190 int ysz = vr_geti_def(VR_DISPLAY_HEIGHT, -1);
|
nuclear@2
|
191 if(xsz != -1) {
|
nuclear@2
|
192 //prev_xsz = win_width;
|
nuclear@2
|
193 //prev_ysz = win_height;
|
nuclear@2
|
194 resize_window(xsz, ysz);
|
nuclear@2
|
195 }
|
nuclear@2
|
196 enter_fullscreen();
|
nuclear@2
|
197
|
nuclear@2
|
198 } else {
|
nuclear@2
|
199 /* leaving fullscreen */
|
nuclear@2
|
200 leave_fullscreen();
|
nuclear@2
|
201 /*move_window(prev_x, prev_y);
|
nuclear@2
|
202 resize_window(prev_xsz, prev_ysz);*/
|
nuclear@2
|
203 }
|
nuclear@2
|
204 }
|
nuclear@2
|
205
|
nuclear@2
|
206 static void create_rtarg(int x, int y)
|
nuclear@2
|
207 {
|
nuclear@2
|
208 if(x == fb_xsz && y == fb_ysz) {
|
nuclear@2
|
209 return; // nothing changed
|
nuclear@2
|
210 }
|
nuclear@2
|
211
|
nuclear@2
|
212 fb_xsz = x;
|
nuclear@2
|
213 fb_ysz = y;
|
nuclear@2
|
214 fb_tex_xsz = next_pow2(fb_xsz);
|
nuclear@2
|
215 fb_tex_ysz = next_pow2(fb_ysz);
|
nuclear@2
|
216
|
nuclear@2
|
217 if(!fbo) {
|
nuclear@2
|
218 glGenFramebuffers(1, &fbo);
|
nuclear@2
|
219
|
nuclear@2
|
220 glGenTextures(1, &fb_tex);
|
nuclear@2
|
221 glBindTexture(GL_TEXTURE_2D, fb_tex);
|
nuclear@2
|
222 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
nuclear@2
|
223 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
nuclear@2
|
224
|
nuclear@2
|
225 glGenRenderbuffers(1, &fb_depth);
|
nuclear@2
|
226 }
|
nuclear@2
|
227
|
nuclear@2
|
228 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
nuclear@2
|
229
|
nuclear@2
|
230 glBindTexture(GL_TEXTURE_2D, fb_tex);
|
nuclear@2
|
231 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fb_tex_xsz, fb_tex_ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
|
nuclear@2
|
232 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb_tex, 0);
|
nuclear@2
|
233
|
nuclear@2
|
234 glBindRenderbuffer(GL_RENDERBUFFER, fb_depth);
|
nuclear@2
|
235 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, fb_tex_xsz, fb_tex_ysz);
|
nuclear@2
|
236 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fb_depth);
|
nuclear@2
|
237
|
nuclear@2
|
238 assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
|
nuclear@2
|
239 glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
nuclear@2
|
240 }
|
nuclear@2
|
241
|
nuclear@2
|
242 static int next_pow2(int x)
|
nuclear@2
|
243 {
|
nuclear@2
|
244 x -= 1;
|
nuclear@2
|
245 x |= x >> 1;
|
nuclear@2
|
246 x |= x >> 2;
|
nuclear@2
|
247 x |= x >> 4;
|
nuclear@2
|
248 x |= x >> 8;
|
nuclear@2
|
249 x |= x >> 16;
|
nuclear@2
|
250 return x + 1;
|
nuclear@2
|
251 }
|