rev |
line source |
nuclear@0
|
1 #include "vr_impl.h"
|
nuclear@0
|
2
|
nuclear@0
|
3 #ifdef USE_OPENHMD
|
nuclear@0
|
4 #include <stdio.h>
|
nuclear@0
|
5 #include <stdlib.h>
|
nuclear@0
|
6 #include <openhmd/openhmd.h>
|
nuclear@0
|
7 #include "opt.h"
|
nuclear@0
|
8
|
nuclear@0
|
9 /* a noble spirit embiggens the framebuffer to avoid aliasing in the middle */
|
nuclear@1
|
10 #define FB_EMBIGGEN 1.5
|
nuclear@0
|
11
|
nuclear@0
|
12 static ohmd_context *ctx;
|
nuclear@0
|
13 static ohmd_device *dev;
|
nuclear@0
|
14 static void *optdb;
|
nuclear@0
|
15 static int new_frame = 1;
|
nuclear@0
|
16
|
nuclear@0
|
17 static int disp_width, disp_height;
|
nuclear@0
|
18 static float ipd;
|
nuclear@0
|
19
|
nuclear@0
|
20 static struct {
|
nuclear@0
|
21 unsigned int id;
|
nuclear@0
|
22 float umin, umax;
|
nuclear@0
|
23 float vmin, vmax;
|
nuclear@0
|
24 } eye_tex[2];
|
nuclear@0
|
25
|
nuclear@0
|
26
|
nuclear@0
|
27 static int init(void)
|
nuclear@0
|
28 {
|
nuclear@0
|
29 int i, num_hmds;
|
nuclear@0
|
30
|
nuclear@0
|
31 if(!(ctx = ohmd_ctx_create())) {
|
nuclear@0
|
32 fprintf(stderr, "failed to create OpenHMD context\n");
|
nuclear@0
|
33 ohmd_ctx_destroy(ctx);
|
nuclear@0
|
34 return -1;
|
nuclear@0
|
35 }
|
nuclear@0
|
36 if(!(num_hmds = ohmd_ctx_probe(ctx))) {
|
nuclear@0
|
37 fprintf(stderr, "no HMDs detected\n");
|
nuclear@0
|
38 return -1;
|
nuclear@0
|
39 }
|
nuclear@0
|
40
|
nuclear@0
|
41 for(i=0; i<num_hmds; i++) {
|
nuclear@0
|
42 const char *vendor = ohmd_list_gets(ctx, i, OHMD_VENDOR);
|
nuclear@0
|
43 const char *product = ohmd_list_gets(ctx, i, OHMD_PRODUCT);
|
nuclear@0
|
44 const char *devpath = ohmd_list_gets(ctx, i, OHMD_PATH);
|
nuclear@0
|
45
|
nuclear@0
|
46 printf("[%d] %s - %s (path: %s)\n", i, vendor, product, devpath);
|
nuclear@0
|
47 }
|
nuclear@0
|
48
|
nuclear@0
|
49 printf("opening device 0\n");
|
nuclear@0
|
50
|
nuclear@0
|
51 if(!(dev = ohmd_list_open_device(ctx, 0))) {
|
nuclear@0
|
52 fprintf(stderr, "failed to open device 0: %s\n", ohmd_ctx_get_error(ctx));
|
nuclear@0
|
53 return -1;
|
nuclear@0
|
54 }
|
nuclear@0
|
55
|
nuclear@0
|
56 ohmd_device_geti(dev, OHMD_SCREEN_HORIZONTAL_SIZE, &disp_width);
|
nuclear@0
|
57 ohmd_device_geti(dev, OHMD_SCREEN_VERTICAL_SIZE, &disp_height);
|
nuclear@0
|
58 ohmd_device_getf(dev, OHMD_EYE_IPD, &ipd);
|
nuclear@0
|
59
|
nuclear@0
|
60 if((optdb = create_options())) {
|
nuclear@0
|
61 set_option_int(optdb, VR_OPT_DISPLAY_WIDTH, disp_width);
|
nuclear@0
|
62 set_option_int(optdb, VR_OPT_DISPLAY_HEIGHT, disp_height);
|
nuclear@0
|
63 set_option_float(optdb, VR_OPT_IPD, ipd);
|
nuclear@0
|
64
|
nuclear@0
|
65 set_option_int(optdb, VR_OPT_LEYE_XRES, (int)(disp_width / 2.0 * FB_EMBIGGEN));
|
nuclear@0
|
66 set_option_int(optdb, VR_OPT_LEYE_YRES, (int)(disp_height * FB_EMBIGGEN));
|
nuclear@0
|
67 set_option_int(optdb, VR_OPT_REYE_XRES, (int)(disp_width / 2.0 * FB_EMBIGGEN));
|
nuclear@0
|
68 set_option_int(optdb, VR_OPT_REYE_YRES, (int)(disp_height * FB_EMBIGGEN));
|
nuclear@0
|
69 }
|
nuclear@0
|
70
|
nuclear@0
|
71 return 0;
|
nuclear@0
|
72 }
|
nuclear@0
|
73
|
nuclear@0
|
74 static void cleanup(void)
|
nuclear@0
|
75 {
|
nuclear@0
|
76 if(ctx) {
|
nuclear@0
|
77 ohmd_ctx_destroy(ctx);
|
nuclear@0
|
78 }
|
nuclear@0
|
79 }
|
nuclear@0
|
80
|
nuclear@0
|
81
|
nuclear@0
|
82 static int set_option(const char *opt, enum opt_type type, void *valp)
|
nuclear@0
|
83 {
|
nuclear@0
|
84 switch(type) {
|
nuclear@0
|
85 case OTYPE_INT:
|
nuclear@0
|
86 set_option_int(optdb, opt, *(int*)valp);
|
nuclear@0
|
87 break;
|
nuclear@0
|
88
|
nuclear@0
|
89 case OTYPE_FLOAT:
|
nuclear@0
|
90 set_option_float(optdb, opt, *(float*)valp);
|
nuclear@0
|
91 break;
|
nuclear@0
|
92 }
|
nuclear@0
|
93 return 0;
|
nuclear@0
|
94 }
|
nuclear@0
|
95
|
nuclear@0
|
96 static int get_option(const char *opt, enum opt_type type, void *valp)
|
nuclear@0
|
97 {
|
nuclear@0
|
98 switch(type) {
|
nuclear@0
|
99 case OTYPE_INT:
|
nuclear@0
|
100 return get_option_int(optdb, opt, valp);
|
nuclear@0
|
101 case OTYPE_FLOAT:
|
nuclear@0
|
102 return get_option_float(optdb, opt, valp);
|
nuclear@0
|
103 }
|
nuclear@0
|
104 return -1;
|
nuclear@0
|
105 }
|
nuclear@0
|
106
|
nuclear@0
|
107 static int translation(int eye, float *vec)
|
nuclear@0
|
108 {
|
nuclear@0
|
109 float xform[16];
|
nuclear@0
|
110
|
nuclear@0
|
111 view_matrix(eye, xform);
|
nuclear@0
|
112
|
nuclear@0
|
113 vec[0] = xform[3];
|
nuclear@0
|
114 vec[1] = xform[7];
|
nuclear@0
|
115 vec[2] = xform[11];
|
nuclear@0
|
116 return 0;
|
nuclear@0
|
117 }
|
nuclear@0
|
118
|
nuclear@0
|
119 static int rotation(int eye, float *quat)
|
nuclear@0
|
120 {
|
nuclear@0
|
121 if(!dev) {
|
nuclear@0
|
122 quat[0] = quat[1] = quat[2] = 0.0f;
|
nuclear@0
|
123 quat[3] = 1.0f;
|
nuclear@0
|
124 return -1;
|
nuclear@0
|
125 }
|
nuclear@0
|
126
|
nuclear@0
|
127 ohmd_device_getf(dev, OHMD_ROTATION_QUAT, quat);
|
nuclear@0
|
128 return 0;
|
nuclear@0
|
129 }
|
nuclear@0
|
130
|
nuclear@0
|
131
|
nuclear@0
|
132 static void view_matrix(int eye, float *mat)
|
nuclear@0
|
133 {
|
nuclear@0
|
134 ohmd_device_getf(dev, OHMD_LEFT_EYE_GL_MODELVIEW_MATRIX + eye, mat);
|
nuclear@0
|
135 }
|
nuclear@0
|
136
|
nuclear@0
|
137 static void proj_matrix(int eye, float znear, float zfar, float *mat)
|
nuclear@0
|
138 {
|
nuclear@0
|
139 ohmd_device_setf(dev, OHMD_PROJECTION_ZNEAR, znear);
|
nuclear@0
|
140 ohmd_device_setf(dev, OHMD_PROJECTION_ZFAR, zfar);
|
nuclear@0
|
141 ohmd_device_getf(dev, OHMD_LEFT_EYE_GL_PROJECTION_MATRIX + eye, mat);
|
nuclear@0
|
142 }
|
nuclear@0
|
143
|
nuclear@0
|
144 static void begin(int eye)
|
nuclear@0
|
145 {
|
nuclear@0
|
146 if(new_frame) {
|
nuclear@0
|
147 ohmd_ctx_update(ctx);
|
nuclear@0
|
148 new_frame = 0;
|
nuclear@0
|
149 }
|
nuclear@0
|
150 }
|
nuclear@0
|
151
|
nuclear@0
|
152 static int present(void)
|
nuclear@0
|
153 {
|
nuclear@0
|
154 new_frame = 1;
|
nuclear@0
|
155 return 0;
|
nuclear@0
|
156 }
|
nuclear@0
|
157
|
nuclear@0
|
158 static void set_eye_texture(int eye, unsigned int tex, float umin, float vmin, float umax, float vmax)
|
nuclear@0
|
159 {
|
nuclear@0
|
160 eye_tex[eye].id = tex;
|
nuclear@0
|
161 eye_tex[eye].umin = umin;
|
nuclear@0
|
162 eye_tex[eye].umax = umax;
|
nuclear@0
|
163 eye_tex[eye].vmin = vmin;
|
nuclear@0
|
164 eye_tex[eye].vmax = vmax;
|
nuclear@0
|
165 }
|
nuclear@0
|
166
|
nuclear@0
|
167 static void recenter(void)
|
nuclear@0
|
168 {
|
nuclear@0
|
169 /* TODO does OHMD support the magnetometer? */
|
nuclear@0
|
170 }
|
nuclear@0
|
171
|
nuclear@0
|
172
|
nuclear@0
|
173 struct vr_module *vr_module_openhmd(void)
|
nuclear@0
|
174 {
|
nuclear@0
|
175 static struct vr_module m;
|
nuclear@0
|
176
|
nuclear@0
|
177 if(!m.init) {
|
nuclear@0
|
178 m.name = "openhmd";
|
nuclear@0
|
179 m.init = init;
|
nuclear@0
|
180 m.cleanup = cleanup;
|
nuclear@0
|
181 m.set_option = set_option;
|
nuclear@0
|
182 m.get_option = get_option;
|
nuclear@0
|
183 m.view_matrix = view_matrix;
|
nuclear@0
|
184 m.proj_matrix = proj_matrix;
|
nuclear@0
|
185 m.begin = begin;
|
nuclear@0
|
186 m.present = present;
|
nuclear@0
|
187 m.set_eye_texture = set_eye_texture;
|
nuclear@0
|
188 m.recenter = recenter;
|
nuclear@0
|
189 }
|
nuclear@0
|
190 }
|
nuclear@0
|
191
|
nuclear@0
|
192 #else /* don't use OpenHMD */
|
nuclear@0
|
193
|
nuclear@0
|
194 static int init(void)
|
nuclear@0
|
195 {
|
nuclear@0
|
196 return -1;
|
nuclear@0
|
197 }
|
nuclear@0
|
198
|
nuclear@0
|
199 struct vr_module *vr_module_openhmd(void)
|
nuclear@0
|
200 {
|
nuclear@0
|
201 static struct vr_module m;
|
nuclear@0
|
202
|
nuclear@0
|
203 if(!m.init) {
|
nuclear@0
|
204 m.name = "openhmd";
|
nuclear@0
|
205 m.init = init;
|
nuclear@0
|
206 }
|
nuclear@0
|
207 return &m;
|
nuclear@0
|
208 }
|
nuclear@0
|
209
|
nuclear@0
|
210 #endif /* USE_OPENHMD */
|