rev |
line source |
nuclear@0
|
1 #include <stdio.h>
|
nuclear@0
|
2 #include <assert.h>
|
nuclear@0
|
3 #include <GL/glew.h>
|
nuclear@0
|
4 #include <openvr.h>
|
nuclear@0
|
5 #include <gmath/gmath.h>
|
nuclear@0
|
6 #include "app.h"
|
nuclear@0
|
7
|
nuclear@0
|
8 using namespace vr; // OpenVR namespace
|
nuclear@0
|
9
|
nuclear@0
|
10 static void draw_scene();
|
nuclear@0
|
11 static void draw_box(float xsz, float ysz, float zsz, float norm_sign);
|
nuclear@0
|
12 static Mat4 openvr_matrix4(const HmdMatrix44_t &mat);
|
nuclear@0
|
13 static Mat4 openvr_matrix(const HmdMatrix34_t &mat);
|
nuclear@0
|
14 static VRTextureBounds_t openvr_tex_bounds(float umin, float vmin, float umax, float vmax);
|
nuclear@0
|
15 static void update_rtarg(int width, int height);
|
nuclear@0
|
16 static unsigned int next_pow2(unsigned int x);
|
nuclear@0
|
17 static unsigned int gen_chess_tex(float r0, float g0, float b0, float r1, float g1, float b1);
|
nuclear@0
|
18
|
nuclear@0
|
19 static int win_width, win_height;
|
nuclear@0
|
20
|
nuclear@0
|
21 static unsigned int fbo, fb_tex, fb_depth;
|
nuclear@0
|
22 static int fb_width, fb_height;
|
nuclear@0
|
23 static int fb_tex_width, fb_tex_height;
|
nuclear@0
|
24
|
nuclear@0
|
25 static unsigned int chess_tex;
|
nuclear@0
|
26
|
nuclear@0
|
27 // openvr stuff
|
nuclear@0
|
28 static IVRSystem *vrsys;
|
nuclear@0
|
29 static IVRCompositor *vrcomp;
|
nuclear@0
|
30 static bool vrdev_state[k_unMaxTrackedDeviceCount];
|
nuclear@0
|
31 static TrackedDevicePose_t vrdev_pose[k_unMaxTrackedDeviceCount];
|
nuclear@0
|
32 static Mat4 eye_matrix[2];
|
nuclear@0
|
33 static Mat4 proj_matrix[2];
|
nuclear@0
|
34 static Texture_t vrtex = {0, API_OpenGL, ColorSpace_Linear};
|
nuclear@0
|
35 static VRTextureBounds_t vrtex_bounds[2];
|
nuclear@0
|
36
|
nuclear@0
|
37 bool app_init()
|
nuclear@0
|
38 {
|
nuclear@0
|
39 glewInit();
|
nuclear@0
|
40
|
nuclear@0
|
41 glEnable(GL_DEPTH_TEST);
|
nuclear@0
|
42 glEnable(GL_CULL_FACE);
|
nuclear@0
|
43 glEnable(GL_LIGHTING);
|
nuclear@0
|
44 glEnable(GL_LIGHT0);
|
nuclear@0
|
45 glEnable(GL_LIGHT1);
|
nuclear@0
|
46 glEnable(GL_NORMALIZE);
|
nuclear@0
|
47
|
nuclear@0
|
48 glClearColor(0.1, 0.1, 0.1, 1);
|
nuclear@0
|
49
|
nuclear@0
|
50 chess_tex = gen_chess_tex(1.0, 0.7, 0.4, 0.4, 0.7, 1.0);
|
nuclear@0
|
51
|
nuclear@0
|
52 // Initialize OpenVR
|
nuclear@0
|
53 EVRInitError vrerr;
|
nuclear@0
|
54 if(!(vrsys = VR_Init(&vrerr, VRApplication_Scene))) {
|
nuclear@0
|
55 fprintf(stderr, "failed to initialize OpenVR: %s\n",
|
nuclear@0
|
56 VR_GetVRInitErrorAsEnglishDescription(vrerr));
|
nuclear@0
|
57 return false;
|
nuclear@0
|
58 }
|
nuclear@0
|
59 if(!(vrcomp = VRCompositor())) {
|
nuclear@0
|
60 fprintf(stderr, "failed to initialize OpenVR compositor\n");
|
nuclear@0
|
61 return false;
|
nuclear@0
|
62 }
|
nuclear@0
|
63
|
nuclear@0
|
64 uint32_t xsz, ysz;
|
nuclear@0
|
65 vrsys->GetRecommendedRenderTargetSize(&xsz, &ysz);
|
nuclear@0
|
66 fb_width = xsz * 2;
|
nuclear@0
|
67 fb_height = ysz;
|
nuclear@0
|
68 update_rtarg(fb_width, fb_height); // create render target
|
nuclear@0
|
69
|
nuclear@0
|
70 for(int i=0; i<2; i++) {
|
nuclear@0
|
71 EVREye eye = i == 0 ? Eye_Left : Eye_Right;
|
nuclear@0
|
72
|
nuclear@0
|
73 // projection matrix for each eye
|
nuclear@0
|
74 proj_matrix[i] = openvr_matrix4(vrsys->GetProjectionMatrix(eye, 0.5, 500.0, API_OpenGL));
|
nuclear@0
|
75 // eye (relative to head) matrix
|
nuclear@0
|
76 eye_matrix[i] = openvr_matrix(vrsys->GetEyeToHeadTransform(eye));
|
nuclear@0
|
77 }
|
nuclear@0
|
78
|
nuclear@0
|
79 // XXX this doesn't seem to work correctly for some reason
|
nuclear@0
|
80 //vrcomp->ShowMirrorWindow();
|
nuclear@0
|
81
|
nuclear@0
|
82 assert(glGetError() == GL_NO_ERROR);
|
nuclear@0
|
83 return true;
|
nuclear@0
|
84 }
|
nuclear@0
|
85
|
nuclear@0
|
86 void app_shutdown()
|
nuclear@0
|
87 {
|
nuclear@0
|
88 // if we call VR_Shutdown while a frame is pending, we'll crash
|
nuclear@0
|
89 vrcomp->ClearLastSubmittedFrame();
|
nuclear@0
|
90 VR_Shutdown();
|
nuclear@0
|
91 }
|
nuclear@0
|
92
|
nuclear@0
|
93 static void update()
|
nuclear@0
|
94 {
|
nuclear@0
|
95 // process OpenVR events (TODO: I think there are more events to handle)
|
nuclear@0
|
96 VREvent_t ev;
|
nuclear@0
|
97 while(vrsys->PollNextEvent(&ev, sizeof ev)) {
|
nuclear@0
|
98 switch(ev.eventType) {
|
nuclear@0
|
99 case VREvent_TrackedDeviceActivated:
|
nuclear@0
|
100 printf("Device %u activated\n", ev.trackedDeviceIndex);
|
nuclear@0
|
101 break;
|
nuclear@0
|
102
|
nuclear@0
|
103 case VREvent_TrackedDeviceDeactivated:
|
nuclear@0
|
104 printf("Device %u lost\n", ev.trackedDeviceIndex);
|
nuclear@0
|
105 break;
|
nuclear@0
|
106
|
nuclear@0
|
107 case VREvent_TrackedDeviceUpdated:
|
nuclear@0
|
108 printf("Device %u updated(?)\n", ev.trackedDeviceIndex);
|
nuclear@0
|
109 break;
|
nuclear@0
|
110 }
|
nuclear@0
|
111 }
|
nuclear@0
|
112
|
nuclear@0
|
113 // TODO implement controllers
|
nuclear@0
|
114 for(int i=0; i<k_unMaxTrackedDeviceCount; i++) {
|
nuclear@0
|
115 VRControllerState_t st;
|
nuclear@0
|
116 if(vrsys->GetControllerState(i, &st)) {
|
nuclear@0
|
117 // XXX ?
|
nuclear@0
|
118 vrdev_state[i] = st.ulButtonPressed == 0;
|
nuclear@0
|
119 }
|
nuclear@0
|
120 }
|
nuclear@0
|
121
|
nuclear@0
|
122 // this will probably block at some point... investigate further
|
nuclear@0
|
123 vrcomp->WaitGetPoses(vrdev_pose, k_unMaxTrackedDeviceCount, 0, 0);
|
nuclear@0
|
124 }
|
nuclear@0
|
125
|
nuclear@0
|
126 void app_draw()
|
nuclear@0
|
127 {
|
nuclear@0
|
128 update();
|
nuclear@0
|
129
|
nuclear@0
|
130 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
nuclear@0
|
131 glClearColor(0, 0, 0, 1);
|
nuclear@0
|
132 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
nuclear@0
|
133
|
nuclear@0
|
134 for(int i=0; i<2; i++) {
|
nuclear@0
|
135 EVREye eye = i == 0 ? Eye_Left : Eye_Right;
|
nuclear@0
|
136
|
nuclear@0
|
137 glViewport(i == 0 ? 0 : fb_width / 2, 0, fb_width / 2, fb_height);
|
nuclear@0
|
138
|
nuclear@0
|
139 glMatrixMode(GL_PROJECTION);
|
nuclear@0
|
140 glLoadMatrixf(proj_matrix[i][0]);
|
nuclear@0
|
141
|
nuclear@0
|
142 Mat4 hmd_mat = openvr_matrix(vrdev_pose[k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking);
|
nuclear@0
|
143 Mat4 view_mat = inverse(eye_matrix[i] * hmd_mat);
|
nuclear@0
|
144
|
nuclear@0
|
145 glMatrixMode(GL_MODELVIEW);
|
nuclear@0
|
146 glLoadMatrixf(view_mat[0]);
|
nuclear@0
|
147
|
nuclear@0
|
148 draw_scene();
|
nuclear@0
|
149 vrcomp->Submit(eye, &vrtex, vrtex_bounds + i);
|
nuclear@0
|
150 }
|
nuclear@0
|
151 /* this is supposed to tell the compositor to get on with showing the frame without waiting for
|
nuclear@0
|
152 * the next WaitGetPoses call.
|
nuclear@0
|
153 */
|
nuclear@0
|
154 vrcomp->PostPresentHandoff();
|
nuclear@0
|
155
|
nuclear@0
|
156 glUseProgram(0);
|
nuclear@0
|
157
|
nuclear@0
|
158 // render window output
|
nuclear@0
|
159 glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
nuclear@0
|
160 glViewport(0, 0, win_width, win_height);
|
nuclear@0
|
161
|
nuclear@0
|
162 glMatrixMode(GL_PROJECTION);
|
nuclear@0
|
163 glLoadIdentity();
|
nuclear@0
|
164 glMatrixMode(GL_MODELVIEW);
|
nuclear@0
|
165 glLoadIdentity();
|
nuclear@0
|
166
|
nuclear@0
|
167 glPushAttrib(GL_ENABLE_BIT);
|
nuclear@0
|
168 glBindTexture(GL_TEXTURE_2D, fb_tex);
|
nuclear@0
|
169 glEnable(GL_TEXTURE_2D);
|
nuclear@0
|
170 glDisable(GL_LIGHTING);
|
nuclear@0
|
171 glDisable(GL_DEPTH_TEST);
|
nuclear@0
|
172
|
nuclear@0
|
173 glBegin(GL_QUADS);
|
nuclear@0
|
174 float umax = (float)fb_width / fb_tex_width;
|
nuclear@0
|
175 float vmax = (float)fb_height / fb_tex_height;
|
nuclear@0
|
176 glTexCoord2f(0, 0); glVertex2f(-1, -1);
|
nuclear@0
|
177 glTexCoord2f(umax, 0); glVertex2f(1, -1);
|
nuclear@0
|
178 glTexCoord2f(umax, vmax); glVertex2f(1, 1);
|
nuclear@0
|
179 glTexCoord2f(0, vmax); glVertex2f(-1, 1);
|
nuclear@0
|
180 glEnd();
|
nuclear@0
|
181
|
nuclear@0
|
182 glPopAttrib();
|
nuclear@0
|
183
|
nuclear@0
|
184 app_swap_buffers();
|
nuclear@0
|
185 }
|
nuclear@0
|
186
|
nuclear@0
|
187 void app_reshape(int x, int y)
|
nuclear@0
|
188 {
|
nuclear@0
|
189 win_width = x;
|
nuclear@0
|
190 win_height = y;
|
nuclear@0
|
191 glViewport(0, 0, x, y);
|
nuclear@0
|
192
|
nuclear@0
|
193 glMatrixMode(GL_PROJECTION);
|
nuclear@0
|
194 glLoadIdentity();
|
nuclear@0
|
195 gluPerspective(50, (float)x / (float)y, 0.5, 500.0);
|
nuclear@0
|
196 }
|
nuclear@0
|
197
|
nuclear@0
|
198 static void draw_scene(void)
|
nuclear@0
|
199 {
|
nuclear@0
|
200 float grey[] = {0.8, 0.8, 0.8, 1};
|
nuclear@0
|
201 float col[] = {0, 0, 0, 1};
|
nuclear@0
|
202 float lpos[][4] = {
|
nuclear@0
|
203 {-8, 2, 10, 1},
|
nuclear@0
|
204 {0, 15, 0, 1}
|
nuclear@0
|
205 };
|
nuclear@0
|
206 float lcol[][4] = {
|
nuclear@0
|
207 {0.8, 0.8, 0.8, 1},
|
nuclear@0
|
208 {0.4, 0.3, 0.3, 1}
|
nuclear@0
|
209 };
|
nuclear@0
|
210
|
nuclear@0
|
211 for(int i=0; i<2; i++) {
|
nuclear@0
|
212 glLightfv(GL_LIGHT0 + i, GL_POSITION, lpos[i]);
|
nuclear@0
|
213 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, lcol[i]);
|
nuclear@0
|
214 }
|
nuclear@0
|
215
|
nuclear@0
|
216 glMatrixMode(GL_MODELVIEW);
|
nuclear@0
|
217
|
nuclear@0
|
218 glPushMatrix();
|
nuclear@0
|
219 glTranslatef(0, 10, 0);
|
nuclear@0
|
220 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, grey);
|
nuclear@0
|
221 glBindTexture(GL_TEXTURE_2D, chess_tex);
|
nuclear@0
|
222 glEnable(GL_TEXTURE_2D);
|
nuclear@0
|
223 draw_box(30, 20, 30, -1.0);
|
nuclear@0
|
224 glDisable(GL_TEXTURE_2D);
|
nuclear@0
|
225 glPopMatrix();
|
nuclear@0
|
226
|
nuclear@0
|
227 for(int i=0; i<4; i++) {
|
nuclear@0
|
228 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, grey);
|
nuclear@0
|
229 glPushMatrix();
|
nuclear@0
|
230 glTranslatef(i & 1 ? 5 : -5, 1, i & 2 ? -5 : 5);
|
nuclear@0
|
231 draw_box(0.5, 2, 0.5, 1.0);
|
nuclear@0
|
232 glPopMatrix();
|
nuclear@0
|
233
|
nuclear@0
|
234 col[0] = i & 1 ? 1.0 : 0.3;
|
nuclear@0
|
235 col[1] = i == 0 ? 1.0 : 0.3;
|
nuclear@0
|
236 col[2] = i & 2 ? 1.0 : 0.3;
|
nuclear@0
|
237 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col);
|
nuclear@0
|
238
|
nuclear@0
|
239 glPushMatrix();
|
nuclear@0
|
240 if(i & 1) {
|
nuclear@0
|
241 glTranslatef(0, 0.25, i & 2 ? 2 : -2);
|
nuclear@0
|
242 } else {
|
nuclear@0
|
243 glTranslatef(i & 2 ? 2 : -2, 0.25, 0);
|
nuclear@0
|
244 }
|
nuclear@0
|
245 draw_box(0.5, 0.5, 0.5, 1.0);
|
nuclear@0
|
246 glPopMatrix();
|
nuclear@0
|
247 }
|
nuclear@0
|
248
|
nuclear@0
|
249 col[0] = 1;
|
nuclear@0
|
250 col[1] = 1;
|
nuclear@0
|
251 col[2] = 0.4;
|
nuclear@0
|
252 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col);
|
nuclear@0
|
253 draw_box(0.05, 1.2, 6, 1.0);
|
nuclear@0
|
254 draw_box(6, 1.2, 0.05, 1.0);
|
nuclear@0
|
255 }
|
nuclear@0
|
256
|
nuclear@0
|
257 static void draw_box(float xsz, float ysz, float zsz, float norm_sign)
|
nuclear@0
|
258 {
|
nuclear@0
|
259 glMatrixMode(GL_MODELVIEW);
|
nuclear@0
|
260 glPushMatrix();
|
nuclear@0
|
261 glScalef(xsz * 0.5, ysz * 0.5, zsz * 0.5);
|
nuclear@0
|
262
|
nuclear@0
|
263 if(norm_sign < 0.0) {
|
nuclear@0
|
264 glFrontFace(GL_CW);
|
nuclear@0
|
265 }
|
nuclear@0
|
266
|
nuclear@0
|
267 glBegin(GL_QUADS);
|
nuclear@0
|
268 glNormal3f(0, 0, 1 * norm_sign);
|
nuclear@0
|
269 glTexCoord2f(0, 0); glVertex3f(-1, -1, 1);
|
nuclear@0
|
270 glTexCoord2f(1, 0); glVertex3f(1, -1, 1);
|
nuclear@0
|
271 glTexCoord2f(1, 1); glVertex3f(1, 1, 1);
|
nuclear@0
|
272 glTexCoord2f(0, 1); glVertex3f(-1, 1, 1);
|
nuclear@0
|
273 glNormal3f(1 * norm_sign, 0, 0);
|
nuclear@0
|
274 glTexCoord2f(0, 0); glVertex3f(1, -1, 1);
|
nuclear@0
|
275 glTexCoord2f(1, 0); glVertex3f(1, -1, -1);
|
nuclear@0
|
276 glTexCoord2f(1, 1); glVertex3f(1, 1, -1);
|
nuclear@0
|
277 glTexCoord2f(0, 1); glVertex3f(1, 1, 1);
|
nuclear@0
|
278 glNormal3f(0, 0, -1 * norm_sign);
|
nuclear@0
|
279 glTexCoord2f(0, 0); glVertex3f(1, -1, -1);
|
nuclear@0
|
280 glTexCoord2f(1, 0); glVertex3f(-1, -1, -1);
|
nuclear@0
|
281 glTexCoord2f(1, 1); glVertex3f(-1, 1, -1);
|
nuclear@0
|
282 glTexCoord2f(0, 1); glVertex3f(1, 1, -1);
|
nuclear@0
|
283 glNormal3f(-1 * norm_sign, 0, 0);
|
nuclear@0
|
284 glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
|
nuclear@0
|
285 glTexCoord2f(1, 0); glVertex3f(-1, -1, 1);
|
nuclear@0
|
286 glTexCoord2f(1, 1); glVertex3f(-1, 1, 1);
|
nuclear@0
|
287 glTexCoord2f(0, 1); glVertex3f(-1, 1, -1);
|
nuclear@0
|
288 glEnd();
|
nuclear@0
|
289 glBegin(GL_TRIANGLE_FAN);
|
nuclear@0
|
290 glNormal3f(0, 1 * norm_sign, 0);
|
nuclear@0
|
291 glTexCoord2f(0.5, 0.5); glVertex3f(0, 1, 0);
|
nuclear@0
|
292 glTexCoord2f(0, 0); glVertex3f(-1, 1, 1);
|
nuclear@0
|
293 glTexCoord2f(1, 0); glVertex3f(1, 1, 1);
|
nuclear@0
|
294 glTexCoord2f(1, 1); glVertex3f(1, 1, -1);
|
nuclear@0
|
295 glTexCoord2f(0, 1); glVertex3f(-1, 1, -1);
|
nuclear@0
|
296 glTexCoord2f(0, 0); glVertex3f(-1, 1, 1);
|
nuclear@0
|
297 glEnd();
|
nuclear@0
|
298 glBegin(GL_TRIANGLE_FAN);
|
nuclear@0
|
299 glNormal3f(0, -1 * norm_sign, 0);
|
nuclear@0
|
300 glTexCoord2f(0.5, 0.5); glVertex3f(0, -1, 0);
|
nuclear@0
|
301 glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
|
nuclear@0
|
302 glTexCoord2f(1, 0); glVertex3f(1, -1, -1);
|
nuclear@0
|
303 glTexCoord2f(1, 1); glVertex3f(1, -1, 1);
|
nuclear@0
|
304 glTexCoord2f(0, 1); glVertex3f(-1, -1, 1);
|
nuclear@0
|
305 glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
|
nuclear@0
|
306 glEnd();
|
nuclear@0
|
307
|
nuclear@0
|
308 glFrontFace(GL_CCW);
|
nuclear@0
|
309 glPopMatrix();
|
nuclear@0
|
310 }
|
nuclear@0
|
311
|
nuclear@0
|
312 static Mat4 openvr_matrix4(const HmdMatrix44_t &mat)
|
nuclear@0
|
313 {
|
nuclear@0
|
314 return Mat4(mat.m[0][0], mat.m[1][0], mat.m[2][0], mat.m[3][0],
|
nuclear@0
|
315 mat.m[0][1], mat.m[1][1], mat.m[2][1], mat.m[3][1],
|
nuclear@0
|
316 mat.m[0][2], mat.m[1][2], mat.m[2][2], mat.m[3][2],
|
nuclear@0
|
317 mat.m[0][3], mat.m[1][3], mat.m[2][3], mat.m[3][3]);
|
nuclear@0
|
318 }
|
nuclear@0
|
319
|
nuclear@0
|
320 static Mat4 openvr_matrix(const HmdMatrix34_t &mat)
|
nuclear@0
|
321 {
|
nuclear@0
|
322 return Mat4(mat.m[0][0], mat.m[1][0], mat.m[2][0], 0,
|
nuclear@0
|
323 mat.m[0][1], mat.m[1][1], mat.m[2][1], 0,
|
nuclear@0
|
324 mat.m[0][2], mat.m[1][2], mat.m[2][2], 0,
|
nuclear@0
|
325 mat.m[0][3], mat.m[1][3], mat.m[2][3], 1);
|
nuclear@0
|
326 }
|
nuclear@0
|
327
|
nuclear@0
|
328 static VRTextureBounds_t openvr_tex_bounds(float umin, float vmin, float umax, float vmax)
|
nuclear@0
|
329 {
|
nuclear@0
|
330 VRTextureBounds_t res;
|
nuclear@0
|
331 res.uMin = umin;
|
nuclear@0
|
332 res.uMax = umax;
|
nuclear@0
|
333 res.vMin = vmin;
|
nuclear@0
|
334 res.vMax = vmax;
|
nuclear@0
|
335 return res;
|
nuclear@0
|
336 }
|
nuclear@0
|
337
|
nuclear@0
|
338 /* update_rtarg creates (and/or resizes) the render target used to draw the two stero views */
|
nuclear@0
|
339 static void update_rtarg(int width, int height)
|
nuclear@0
|
340 {
|
nuclear@0
|
341 if(!fbo) {
|
nuclear@0
|
342 /* if fbo does not exist, then nothing does... create every opengl object */
|
nuclear@0
|
343 glGenFramebuffers(1, &fbo);
|
nuclear@0
|
344 glGenTextures(1, &fb_tex);
|
nuclear@0
|
345 glGenRenderbuffers(1, &fb_depth);
|
nuclear@0
|
346
|
nuclear@0
|
347 glBindTexture(GL_TEXTURE_2D, fb_tex);
|
nuclear@0
|
348 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
nuclear@0
|
349 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
nuclear@0
|
350 }
|
nuclear@0
|
351
|
nuclear@0
|
352 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
nuclear@0
|
353
|
nuclear@0
|
354 /* calculate the next power of two in both dimensions and use that as a texture size */
|
nuclear@0
|
355 fb_tex_width = next_pow2(width);
|
nuclear@0
|
356 fb_tex_height = next_pow2(height);
|
nuclear@0
|
357
|
nuclear@0
|
358 /* create and attach the texture that will be used as a color buffer */
|
nuclear@0
|
359 glBindTexture(GL_TEXTURE_2D, fb_tex);
|
nuclear@0
|
360 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fb_tex_width, fb_tex_height, 0,
|
nuclear@0
|
361 GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
nuclear@0
|
362 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb_tex, 0);
|
nuclear@0
|
363
|
nuclear@0
|
364 /* create and attach the renderbuffer that will serve as our z-buffer */
|
nuclear@0
|
365 glBindRenderbuffer(GL_RENDERBUFFER, fb_depth);
|
nuclear@0
|
366 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, fb_tex_width, fb_tex_height);
|
nuclear@0
|
367 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fb_depth);
|
nuclear@0
|
368
|
nuclear@0
|
369 if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
nuclear@0
|
370 fprintf(stderr, "incomplete framebuffer!\n");
|
nuclear@0
|
371 }
|
nuclear@0
|
372
|
nuclear@0
|
373 glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
nuclear@0
|
374 printf("created render target: %dx%d (texture size: %dx%d)\n", width, height, fb_tex_width, fb_tex_height);
|
nuclear@0
|
375
|
nuclear@0
|
376 /* update the OpenVR texture descriptors */
|
nuclear@0
|
377 vrtex.handle = (void*)fb_tex;
|
nuclear@0
|
378 float umax = (float)fb_width / fb_tex_width;
|
nuclear@0
|
379 float vmax = (float)fb_height / fb_tex_height;
|
nuclear@0
|
380 vrtex_bounds[0] = openvr_tex_bounds(0, 1.0 - vmax, 0.5 * umax, 1.0);
|
nuclear@0
|
381 vrtex_bounds[1] = openvr_tex_bounds(0.5 * umax, 1.0 - vmax, umax, 1.0);
|
nuclear@0
|
382 }
|
nuclear@0
|
383
|
nuclear@0
|
384
|
nuclear@0
|
385 void app_keyboard(int key, bool pressed)
|
nuclear@0
|
386 {
|
nuclear@0
|
387 if(pressed) {
|
nuclear@0
|
388 switch(key) {
|
nuclear@0
|
389 case 27:
|
nuclear@0
|
390 app_quit();
|
nuclear@0
|
391 break;
|
nuclear@0
|
392
|
nuclear@0
|
393 case ' ':
|
nuclear@0
|
394 case 'r':
|
nuclear@0
|
395 vrsys->ResetSeatedZeroPose();
|
nuclear@0
|
396 break;
|
nuclear@0
|
397
|
nuclear@0
|
398 default:
|
nuclear@0
|
399 break;
|
nuclear@0
|
400 }
|
nuclear@0
|
401 }
|
nuclear@0
|
402 }
|
nuclear@0
|
403
|
nuclear@0
|
404 static unsigned int next_pow2(unsigned int x)
|
nuclear@0
|
405 {
|
nuclear@0
|
406 x -= 1;
|
nuclear@0
|
407 x |= x >> 1;
|
nuclear@0
|
408 x |= x >> 2;
|
nuclear@0
|
409 x |= x >> 4;
|
nuclear@0
|
410 x |= x >> 8;
|
nuclear@0
|
411 x |= x >> 16;
|
nuclear@0
|
412 return x + 1;
|
nuclear@0
|
413 }
|
nuclear@0
|
414
|
nuclear@0
|
415 /* generate a chessboard texture with tiles colored (r0, g0, b0) and (r1, g1, b1) */
|
nuclear@0
|
416 unsigned int gen_chess_tex(float r0, float g0, float b0, float r1, float g1, float b1)
|
nuclear@0
|
417 {
|
nuclear@0
|
418 unsigned int tex;
|
nuclear@0
|
419 unsigned char img[8 * 8 * 3];
|
nuclear@0
|
420 unsigned char *pix = img;
|
nuclear@0
|
421
|
nuclear@0
|
422 for(int i=0; i<8; i++) {
|
nuclear@0
|
423 for(int j=0; j<8; j++) {
|
nuclear@0
|
424 int black = (i & 1) == (j & 1);
|
nuclear@0
|
425 pix[0] = (black ? r0 : r1) * 255;
|
nuclear@0
|
426 pix[1] = (black ? g0 : g1) * 255;
|
nuclear@0
|
427 pix[2] = (black ? b0 : b1) * 255;
|
nuclear@0
|
428 pix += 3;
|
nuclear@0
|
429 }
|
nuclear@0
|
430 }
|
nuclear@0
|
431
|
nuclear@0
|
432 glGenTextures(1, &tex);
|
nuclear@0
|
433 glBindTexture(GL_TEXTURE_2D, tex);
|
nuclear@0
|
434 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
nuclear@0
|
435 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
nuclear@0
|
436 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, img);
|
nuclear@0
|
437
|
nuclear@0
|
438 return tex;
|
nuclear@0
|
439 }
|