symmetry

view src/vr/vr.cc @ 0:a90a71a74f0b

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