oculus1

view src/vr.cc @ 29:9a973ef0e2a3

fixed the performance issue under MacOSX by replacing glutSolidTeapot (which uses glEvalMesh) with my own teapot generator.
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 27 Oct 2013 06:31:18 +0200
parents ef4c9d8eeca7
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 glewInit();
24 init_ctx();
26 if(!init_ovr()) {
27 return -1;
28 }
30 if(!init_sdr()) {
31 return -1;
32 }
34 return 0;
35 }
37 extern "C" void vr_shutdown(void)
38 {
39 delete [] vr_ctx.info.display;
40 //System::Destroy();
41 }
43 static void init_ctx()
44 {
45 vr_ctx.info.width = 1280;
46 vr_ctx.info.height = 800;
47 vr_ctx.info.fov = M_PI / 2.0;
48 vr_ctx.info.aspect = (float)vr_ctx.info.width / (float)vr_ctx.info.height;
49 vr_ctx.info.ipd = 0.035;
50 vr_ctx.info.scale = 1.0;
51 }
53 static bool init_ovr()
54 {
55 LogMaskConstants log_level = LogMask_All;
56 // initialize Oculus SDK
57 const char *logenv = getenv("VR_LOGLEVEL");
58 if(logenv) {
59 switch(atoi(logenv)) {
60 case 0:
61 log_level = LogMask_None;
62 break;
63 case 1:
64 log_level = LogMask_Regular;
65 break;
66 case 2:
67 default:
68 log_level = LogMask_All;
69 break;
70 }
71 }
73 System::Init(Log::ConfigureDefaultLog(log_level));
74 if(!(vr_ctx.ovr_devman = DeviceManager::Create())) {
75 fprintf(stderr, "failed to create OVR device manager\n");
76 return false;
77 }
79 // create the display device
80 HMDInfo info;
81 if(!(vr_ctx.ovr_hmd_dev = vr_ctx.ovr_devman->EnumerateDevices<HMDDevice>().CreateDevice())) {
82 fprintf(stderr, "no oculus rift devices found\n");
83 } else {
84 if(vr_ctx.ovr_hmd_dev->GetDeviceInfo(&info)) {
85 printf("oculus device info:\n");
86 printf(" name: %s\n", info.DisplayDeviceName);
87 printf(" ipd: %f\n", info.InterpupillaryDistance);
88 printf(" distortion: %f %f %f %f\n", info.DistortionK[0],
89 info.DistortionK[1], info.DistortionK[2], info.DistortionK[3]);
90 }
92 // calculate and store viewing parameters
93 vr_ctx.info.width = info.HResolution;
94 vr_ctx.info.height = info.VResolution;
95 vr_ctx.info.aspect = (float)vr_ctx.info.width / (float)vr_ctx.info.height;
97 vr_ctx.info.ipd = info.InterpupillaryDistance;
98 for(int i=0; i<4; i++) {
99 vr_ctx.info.distort[i] = info.DistortionK[i];
100 }
102 Util::Render::StereoConfig stereohelp;
103 stereohelp.SetFullViewport(Util::Render::Viewport(0, 0, vr_ctx.info.width, vr_ctx.info.height));
104 stereohelp.SetStereoMode(Util::Render::Stereo_LeftRight_Multipass);
105 stereohelp.SetHMDInfo(info);
106 stereohelp.SetDistortionFitPointVP(-1.0, 0.0);
108 vr_ctx.info.scale = stereohelp.GetDistortionScale();
110 float vhalfsz = vr_ctx.info.scale * info.VScreenSize * 0.5;
111 vr_ctx.info.fov = 2.0 * atan(vhalfsz / info.EyeToScreenDistance);
113 vr_ctx.info.lens_center_offset = 0.5 - info.LensSeparationDistance / info.HScreenSize;
115 // calculate center of projection shift to match the lens positions
116 float center_dist_meters = info.HScreenSize * 0.25;
117 float proj_shift = center_dist_meters - info.LensSeparationDistance * 0.5;
118 vr_ctx.info.proj_center_offset = 4.0 * proj_shift / info.HScreenSize;
120 // grab the display info
121 vr_ctx.info.display = new char[strlen(info.DisplayDeviceName) + 1];
122 strcpy(vr_ctx.info.display, info.DisplayDeviceName);
124 vr_ctx.info.display_xoffs = info.DesktopX;
125 vr_ctx.info.display_yoffs = info.DesktopY;
127 printf("display: \"%s\" offset: %+d %+d\n", vr_ctx.info.display,
128 vr_ctx.info.display_xoffs, vr_ctx.info.display_yoffs);
129 }
131 // get the sensor device
132 if(vr_ctx.ovr_hmd_dev) {
133 if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_hmd_dev->GetSensor())) {
134 fprintf(stderr, "failed to get oculus sensor device\n");
135 }
136 } else {
137 if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_devman->EnumerateDevices<SensorDevice>().CreateDevice())) {
138 fprintf(stderr, "failed to get oculus sensor device\n");
139 }
140 }
142 if(vr_ctx.ovr_sensor_dev) {
143 SensorInfo sinfo;
144 if(vr_ctx.ovr_sensor_dev->GetDeviceInfo(&sinfo)) {
145 printf("oculus sensor device info:\n");
146 printf(" name: %s\n", sinfo.ProductName);
147 }
149 vr_ctx.ovr_sfusion.AttachToSensor(vr_ctx.ovr_sensor_dev);
150 }
151 return true;
152 }
154 #define EXTERNAL_SHADER
156 static bool init_sdr()
157 {
158 int status;
160 #ifdef EXTERNAL_SHADER
161 FILE *fp = fopen("sdr/sdr.glsl", "rb");
162 if(!fp) {
163 perror("failed to load sdr.glsl");
164 return false;
165 }
166 fseek(fp, 0, SEEK_END);
167 long sz = ftell(fp);
168 rewind(fp);
170 char *buf = (char*)alloca(sz + 1);
171 fread(buf, 1, sz, fp);
172 buf[sz] = 0;
173 sdr_src = buf;
175 fclose(fp);
176 #endif
178 unsigned int sdr = glCreateShader(GL_FRAGMENT_SHADER);
179 glShaderSource(sdr, 1, &sdr_src, 0);
180 glCompileShader(sdr);
181 glGetShaderiv(sdr, GL_COMPILE_STATUS, &status);
182 if(!status) {
183 fprintf(stderr, "failed to compile distortion shader\n");
185 int loglen;
186 glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &loglen);
188 if(loglen > 0) {
189 char *log = (char*)alloca(loglen);
190 glGetShaderInfoLog(sdr, loglen, &loglen, log);
191 fprintf(stderr, "%s\n", log);
192 }
194 return false;
195 }
197 sdrprog = glCreateProgram();
198 glAttachShader(sdrprog, sdr);
199 glLinkProgram(sdrprog);
200 if(!status) {
201 fprintf(stderr, "failed to link distortion shader program\n");
202 glDeleteShader(sdr);
203 return false;
204 }
206 int loc;
208 glUseProgram(sdrprog);
210 if((loc = glGetUniformLocation(sdrprog, "tex")) != -1) {
211 glUniform1i(loc, 0);
212 }
213 if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) {
214 glUniform1f(loc, 0);
215 }
216 if((loc = glGetUniformLocation(sdrprog, "scr_center")) != -1) {
217 glUniform2f(loc, 0, 0);
218 }
219 if((loc = glGetUniformLocation(sdrprog, "scale")) != -1) {
220 glUniform1f(loc, vr_ctx.info.scale);
221 }
222 if((loc = glGetUniformLocation(sdrprog, "aspect")) != -1) {
223 printf("setting aspect: %f\n", vr_ctx.info.aspect / 2.0);
224 glUniform1f(loc, vr_ctx.info.aspect / 2.0);
225 }
226 if((loc = glGetUniformLocation(sdrprog, "scale_in")) != -1) {
227 glUniform2f(loc, 1, 1);
228 }
229 if((loc = glGetUniformLocation(sdrprog, "dist_factors")) != -1) {
230 glUniform4f(loc, vr_ctx.info.distort[0], vr_ctx.info.distort[1],
231 vr_ctx.info.distort[2], vr_ctx.info.distort[3]);
232 }
234 return true;
235 }
237 extern "C" const char *vr_get_display_name(void)
238 {
239 return vr_ctx.info.display;
240 }
242 extern "C" void vr_get_display_pos(int *xptr, int *yptr)
243 {
244 *xptr = vr_ctx.info.display_xoffs;
245 *yptr = vr_ctx.info.display_yoffs;
246 }
248 extern "C" int vr_get_width(void)
249 {
250 return vr_ctx.info.width;
251 }
253 extern "C" int vr_get_height(void)
254 {
255 return vr_ctx.info.height;
256 }
258 extern "C" float vr_get_fov(void)
259 {
260 return vr_ctx.info.fov;
261 }
263 extern "C" float vr_get_aspect(void)
264 {
265 return vr_ctx.info.aspect;
266 }
268 extern "C" void vr_set_eyedist(float ipd)
269 {
270 vr_ctx.info.ipd = ipd;
271 }
273 extern "C" float vr_get_eyedist(void)
274 {
275 return vr_ctx.info.ipd;
276 }
278 extern "C" void vr_set_distort(const float *coef)
279 {
280 memcpy(vr_ctx.info.distort, coef, sizeof vr_ctx.info.distort);
281 }
283 extern "C" void vr_get_distort(float *coef)
284 {
285 memcpy(coef, vr_ctx.info.distort, sizeof vr_ctx.info.distort);
286 }
288 extern "C" void vr_set_prediction_sec(float dt)
289 {
290 vr_ctx.ovr_sfusion.SetPrediction(dt);
291 }
293 extern "C" float vr_get_prediction_sec(void)
294 {
295 return vr_ctx.ovr_sfusion.GetPredictionDelta();
296 }
298 extern "C" void vr_get_view_matrix(float *res, int eye)
299 {
300 // TODO
301 }
303 extern "C" void vr_get_proj_matrix(float *res, int eye)
304 {
305 static float eye_scale[] = {0.0, 1.0, -1.0};
307 Matrix4f proj = Matrix4f::PerspectiveRH(vr_ctx.info.fov, vr_ctx.info.aspect / 2.0, 0.3, 1000.0);
308 proj = Matrix4f::Translation(vr_ctx.info.proj_center_offset * eye_scale[eye], 0, 0) * proj;
310 memcpy(res, proj.M[0], 16 * sizeof(float));
311 }
313 extern "C" void vr_get_translation(float *offs)
314 {
315 // current oculus devkit doesn't do translation
316 offs[0] = offs[1] = offs[2] = 0.0f;
317 }
319 extern "C" void vr_get_rotation(float *quat)
320 {
321 Quatf oq = vr_ctx.ovr_sfusion.GetPredictedOrientation();
322 quat[0] = oq.x;
323 quat[1] = oq.y;
324 quat[2] = oq.z;
325 quat[3] = oq.w;
326 }
328 extern "C" void vr_get_rotation_euler(float *euler)
329 {
330 Quatf oq = vr_ctx.ovr_sfusion.GetPredictedOrientation();
331 oq.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(euler + 1, euler, euler + 2);
332 }
334 extern "C" void vr_draw_eye(int eye, unsigned int tex, float tex_scale_x, float tex_scale_y)
335 {
336 static const float rects[3][4] = {
337 {-1, -1, 1, 1},
338 {-1, -1, 0, 1},
339 {0, -1, 1, 1}
340 };
341 static const float offs_scale[3] = {0.0, -1.0, 1.0};
343 glPushAttrib(GL_ENABLE_BIT);
344 glDisable(GL_DEPTH_TEST);
345 glDisable(GL_LIGHTING);
346 glEnable(GL_TEXTURE_2D);
348 glMatrixMode(GL_MODELVIEW);
349 glPushMatrix();
350 glLoadIdentity();
352 glMatrixMode(GL_PROJECTION);
353 glPushMatrix();
354 glLoadIdentity();
356 glUseProgram(sdrprog);
358 if(sdrprog) {
359 int loc;
360 if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) {
361 float offset = vr_ctx.info.lens_center_offset * offs_scale[eye];
362 glUniform1f(loc, offset);
363 }
365 if((loc = glGetUniformLocation(sdrprog, "tex_scale")) != -1) {
366 glUniform2f(loc, tex_scale_x, tex_scale_y);
367 }
368 }
370 glBindTexture(GL_TEXTURE_2D, tex);
371 glBegin(GL_QUADS);
372 glColor4f(1, 1, 1, 1);
373 glTexCoord2f(0, 0); glVertex2f(rects[eye][0], rects[eye][1]);
374 glTexCoord2f(1, 0); glVertex2f(rects[eye][2], rects[eye][1]);
375 glTexCoord2f(1, 1); glVertex2f(rects[eye][2], rects[eye][3]);
376 glTexCoord2f(0, 1); glVertex2f(rects[eye][0], rects[eye][3]);
377 glEnd();
379 glUseProgram(0);
381 glPopMatrix();
382 glMatrixMode(GL_MODELVIEW);
383 glPopMatrix();
385 glPopAttrib();
386 }