oculus1

view src/vr.cc @ 18:1b107de821c1

fixed the test to work with non-pow2 textures
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 26 Sep 2013 10:33:08 +0300
parents cfe4979ab3eb
children 899cf9ebffb4
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 static void init_ctx();
8 static bool init_ovr();
9 static bool init_sdr();
11 VRContext vr_ctx;
12 static unsigned int sdrprog;
14 extern "C" int vr_init(enum vr_init_mode mode)
15 {
16 glewInit();
18 init_ctx();
20 if(!init_ovr()) {
21 return -1;
22 }
24 if(!init_sdr()) {
25 return -1;
26 }
28 return 0;
29 }
31 extern "C" void vr_shutdown(void)
32 {
33 delete [] vr_ctx.info.display;
34 //System::Destroy();
35 }
37 static void init_ctx()
38 {
39 vr_ctx.info.width = 1280;
40 vr_ctx.info.height = 800;
41 vr_ctx.info.fov = M_PI / 2.0;
42 vr_ctx.info.aspect = (float)vr_ctx.info.width / (float)vr_ctx.info.height;
43 vr_ctx.info.ipd = 0.035;
44 vr_ctx.info.scale = 1.0;
45 }
47 static bool init_ovr()
48 {
49 LogMaskConstants log_level = LogMask_All;
50 // initialize Oculus SDK
51 const char *logenv = getenv("VR_LOGLEVEL");
52 if(logenv) {
53 switch(atoi(logenv)) {
54 case 0:
55 log_level = LogMask_None;
56 break;
57 case 1:
58 log_level = LogMask_Regular;
59 break;
60 case 2:
61 default:
62 log_level = LogMask_All;
63 break;
64 }
65 }
67 System::Init(Log::ConfigureDefaultLog(log_level));
68 if(!(vr_ctx.ovr_devman = DeviceManager::Create())) {
69 fprintf(stderr, "failed to create OVR device manager\n");
70 return false;
71 }
73 // create the display device
74 HMDInfo info;
75 if(!(vr_ctx.ovr_hmd_dev = vr_ctx.ovr_devman->EnumerateDevices<HMDDevice>().CreateDevice())) {
76 fprintf(stderr, "no oculus rift devices found\n");
77 } else {
78 if(vr_ctx.ovr_hmd_dev->GetDeviceInfo(&info)) {
79 printf("oculus device info:\n");
80 printf(" name: %s\n", info.DisplayDeviceName);
81 printf(" ipd: %f\n", info.InterpupillaryDistance);
82 printf(" distortion: %f %f %f %f\n", info.DistortionK[0],
83 info.DistortionK[1], info.DistortionK[2], info.DistortionK[3]);
84 }
86 // calculate and store viewing parameters
87 vr_ctx.info.width = info.HResolution;
88 vr_ctx.info.height = info.VResolution;
89 vr_ctx.info.aspect = (float)vr_ctx.info.width / (float)vr_ctx.info.height;
91 vr_ctx.info.ipd = info.InterpupillaryDistance;
92 for(int i=0; i<4; i++) {
93 vr_ctx.info.distort[i] = info.DistortionK[i];
94 }
96 Util::Render::StereoConfig stereohelp;
97 stereohelp.SetFullViewport(Util::Render::Viewport(0, 0, vr_ctx.info.width, vr_ctx.info.height));
98 stereohelp.SetStereoMode(Util::Render::Stereo_LeftRight_Multipass);
99 stereohelp.SetHMDInfo(info);
100 stereohelp.SetDistortionFitPointVP(-1.0, 0.0);
102 vr_ctx.info.scale = stereohelp.GetDistortionScale();
104 float vhalfsz = vr_ctx.info.scale * info.VScreenSize * 0.5;
105 vr_ctx.info.fov = 2.0 * atan(vhalfsz / info.EyeToScreenDistance);
107 vr_ctx.info.lens_center_offset = 0.5 - info.LensSeparationDistance / info.HScreenSize;
109 // calculate center of projection shift to match the lens positions
110 float center_dist_meters = info.HScreenSize * 0.25;
111 float proj_shift = center_dist_meters - info.LensSeparationDistance * 0.5;
112 vr_ctx.info.proj_center_offset = 4.0 * proj_shift / info.HScreenSize;
114 // grab the display info
115 vr_ctx.info.display = new char[strlen(info.DisplayDeviceName) + 1];
116 strcpy(vr_ctx.info.display, info.DisplayDeviceName);
118 vr_ctx.info.display_xoffs = info.DesktopX;
119 vr_ctx.info.display_yoffs = info.DesktopY;
121 printf("display: \"%s\" offset: %+d %+d\n", vr_ctx.info.display,
122 vr_ctx.info.display_xoffs, vr_ctx.info.display_yoffs);
123 }
125 // get the sensor device
126 if(vr_ctx.ovr_hmd_dev) {
127 if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_hmd_dev->GetSensor())) {
128 fprintf(stderr, "failed to get oculus sensor device\n");
129 }
130 } else {
131 if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_devman->EnumerateDevices<SensorDevice>().CreateDevice())) {
132 fprintf(stderr, "failed to get oculus sensor device\n");
133 }
134 }
136 if(vr_ctx.ovr_sensor_dev) {
137 SensorInfo sinfo;
138 if(vr_ctx.ovr_sensor_dev->GetDeviceInfo(&sinfo)) {
139 printf("oculus sensor device info:\n");
140 printf(" name: %s\n", sinfo.ProductName);
141 }
143 vr_ctx.ovr_sfusion.AttachToSensor(vr_ctx.ovr_sensor_dev);
144 }
145 return true;
146 }
148 #define EXTERNAL_SHADER
150 static bool init_sdr()
151 {
152 int status;
154 #ifdef EXTERNAL_SHADER
155 FILE *fp = fopen("sdr/sdr.glsl", "rb");
156 if(!fp) {
157 perror("failed to load sdr.glsl");
158 return false;
159 }
160 fseek(fp, 0, SEEK_END);
161 long sz = ftell(fp);
162 rewind(fp);
164 char *buf = (char*)alloca(sz + 1);
165 fread(buf, 1, sz, fp);
166 buf[sz] = 0;
167 sdr_src = buf;
169 fclose(fp);
170 #endif
172 unsigned int sdr = glCreateShader(GL_FRAGMENT_SHADER);
173 glShaderSource(sdr, 1, &sdr_src, 0);
174 glCompileShader(sdr);
175 glGetShaderiv(sdr, GL_COMPILE_STATUS, &status);
176 if(!status) {
177 fprintf(stderr, "failed to compile distortion shader\n");
179 int loglen;
180 glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &loglen);
182 if(loglen > 0) {
183 char *log = (char*)alloca(loglen);
184 glGetShaderInfoLog(sdr, loglen, &loglen, log);
185 fprintf(stderr, "%s\n", log);
186 }
188 return false;
189 }
191 sdrprog = glCreateProgram();
192 glAttachShader(sdrprog, sdr);
193 glLinkProgram(sdrprog);
194 if(!status) {
195 fprintf(stderr, "failed to link distortion shader program\n");
196 glDeleteShader(sdr);
197 return false;
198 }
200 int loc;
202 glUseProgram(sdrprog);
204 if((loc = glGetUniformLocation(sdrprog, "tex")) != -1) {
205 glUniform1i(loc, 0);
206 }
207 if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) {
208 glUniform1f(loc, 0);
209 }
210 if((loc = glGetUniformLocation(sdrprog, "scr_center")) != -1) {
211 glUniform2f(loc, 0, 0);
212 }
213 if((loc = glGetUniformLocation(sdrprog, "scale")) != -1) {
214 glUniform1f(loc, vr_ctx.info.scale);
215 }
216 if((loc = glGetUniformLocation(sdrprog, "aspect")) != -1) {
217 printf("setting aspect: %f\n", vr_ctx.info.aspect / 2.0);
218 glUniform1f(loc, vr_ctx.info.aspect / 2.0);
219 }
220 if((loc = glGetUniformLocation(sdrprog, "scale_in")) != -1) {
221 glUniform2f(loc, 1, 1);
222 }
223 if((loc = glGetUniformLocation(sdrprog, "dist_factors")) != -1) {
224 glUniform4f(loc, vr_ctx.info.distort[0], vr_ctx.info.distort[1],
225 vr_ctx.info.distort[2], vr_ctx.info.distort[3]);
226 }
228 return true;
229 }
231 extern "C" const char *vr_get_display_name(void)
232 {
233 return vr_ctx.info.display;
234 }
236 extern "C" void vr_get_display_pos(int *xptr, int *yptr)
237 {
238 *xptr = vr_ctx.info.display_xoffs;
239 *yptr = vr_ctx.info.display_yoffs;
240 }
242 extern "C" int vr_get_width(void)
243 {
244 return vr_ctx.info.width;
245 }
247 extern "C" int vr_get_height(void)
248 {
249 return vr_ctx.info.height;
250 }
252 extern "C" float vr_get_fov(void)
253 {
254 return vr_ctx.info.fov;
255 }
257 extern "C" float vr_get_aspect(void)
258 {
259 return vr_ctx.info.aspect;
260 }
262 extern "C" void vr_set_eyedist(float ipd)
263 {
264 vr_ctx.info.ipd = ipd;
265 }
267 extern "C" float vr_get_eyedist(void)
268 {
269 return vr_ctx.info.ipd;
270 }
272 extern "C" void vr_set_distort(const float *coef)
273 {
274 memcpy(vr_ctx.info.distort, coef, sizeof vr_ctx.info.distort);
275 }
277 extern "C" void vr_get_distort(float *coef)
278 {
279 memcpy(coef, vr_ctx.info.distort, sizeof vr_ctx.info.distort);
280 }
282 extern "C" void vr_set_prediction_sec(float dt)
283 {
284 vr_ctx.ovr_sfusion.SetPrediction(dt);
285 }
287 extern "C" float vr_get_prediction_sec(void)
288 {
289 return vr_ctx.ovr_sfusion.GetPredictionDelta();
290 }
292 extern "C" void vr_get_view_matrix(float *res, int eye)
293 {
294 // TODO
295 }
297 extern "C" void vr_get_proj_matrix(float *res, int eye)
298 {
299 static float eye_scale[] = {0.0, 1.0, -1.0};
301 Matrix4f proj = Matrix4f::PerspectiveRH(vr_ctx.info.fov, vr_ctx.info.aspect / 2.0, 0.3, 1000.0);
302 proj = Matrix4f::Translation(vr_ctx.info.proj_center_offset * eye_scale[eye], 0, 0) * proj;
304 memcpy(res, proj.M[0], 16 * sizeof(float));
305 }
307 extern "C" void vr_get_translation(float *offs)
308 {
309 // current oculus devkit doesn't do translation
310 offs[0] = offs[1] = offs[2] = 0.0f;
311 }
313 extern "C" void vr_get_rotation(float *quat)
314 {
315 Quatf oq = vr_ctx.ovr_sfusion.GetPredictedOrientation();
316 quat[0] = oq.x;
317 quat[1] = oq.y;
318 quat[2] = oq.z;
319 quat[3] = oq.w;
320 }
322 extern "C" void vr_get_rotation_euler(float *euler)
323 {
324 Quatf oq = vr_ctx.ovr_sfusion.GetPredictedOrientation();
325 oq.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(euler + 1, euler, euler + 2);
326 }
328 extern "C" void vr_draw_eye(int eye, unsigned int tex, float tex_scale_x, float tex_scale_y)
329 {
330 static const float rects[3][4] = {
331 {-1, -1, 1, 1},
332 {-1, -1, 0, 1},
333 {0, -1, 1, 1}
334 };
335 static const float offs_scale[3] = {0.0, -1.0, 1.0};
337 glPushAttrib(GL_ENABLE_BIT);
338 glDisable(GL_DEPTH_TEST);
339 glDisable(GL_LIGHTING);
340 glEnable(GL_TEXTURE_2D);
342 glMatrixMode(GL_MODELVIEW);
343 glPushMatrix();
344 glLoadIdentity();
346 glMatrixMode(GL_PROJECTION);
347 glPushMatrix();
348 glLoadIdentity();
350 glUseProgram(sdrprog);
352 if(sdrprog) {
353 int loc;
354 if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) {
355 float offset = vr_ctx.info.lens_center_offset * offs_scale[eye];
356 glUniform1f(loc, offset);
357 }
359 if((loc = glGetUniformLocation(sdrprog, "tex_scale")) != -1) {
360 glUniform2f(loc, tex_scale_x, tex_scale_y);
361 }
362 }
364 glBindTexture(GL_TEXTURE_2D, tex);
365 glBegin(GL_QUADS);
366 glColor4f(1, 1, 1, 1);
367 glTexCoord2f(0, 0); glVertex2f(rects[eye][0], rects[eye][1]);
368 glTexCoord2f(1, 0); glVertex2f(rects[eye][2], rects[eye][1]);
369 glTexCoord2f(1, 1); glVertex2f(rects[eye][2], rects[eye][3]);
370 glTexCoord2f(0, 1); glVertex2f(rects[eye][0], rects[eye][3]);
371 glEnd();
373 glUseProgram(0);
375 glPopMatrix();
376 glMatrixMode(GL_MODELVIEW);
377 glPopMatrix();
379 glPopAttrib();
380 }