rev |
line source |
nuclear@1
|
1 #include <stdio.h>
|
nuclear@12
|
2 #include <GL/glew.h>
|
nuclear@1
|
3 #include "vr.h"
|
nuclear@1
|
4 #include "vr_impl.h"
|
nuclear@1
|
5
|
nuclear@12
|
6 static const char *sdr_src =
|
nuclear@12
|
7 "uniform sampler2D tex;\n"
|
nuclear@12
|
8 "uniform vec2 lens_center;\n"
|
nuclear@12
|
9 "uniform vec2 scr_center;\n"
|
nuclear@12
|
10 "uniform vec2 scale;\n"
|
nuclear@12
|
11 "uniform vec2 scale_in;\n"
|
nuclear@12
|
12 "uniform vec4 warp_param;\n"
|
nuclear@12
|
13 "\n"
|
nuclear@13
|
14 "vec2 warp(in vec2 pt, out float dbgrad)\n"
|
nuclear@12
|
15 "{\n"
|
nuclear@12
|
16 " vec2 theta = (pt - lens_center) * scale_in;\n"
|
nuclear@13
|
17 " float rsq = dot(theta, theta);\n"
|
nuclear@13
|
18 " vec2 rvec = theta * (warp_param.x + \n"
|
nuclear@13
|
19 " warp_param.y * rsq +\n"
|
nuclear@12
|
20 " warp_param.z * rsq * rsq +\n"
|
nuclear@12
|
21 " warp_param.w * rsq * rsq * rsq);\n"
|
nuclear@13
|
22 " dbgrad = length(theta);\n"
|
nuclear@12
|
23 " return lens_center + scale * rvec;\n"
|
nuclear@12
|
24 "}\n"
|
nuclear@12
|
25 "\n"
|
nuclear@12
|
26 "void main()\n"
|
nuclear@12
|
27 "{\n"
|
nuclear@13
|
28 " float dbgrad;\n"
|
nuclear@13
|
29 " vec2 tc = warp(gl_TexCoord[0].xy, dbgrad);\n"
|
nuclear@12
|
30 " gl_FragColor.rgb = texture2D(tex, tc).rgb;\n"
|
nuclear@13
|
31 " gl_FragColor.rgb += mix(vec3(1.0, 1.0, 0.0), vec3(0.0), smoothstep(0.01, 0.05, dbgrad));\n"
|
nuclear@12
|
32 " gl_FragColor.a = 1.0;\n"
|
nuclear@12
|
33 "}\n";
|
nuclear@12
|
34
|
nuclear@1
|
35 static bool init_ovr();
|
nuclear@12
|
36 static bool init_sdr();
|
nuclear@1
|
37
|
nuclear@3
|
38 VRContext vr_ctx;
|
nuclear@12
|
39 static unsigned int sdrprog;
|
nuclear@1
|
40
|
nuclear@1
|
41 extern "C" int vr_init(enum vr_init_mode mode)
|
nuclear@1
|
42 {
|
nuclear@12
|
43 glewInit();
|
nuclear@12
|
44
|
nuclear@1
|
45 if(!init_ovr()) {
|
nuclear@1
|
46 return -1;
|
nuclear@1
|
47 }
|
nuclear@12
|
48
|
nuclear@12
|
49 if(!init_sdr()) {
|
nuclear@12
|
50 return -1;
|
nuclear@12
|
51 }
|
nuclear@12
|
52
|
nuclear@1
|
53 return 0;
|
nuclear@1
|
54 }
|
nuclear@1
|
55
|
nuclear@1
|
56 extern "C" void vr_shutdown(void)
|
nuclear@1
|
57 {
|
nuclear@3
|
58 //System::Destroy();
|
nuclear@1
|
59 }
|
nuclear@1
|
60
|
nuclear@1
|
61 static bool init_ovr()
|
nuclear@1
|
62 {
|
nuclear@8
|
63 LogMaskConstants log_level = LogMask_All;
|
nuclear@1
|
64 // initialize Oculus SDK
|
nuclear@5
|
65 const char *logenv = getenv("VR_LOGLEVEL");
|
nuclear@5
|
66 if(logenv) {
|
nuclear@5
|
67 switch(atoi(logenv)) {
|
nuclear@5
|
68 case 0:
|
nuclear@5
|
69 log_level = LogMask_None;
|
nuclear@5
|
70 break;
|
nuclear@5
|
71 case 1:
|
nuclear@5
|
72 log_level = LogMask_Regular;
|
nuclear@5
|
73 break;
|
nuclear@5
|
74 case 2:
|
nuclear@5
|
75 default:
|
nuclear@5
|
76 log_level = LogMask_All;
|
nuclear@5
|
77 break;
|
nuclear@5
|
78 }
|
nuclear@5
|
79 }
|
nuclear@5
|
80
|
nuclear@5
|
81 System::Init(Log::ConfigureDefaultLog(log_level));
|
nuclear@3
|
82 if(!(vr_ctx.ovr_devman = DeviceManager::Create())) {
|
nuclear@1
|
83 fprintf(stderr, "failed to create OVR device manager\n");
|
nuclear@1
|
84 return false;
|
nuclear@1
|
85 }
|
nuclear@1
|
86
|
nuclear@1
|
87 // create the display device
|
nuclear@4
|
88 HMDInfo info;
|
nuclear@3
|
89 if(!(vr_ctx.ovr_hmd_dev = vr_ctx.ovr_devman->EnumerateDevices<HMDDevice>().CreateDevice())) {
|
nuclear@1
|
90 fprintf(stderr, "no oculus rift devices found\n");
|
nuclear@4
|
91 } else {
|
nuclear@4
|
92 if(vr_ctx.ovr_hmd_dev->GetDeviceInfo(&info)) {
|
nuclear@4
|
93 printf("oculus device info:\n");
|
nuclear@4
|
94 printf(" name: %s\n", info.DisplayDeviceName);
|
nuclear@4
|
95 printf(" ipd: %f\n", info.InterpupillaryDistance);
|
nuclear@4
|
96 printf(" distortion: %f %f %f %f\n", info.DistortionK[0],
|
nuclear@4
|
97 info.DistortionK[1], info.DistortionK[2], info.DistortionK[3]);
|
nuclear@4
|
98 }
|
nuclear@1
|
99
|
nuclear@4
|
100 // calculate and store viewing parameters
|
nuclear@4
|
101 vr_ctx.info.width = info.HResolution;
|
nuclear@4
|
102 vr_ctx.info.height = info.VResolution;
|
nuclear@4
|
103 vr_ctx.info.aspect = (float)vr_ctx.info.width / (float)vr_ctx.info.height;
|
nuclear@4
|
104
|
nuclear@4
|
105 vr_ctx.info.ipd = info.InterpupillaryDistance;
|
nuclear@4
|
106 for(int i=0; i<4; i++) {
|
nuclear@4
|
107 vr_ctx.info.distort[i] = info.DistortionK[i];
|
nuclear@4
|
108 }
|
nuclear@12
|
109
|
nuclear@14
|
110 Util::Render::StereoConfig stereohelp;
|
nuclear@14
|
111 stereohelp.SetFullViewport(Util::Render::Viewport(0, 0, vr_ctx.info.width, vr_ctx.info.height));
|
nuclear@14
|
112 stereohelp.SetStereoMode(Util::Render::Stereo_LeftRight_Multipass);
|
nuclear@14
|
113 stereohelp.SetHMDInfo(info);
|
nuclear@14
|
114 stereohelp.SetDistortionFitPointVP(-1.0, 0.0);
|
nuclear@14
|
115
|
nuclear@14
|
116 vr_ctx.info.scale = stereohelp.GetDistortionScale();
|
nuclear@13
|
117
|
nuclear@13
|
118 float vhalfsz = vr_ctx.info.scale * info.VScreenSize * 0.5;
|
nuclear@13
|
119 vr_ctx.info.fov = 2.0 * atan(vhalfsz / info.EyeToScreenDistance);
|
nuclear@13
|
120
|
nuclear@13
|
121 vr_ctx.info.lens_center_offset = 0.5 - info.LensSeparationDistance / info.HScreenSize;
|
nuclear@13
|
122
|
nuclear@13
|
123 // calculate center of projection shift to match the lens positions
|
nuclear@13
|
124 float center_dist_meters = info.HScreenSize * 0.25;
|
nuclear@13
|
125 float proj_shift = center_dist_meters - info.LensSeparationDistance * 0.5;
|
nuclear@13
|
126 vr_ctx.info.proj_center_offset = 4.0 * proj_shift / info.HScreenSize;
|
nuclear@1
|
127 }
|
nuclear@1
|
128
|
nuclear@1
|
129 // get the sensor device
|
nuclear@4
|
130 if(vr_ctx.ovr_hmd_dev) {
|
nuclear@4
|
131 if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_hmd_dev->GetSensor())) {
|
nuclear@4
|
132 fprintf(stderr, "failed to get oculus sensor device\n");
|
nuclear@4
|
133 }
|
nuclear@4
|
134 } else {
|
nuclear@4
|
135 if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_devman->EnumerateDevices<SensorDevice>().CreateDevice())) {
|
nuclear@4
|
136 fprintf(stderr, "failed to get oculus sensor device\n");
|
nuclear@4
|
137 }
|
nuclear@1
|
138 }
|
nuclear@1
|
139
|
nuclear@4
|
140 if(vr_ctx.ovr_sensor_dev) {
|
nuclear@4
|
141 SensorInfo sinfo;
|
nuclear@4
|
142 if(vr_ctx.ovr_sensor_dev->GetDeviceInfo(&sinfo)) {
|
nuclear@4
|
143 printf("oculus sensor device info:\n");
|
nuclear@4
|
144 printf(" name: %s\n", sinfo.ProductName);
|
nuclear@4
|
145 }
|
nuclear@4
|
146
|
nuclear@4
|
147 vr_ctx.ovr_sfusion.AttachToSensor(vr_ctx.ovr_sensor_dev);
|
nuclear@1
|
148 }
|
nuclear@1
|
149 return true;
|
nuclear@1
|
150 }
|
nuclear@3
|
151
|
nuclear@13
|
152 #define EXTERNAL_SHADER
|
nuclear@13
|
153
|
nuclear@12
|
154 static bool init_sdr()
|
nuclear@12
|
155 {
|
nuclear@12
|
156 int status;
|
nuclear@12
|
157
|
nuclear@13
|
158 #ifdef EXTERNAL_SHADER
|
nuclear@13
|
159 FILE *fp = fopen("sdr.glsl", "rb");
|
nuclear@13
|
160 if(!fp) {
|
nuclear@13
|
161 perror("failed to load sdr.glsl");
|
nuclear@13
|
162 return false;
|
nuclear@13
|
163 }
|
nuclear@13
|
164 fseek(fp, 0, SEEK_END);
|
nuclear@13
|
165 long sz = ftell(fp);
|
nuclear@13
|
166 rewind(fp);
|
nuclear@13
|
167
|
nuclear@13
|
168 char *buf = (char*)alloca(sz + 1);
|
nuclear@13
|
169 fread(buf, 1, sz, fp);
|
nuclear@13
|
170 buf[sz] = 0;
|
nuclear@13
|
171 sdr_src = buf;
|
nuclear@13
|
172
|
nuclear@13
|
173 fclose(fp);
|
nuclear@13
|
174 #endif
|
nuclear@13
|
175
|
nuclear@12
|
176 unsigned int sdr = glCreateShader(GL_FRAGMENT_SHADER);
|
nuclear@12
|
177 glShaderSource(sdr, 1, &sdr_src, 0);
|
nuclear@12
|
178 glCompileShader(sdr);
|
nuclear@12
|
179 glGetShaderiv(sdr, GL_COMPILE_STATUS, &status);
|
nuclear@12
|
180 if(!status) {
|
nuclear@12
|
181 fprintf(stderr, "failed to compile distortion shader\n");
|
nuclear@14
|
182
|
nuclear@14
|
183 int loglen;
|
nuclear@14
|
184 glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &loglen);
|
nuclear@14
|
185
|
nuclear@14
|
186 if(loglen > 0) {
|
nuclear@14
|
187 char *log = (char*)alloca(loglen);
|
nuclear@14
|
188 glGetShaderInfoLog(sdr, loglen, &loglen, log);
|
nuclear@14
|
189 fprintf(stderr, "%s\n", log);
|
nuclear@14
|
190 }
|
nuclear@14
|
191
|
nuclear@12
|
192 return false;
|
nuclear@12
|
193 }
|
nuclear@12
|
194
|
nuclear@12
|
195 sdrprog = glCreateProgram();
|
nuclear@12
|
196 glAttachShader(sdrprog, sdr);
|
nuclear@12
|
197 glLinkProgram(sdrprog);
|
nuclear@12
|
198 if(!status) {
|
nuclear@12
|
199 fprintf(stderr, "failed to link distortion shader program\n");
|
nuclear@12
|
200 glDeleteShader(sdr);
|
nuclear@12
|
201 return false;
|
nuclear@12
|
202 }
|
nuclear@12
|
203
|
nuclear@12
|
204 int loc;
|
nuclear@12
|
205
|
nuclear@12
|
206 glUseProgram(sdrprog);
|
nuclear@12
|
207
|
nuclear@12
|
208 if((loc = glGetUniformLocation(sdrprog, "tex")) != -1) {
|
nuclear@12
|
209 glUniform1i(loc, 0);
|
nuclear@12
|
210 }
|
nuclear@13
|
211 if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) {
|
nuclear@13
|
212 glUniform1f(loc, 0);
|
nuclear@12
|
213 }
|
nuclear@12
|
214 if((loc = glGetUniformLocation(sdrprog, "scr_center")) != -1) {
|
nuclear@12
|
215 glUniform2f(loc, 0, 0);
|
nuclear@12
|
216 }
|
nuclear@12
|
217 if((loc = glGetUniformLocation(sdrprog, "scale")) != -1) {
|
nuclear@13
|
218 glUniform1f(loc, vr_ctx.info.scale);
|
nuclear@13
|
219 }
|
nuclear@13
|
220 if((loc = glGetUniformLocation(sdrprog, "aspect")) != -1) {
|
nuclear@13
|
221 printf("setting aspect: %f\n", vr_ctx.info.aspect / 2.0);
|
nuclear@13
|
222 glUniform1f(loc, vr_ctx.info.aspect / 2.0);
|
nuclear@12
|
223 }
|
nuclear@12
|
224 if((loc = glGetUniformLocation(sdrprog, "scale_in")) != -1) {
|
nuclear@12
|
225 glUniform2f(loc, 1, 1);
|
nuclear@12
|
226 }
|
nuclear@13
|
227 if((loc = glGetUniformLocation(sdrprog, "dist_factors")) != -1) {
|
nuclear@12
|
228 glUniform4f(loc, vr_ctx.info.distort[0], vr_ctx.info.distort[1],
|
nuclear@12
|
229 vr_ctx.info.distort[2], vr_ctx.info.distort[3]);
|
nuclear@12
|
230 }
|
nuclear@12
|
231
|
nuclear@12
|
232 return true;
|
nuclear@12
|
233 }
|
nuclear@12
|
234
|
nuclear@3
|
235 extern "C" int vr_get_width(void)
|
nuclear@3
|
236 {
|
nuclear@3
|
237 return vr_ctx.info.width;
|
nuclear@3
|
238 }
|
nuclear@3
|
239
|
nuclear@3
|
240 extern "C" int vr_get_height(void)
|
nuclear@3
|
241 {
|
nuclear@3
|
242 return vr_ctx.info.height;
|
nuclear@3
|
243 }
|
nuclear@3
|
244
|
nuclear@3
|
245 extern "C" float vr_get_fov(void)
|
nuclear@3
|
246 {
|
nuclear@3
|
247 return vr_ctx.info.fov;
|
nuclear@3
|
248 }
|
nuclear@3
|
249
|
nuclear@3
|
250 extern "C" float vr_get_aspect(void)
|
nuclear@3
|
251 {
|
nuclear@3
|
252 return vr_ctx.info.aspect;
|
nuclear@3
|
253 }
|
nuclear@3
|
254
|
nuclear@3
|
255 extern "C" void vr_set_eyedist(float ipd)
|
nuclear@3
|
256 {
|
nuclear@3
|
257 vr_ctx.info.ipd = ipd;
|
nuclear@3
|
258 }
|
nuclear@3
|
259
|
nuclear@3
|
260 extern "C" float vr_get_eyedist(void)
|
nuclear@3
|
261 {
|
nuclear@3
|
262 return vr_ctx.info.ipd;
|
nuclear@3
|
263 }
|
nuclear@3
|
264
|
nuclear@3
|
265 extern "C" void vr_set_distort(const float *coef)
|
nuclear@3
|
266 {
|
nuclear@3
|
267 memcpy(vr_ctx.info.distort, coef, sizeof vr_ctx.info.distort);
|
nuclear@3
|
268 }
|
nuclear@3
|
269
|
nuclear@3
|
270 extern "C" void vr_get_distort(float *coef)
|
nuclear@3
|
271 {
|
nuclear@3
|
272 memcpy(coef, vr_ctx.info.distort, sizeof vr_ctx.info.distort);
|
nuclear@3
|
273 }
|
nuclear@3
|
274
|
nuclear@3
|
275 extern "C" void vr_set_prediction_sec(float dt)
|
nuclear@3
|
276 {
|
nuclear@3
|
277 vr_ctx.ovr_sfusion.SetPrediction(dt);
|
nuclear@3
|
278 }
|
nuclear@3
|
279
|
nuclear@3
|
280 extern "C" float vr_get_prediction_sec(void)
|
nuclear@3
|
281 {
|
nuclear@3
|
282 return vr_ctx.ovr_sfusion.GetPredictionDelta();
|
nuclear@3
|
283 }
|
nuclear@3
|
284
|
nuclear@13
|
285 extern "C" void vr_get_view_matrix(float *res, int eye)
|
nuclear@13
|
286 {
|
nuclear@13
|
287 // TODO
|
nuclear@13
|
288 }
|
nuclear@13
|
289
|
nuclear@13
|
290 extern "C" void vr_get_proj_matrix(float *res, int eye)
|
nuclear@13
|
291 {
|
nuclear@13
|
292 static float eye_scale[] = {0.0, 1.0, -1.0};
|
nuclear@13
|
293
|
nuclear@13
|
294 Matrix4f proj = Matrix4f::PerspectiveRH(vr_ctx.info.fov, vr_ctx.info.aspect / 2.0, 0.3, 1000.0);
|
nuclear@13
|
295 proj = Matrix4f::Translation(vr_ctx.info.proj_center_offset * eye_scale[eye], 0, 0) * proj;
|
nuclear@13
|
296
|
nuclear@13
|
297 memcpy(res, proj.M[0], 16 * sizeof(float));
|
nuclear@13
|
298 }
|
nuclear@13
|
299
|
nuclear@3
|
300 extern "C" void vr_get_translation(float *offs)
|
nuclear@3
|
301 {
|
nuclear@3
|
302 // current oculus devkit doesn't do translation
|
nuclear@3
|
303 offs[0] = offs[1] = offs[2] = 0.0f;
|
nuclear@3
|
304 }
|
nuclear@3
|
305
|
nuclear@3
|
306 extern "C" void vr_get_rotation(float *quat)
|
nuclear@3
|
307 {
|
nuclear@3
|
308 Quatf oq = vr_ctx.ovr_sfusion.GetPredictedOrientation();
|
nuclear@3
|
309 quat[0] = oq.x;
|
nuclear@3
|
310 quat[1] = oq.y;
|
nuclear@3
|
311 quat[2] = oq.z;
|
nuclear@3
|
312 quat[3] = oq.w;
|
nuclear@3
|
313 }
|
nuclear@3
|
314
|
nuclear@3
|
315 extern "C" void vr_get_rotation_euler(float *euler)
|
nuclear@3
|
316 {
|
nuclear@3
|
317 Quatf oq = vr_ctx.ovr_sfusion.GetPredictedOrientation();
|
nuclear@3
|
318 oq.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(euler + 1, euler, euler + 2);
|
nuclear@3
|
319 }
|
nuclear@12
|
320
|
nuclear@12
|
321 extern "C" void vr_draw_eye(unsigned int tex, int eye)
|
nuclear@12
|
322 {
|
nuclear@12
|
323 static const float rects[3][4] = {
|
nuclear@12
|
324 {-1, -1, 1, 1},
|
nuclear@12
|
325 {-1, -1, 0, 1},
|
nuclear@12
|
326 {0, -1, 1, 1}
|
nuclear@12
|
327 };
|
nuclear@12
|
328 static const float offs_scale[3] = {0.0, -1.0, 1.0};
|
nuclear@12
|
329
|
nuclear@12
|
330 glPushAttrib(GL_ENABLE_BIT);
|
nuclear@12
|
331 glDisable(GL_DEPTH_TEST);
|
nuclear@12
|
332 glDisable(GL_LIGHTING);
|
nuclear@12
|
333 glEnable(GL_TEXTURE_2D);
|
nuclear@12
|
334
|
nuclear@12
|
335 glMatrixMode(GL_MODELVIEW);
|
nuclear@12
|
336 glPushMatrix();
|
nuclear@12
|
337 glLoadIdentity();
|
nuclear@12
|
338
|
nuclear@12
|
339 glMatrixMode(GL_PROJECTION);
|
nuclear@12
|
340 glPushMatrix();
|
nuclear@12
|
341 glLoadIdentity();
|
nuclear@12
|
342
|
nuclear@12
|
343 glUseProgram(sdrprog);
|
nuclear@12
|
344
|
nuclear@13
|
345 if(sdrprog) {
|
nuclear@13
|
346 int loc;
|
nuclear@13
|
347 if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) {
|
nuclear@13
|
348 float offset = vr_ctx.info.lens_center_offset * offs_scale[eye];
|
nuclear@13
|
349 glUniform1f(loc, offset);
|
nuclear@13
|
350 }
|
nuclear@12
|
351 }
|
nuclear@12
|
352
|
nuclear@12
|
353 glBindTexture(GL_TEXTURE_2D, tex);
|
nuclear@12
|
354 glBegin(GL_QUADS);
|
nuclear@12
|
355 glColor4f(1, 1, 1, 1);
|
nuclear@12
|
356 glTexCoord2f(0, 0); glVertex2f(rects[eye][0], rects[eye][1]);
|
nuclear@12
|
357 glTexCoord2f(1, 0); glVertex2f(rects[eye][2], rects[eye][1]);
|
nuclear@12
|
358 glTexCoord2f(1, 1); glVertex2f(rects[eye][2], rects[eye][3]);
|
nuclear@12
|
359 glTexCoord2f(0, 1); glVertex2f(rects[eye][0], rects[eye][3]);
|
nuclear@12
|
360 glEnd();
|
nuclear@12
|
361
|
nuclear@12
|
362 glUseProgram(0);
|
nuclear@12
|
363
|
nuclear@12
|
364 glPopMatrix();
|
nuclear@12
|
365 glMatrixMode(GL_MODELVIEW);
|
nuclear@12
|
366 glPopMatrix();
|
nuclear@12
|
367
|
nuclear@12
|
368 glPopAttrib();
|
nuclear@12
|
369 }
|