goat3dgfx

view src/vr/vr.cc @ 34:3eb6c8f89fe1

merge
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 02 Mar 2014 17:41:10 +0200
parents 7d6b667821cf
children
line source
1 #include "config.h"
3 #include <stdio.h>
4 #include <string.h>
5 #define _USE_MATH_DEFINES
6 #include <math.h>
7 #include <GL/glew.h>
8 #include "vmath/vmath.h"
9 #include "vr.h"
10 #include "vr_impl.h"
11 #include "vr_sdr.h"
13 #ifndef WIN32
14 #include <alloca.h>
15 #else
16 #include <malloc.h>
17 #endif
19 static void init_ctx();
20 static bool init_ovr();
21 static bool init_sdr();
23 VRContext vr_ctx;
24 static unsigned int sdrprog;
26 extern "C" int vr_init(enum vr_init_mode mode)
27 {
28 init_ctx();
30 if(!init_ovr()) {
31 return -1;
32 }
34 if(!init_sdr()) {
35 return -1;
36 }
38 return 0;
39 }
41 extern "C" void vr_shutdown(void)
42 {
43 delete [] vr_ctx.info.display;
44 #ifdef USE_LIBOVR
45 delete vr_ctx.ovr_sfusion;
46 //System::Destroy();
47 #endif
49 memset(&vr_ctx, 0, sizeof vr_ctx);
50 }
52 static void init_ctx()
53 {
54 vr_ctx.info.width = 1280;
55 vr_ctx.info.height = 800;
56 vr_ctx.info.fov = M_PI / 2.0;
57 vr_ctx.info.aspect = (float)vr_ctx.info.width / (float)vr_ctx.info.height;
58 vr_ctx.info.ipd = 0.035;
59 vr_ctx.info.scale = 1.0;
60 }
62 static bool init_ovr()
63 {
64 #ifdef USE_LIBOVR
65 LogMaskConstants log_level = LogMask_All;
66 // initialize Oculus SDK
67 const char *logenv = getenv("VR_LOGLEVEL");
68 if(logenv) {
69 switch(atoi(logenv)) {
70 case 0:
71 log_level = LogMask_None;
72 break;
73 case 1:
74 log_level = LogMask_Regular;
75 break;
76 case 2:
77 default:
78 log_level = LogMask_All;
79 break;
80 }
81 }
83 System::Init(Log::ConfigureDefaultLog(log_level));
84 if(!(vr_ctx.ovr_devman = DeviceManager::Create())) {
85 fprintf(stderr, "failed to create OVR device manager\n");
86 return false;
87 }
89 // create the display device
90 HMDInfo info;
91 if(!(vr_ctx.ovr_hmd_dev = vr_ctx.ovr_devman->EnumerateDevices<HMDDevice>().CreateDevice())) {
92 fprintf(stderr, "no oculus rift devices found\n");
93 } else {
94 if(vr_ctx.ovr_hmd_dev->GetDeviceInfo(&info)) {
95 printf("oculus device info:\n");
96 printf(" name: %s\n", info.DisplayDeviceName);
97 printf(" ipd: %f\n", info.InterpupillaryDistance);
98 printf(" distortion: %f %f %f %f\n", info.DistortionK[0],
99 info.DistortionK[1], info.DistortionK[2], info.DistortionK[3]);
100 }
102 // calculate and store viewing parameters
103 vr_ctx.info.width = info.HResolution;
104 vr_ctx.info.height = info.VResolution;
105 vr_ctx.info.aspect = (float)vr_ctx.info.width / (float)vr_ctx.info.height;
107 vr_ctx.info.ipd = info.InterpupillaryDistance;
108 for(int i=0; i<4; i++) {
109 vr_ctx.info.distort[i] = info.DistortionK[i];
110 }
112 Util::Render::StereoConfig stereohelp;
113 stereohelp.SetFullViewport(Util::Render::Viewport(0, 0, vr_ctx.info.width, vr_ctx.info.height));
114 stereohelp.SetStereoMode(Util::Render::Stereo_LeftRight_Multipass);
115 stereohelp.SetHMDInfo(info);
116 stereohelp.SetDistortionFitPointVP(-1.0, 0.0);
118 vr_ctx.info.scale = stereohelp.GetDistortionScale();
120 float vhalfsz = vr_ctx.info.scale * info.VScreenSize * 0.5;
121 vr_ctx.info.fov = 2.0 * atan(vhalfsz / info.EyeToScreenDistance);
123 vr_ctx.info.lens_center_offset = 0.5 - info.LensSeparationDistance / info.HScreenSize;
125 // calculate center of projection shift to match the lens positions
126 float center_dist_meters = info.HScreenSize * 0.25;
127 float proj_shift = center_dist_meters - info.LensSeparationDistance * 0.5;
128 vr_ctx.info.proj_center_offset = 4.0 * proj_shift / info.HScreenSize;
130 // grab the display info
131 vr_ctx.info.display = new char[strlen(info.DisplayDeviceName) + 1];
132 strcpy(vr_ctx.info.display, info.DisplayDeviceName);
134 vr_ctx.info.display_xoffs = info.DesktopX;
135 vr_ctx.info.display_yoffs = info.DesktopY;
137 printf("display: \"%s\" offset: %+d %+d\n", vr_ctx.info.display,
138 vr_ctx.info.display_xoffs, vr_ctx.info.display_yoffs);
139 }
141 // get the sensor device
142 if(vr_ctx.ovr_hmd_dev) {
143 if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_hmd_dev->GetSensor())) {
144 fprintf(stderr, "failed to get oculus sensor device\n");
145 }
146 } else {
147 if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_devman->EnumerateDevices<SensorDevice>().CreateDevice())) {
148 fprintf(stderr, "failed to get oculus sensor device\n");
149 }
150 }
152 if(vr_ctx.ovr_sensor_dev) {
153 SensorInfo sinfo;
154 if(vr_ctx.ovr_sensor_dev->GetDeviceInfo(&sinfo)) {
155 printf("oculus sensor device info:\n");
156 printf(" name: %s\n", sinfo.ProductName);
157 }
159 vr_ctx.ovr_sfusion = new SensorFusion;
160 vr_ctx.ovr_sfusion->AttachToSensor(vr_ctx.ovr_sensor_dev);
161 }
162 #endif // USE_LIBOVR
163 return true;
164 }
166 #undef EXTERNAL_SHADER
168 static bool init_sdr()
169 {
170 int status;
172 #ifdef EXTERNAL_SHADER
173 FILE *fp = fopen("sdr/sdr.glsl", "rb");
174 if(!fp) {
175 perror("failed to load sdr.glsl");
176 return false;
177 }
178 fseek(fp, 0, SEEK_END);
179 long sz = ftell(fp);
180 rewind(fp);
182 char *buf = (char*)alloca(sz + 1);
183 fread(buf, 1, sz, fp);
184 buf[sz] = 0;
185 sdr_src = buf;
187 fclose(fp);
188 #endif
190 unsigned int sdr = glCreateShader(GL_FRAGMENT_SHADER);
191 glShaderSource(sdr, 1, &sdr_src, 0);
192 glCompileShader(sdr);
193 glGetShaderiv(sdr, GL_COMPILE_STATUS, &status);
194 if(!status) {
195 fprintf(stderr, "failed to compile distortion shader\n");
197 int loglen;
198 glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &loglen);
200 if(loglen > 0) {
201 char *log = (char*)alloca(loglen);
202 glGetShaderInfoLog(sdr, loglen, &loglen, log);
203 fprintf(stderr, "%s\n", log);
204 }
206 return false;
207 }
209 sdrprog = glCreateProgram();
210 glAttachShader(sdrprog, sdr);
211 glLinkProgram(sdrprog);
212 if(!status) {
213 fprintf(stderr, "failed to link distortion shader program\n");
214 glDeleteShader(sdr);
215 return false;
216 }
218 int loc;
220 glUseProgram(sdrprog);
222 if((loc = glGetUniformLocation(sdrprog, "tex")) != -1) {
223 glUniform1i(loc, 0);
224 }
225 if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) {
226 glUniform1f(loc, 0);
227 }
228 if((loc = glGetUniformLocation(sdrprog, "scr_center")) != -1) {
229 glUniform2f(loc, 0, 0);
230 }
231 if((loc = glGetUniformLocation(sdrprog, "scale")) != -1) {
232 glUniform1f(loc, vr_ctx.info.scale);
233 }
234 if((loc = glGetUniformLocation(sdrprog, "aspect")) != -1) {
235 printf("setting aspect: %f\n", vr_ctx.info.aspect / 2.0);
236 glUniform1f(loc, vr_ctx.info.aspect / 2.0);
237 }
238 if((loc = glGetUniformLocation(sdrprog, "scale_in")) != -1) {
239 glUniform2f(loc, 1, 1);
240 }
241 if((loc = glGetUniformLocation(sdrprog, "dist_factors")) != -1) {
242 glUniform4f(loc, vr_ctx.info.distort[0], vr_ctx.info.distort[1],
243 vr_ctx.info.distort[2], vr_ctx.info.distort[3]);
244 }
246 return true;
247 }
249 extern "C" const char *vr_get_display_name(void)
250 {
251 return vr_ctx.info.display;
252 }
254 extern "C" void vr_get_display_pos(int *xptr, int *yptr)
255 {
256 *xptr = vr_ctx.info.display_xoffs;
257 *yptr = vr_ctx.info.display_yoffs;
258 }
260 extern "C" int vr_get_width(void)
261 {
262 return vr_ctx.info.width;
263 }
265 extern "C" int vr_get_height(void)
266 {
267 return vr_ctx.info.height;
268 }
270 extern "C" float vr_get_fov(void)
271 {
272 return vr_ctx.info.fov;
273 }
275 extern "C" float vr_get_aspect(void)
276 {
277 return vr_ctx.info.aspect;
278 }
280 extern "C" void vr_set_eyedist(float ipd)
281 {
282 vr_ctx.info.ipd = ipd;
283 }
285 extern "C" float vr_get_eyedist(void)
286 {
287 return vr_ctx.info.ipd;
288 }
290 extern "C" void vr_set_distort(const float *coef)
291 {
292 memcpy(vr_ctx.info.distort, coef, sizeof vr_ctx.info.distort);
293 }
295 extern "C" void vr_get_distort(float *coef)
296 {
297 memcpy(coef, vr_ctx.info.distort, sizeof vr_ctx.info.distort);
298 }
300 extern "C" void vr_set_prediction_sec(float dt)
301 {
302 #ifdef USE_LIBOVR
303 vr_ctx.ovr_sfusion->SetPrediction(dt);
304 #endif
305 }
307 extern "C" float vr_get_prediction_sec(void)
308 {
309 #ifdef USE_LIBOVR
310 return vr_ctx.ovr_sfusion->GetPredictionDelta();
311 #endif
312 }
314 extern "C" void vr_get_view_matrix(float *res, int eye)
315 {
316 // TODO
317 }
319 extern "C" void vr_get_proj_matrix(float *res, int eye)
320 {
321 #ifdef USE_LIBOVR
322 static float eye_scale[] = {0.0, 1.0, -1.0};
324 Matrix4f proj = Matrix4f::PerspectiveRH(vr_ctx.info.fov, vr_ctx.info.aspect / 2.0, 0.3, 1000.0);
325 proj = Matrix4f::Translation(vr_ctx.info.proj_center_offset * eye_scale[eye], 0, 0) * proj;
327 memcpy(res, proj.M[0], 16 * sizeof(float));
328 #else
329 Matrix4x4 proj;
330 proj.set_perspective(vr_ctx.info.fov, vr_ctx.info.aspect, 0.3, 1000.0);
331 proj.transpose();
332 memcpy(res, proj[0], 16 * sizeof(float));
333 #endif
334 }
336 extern "C" void vr_get_translation(float *offs)
337 {
338 // current oculus devkit doesn't do translation
339 offs[0] = offs[1] = offs[2] = 0.0f;
340 }
342 extern "C" void vr_get_rotation(float *quat)
343 {
344 #ifdef USE_LIBOVR
345 Quatf oq = vr_ctx.ovr_sfusion->GetPredictedOrientation();
346 quat[0] = oq.x;
347 quat[1] = oq.y;
348 quat[2] = oq.z;
349 quat[3] = oq.w;
350 #else
351 quat[0] = quat[1] = quat[2] = 0.0;
352 quat[3] = 1.0;
353 #endif
354 }
356 extern "C" void vr_get_rotation_euler(float *euler)
357 {
358 #ifdef USE_LIBOVR
359 Quatf oq = vr_ctx.ovr_sfusion->GetPredictedOrientation();
360 oq.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(euler + 1, euler, euler + 2);
361 #else
362 euler[0] = euler[1] = euler[2] = 0.0;
363 #endif
364 }
366 extern "C" void vr_draw_eye(int eye, unsigned int tex, float tex_scale_x, float tex_scale_y)
367 {
368 static const float rects[3][4] = {
369 {-1, -1, 1, 1},
370 {-1, -1, 0, 1},
371 {0, -1, 1, 1}
372 };
373 static const float offs_scale[3] = {0.0, -1.0, 1.0};
375 glPushAttrib(GL_ENABLE_BIT);
376 glDisable(GL_DEPTH_TEST);
377 glDisable(GL_LIGHTING);
378 glEnable(GL_TEXTURE_2D);
380 glMatrixMode(GL_MODELVIEW);
381 glPushMatrix();
382 glLoadIdentity();
384 glMatrixMode(GL_PROJECTION);
385 glPushMatrix();
386 glLoadIdentity();
388 glUseProgram(sdrprog);
390 if(sdrprog) {
391 int loc;
392 if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) {
393 float offset = vr_ctx.info.lens_center_offset * offs_scale[eye];
394 glUniform1f(loc, offset);
395 }
397 if((loc = glGetUniformLocation(sdrprog, "tex_scale")) != -1) {
398 glUniform2f(loc, tex_scale_x, tex_scale_y);
399 }
400 }
402 glBindTexture(GL_TEXTURE_2D, tex);
403 glBegin(GL_QUADS);
404 glColor4f(1, 1, 1, 1);
405 glTexCoord2f(0, 0); glVertex2f(rects[eye][0], rects[eye][1]);
406 glTexCoord2f(1, 0); glVertex2f(rects[eye][2], rects[eye][1]);
407 glTexCoord2f(1, 1); glVertex2f(rects[eye][2], rects[eye][3]);
408 glTexCoord2f(0, 1); glVertex2f(rects[eye][0], rects[eye][3]);
409 glEnd();
411 glUseProgram(0);
413 glPopMatrix();
414 glMatrixMode(GL_MODELVIEW);
415 glPopMatrix();
417 glPopAttrib();
418 }