libgoatvr
changeset 8:3d9ec6fe97d7
- added distortion mesh generation for the OpenHMD module (unfinished)
- changed internal implementation function naming to use the vrimp_ prefix
- added an opengl helper function to load extension entry points
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 20 Sep 2014 13:22:53 +0300 |
parents | 6896f9cf9621 |
children | d12592558809 |
files | example/src/main.c src/mathutil.c src/mathutil.h src/mesh.c src/mesh.h src/opengl.c src/opengl.h src/vr.c src/vr.h src/vr_openhmd.c |
diffstat | 10 files changed, 261 insertions(+), 25 deletions(-) [+] |
line diff
1.1 --- a/example/src/main.c Fri Sep 19 15:16:51 2014 +0300 1.2 +++ b/example/src/main.c Sat Sep 20 13:22:53 2014 +0300 1.3 @@ -139,8 +139,8 @@ 1.4 void display(void) 1.5 { 1.6 int i; 1.7 - float proj_mat[16]; 1.8 - float rot_mat[16], view_mat[16]; 1.9 + float proj_mat[16] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; 1.10 + float view_mat[16] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; 1.11 1.12 /* start drawing onto our texture render target */ 1.13 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 1.14 @@ -164,7 +164,7 @@ 1.15 * use glLoadTransposeMatrixf instead of glLoadMatrixf to load it. 1.16 */ 1.17 if(vr_proj_matrix(i, 0.5, 500.0, proj_mat)) { 1.18 - glLoadTransposeMatrixf(proj_mat); 1.19 + glLoadMatrixf(proj_mat); 1.20 } else { 1.21 glLoadIdentity(); 1.22 gluPerspective(50.0, (float)fb_width / 2.0 / (float)fb_height, 0.5, 500.0); 1.23 @@ -176,7 +176,7 @@ 1.24 */ 1.25 glMatrixMode(GL_MODELVIEW); 1.26 vr_view_matrix(i, view_mat); 1.27 - glLoadTransposeMatrixf(view_mat); 1.28 + glLoadMatrixf(view_mat); 1.29 /* move the camera to the eye level of the user */ 1.30 glTranslatef(0, -vr_get_optf(VR_OPT_EYE_HEIGHT), 0); 1.31
2.1 --- a/src/mathutil.c Fri Sep 19 15:16:51 2014 +0300 2.2 +++ b/src/mathutil.c Sat Sep 20 13:22:53 2014 +0300 2.3 @@ -6,7 +6,7 @@ 2.4 2.5 static const float idmat[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; 2.6 2.7 -void rotation_matrix(const float *quat, float *matrix) 2.8 +void vrimp_rotation_matrix(const float *quat, float *matrix) 2.9 { 2.10 matrix[0] = 1.0 - 2.0 * quat[1] * quat[1] - 2.0 * quat[2] * quat[2]; 2.11 matrix[1] = 2.0 * quat[0] * quat[1] + 2.0 * quat[3] * quat[2]; 2.12 @@ -26,10 +26,10 @@ 2.13 matrix[12] = matrix[13] = matrix[14] = 0.0f; 2.14 matrix[15] = 1.0f; 2.15 2.16 - transpose_matrix(matrix); 2.17 + vrimp_transpose_matrix(matrix); 2.18 } 2.19 2.20 -void translation_matrix(const float *vec, float *matrix) 2.21 +void vrimp_translation_matrix(const float *vec, float *matrix) 2.22 { 2.23 memcpy(matrix, idmat, sizeof idmat); 2.24 matrix[12] = vec[0]; 2.25 @@ -37,7 +37,7 @@ 2.26 matrix[14] = vec[2]; 2.27 } 2.28 2.29 -void mult_matrix(float *dest, const float *m1, const float *m2) 2.30 +void vrimp_mult_matrix(float *dest, const float *m1, const float *m2) 2.31 { 2.32 int i, j; 2.33 float tmp[16]; 2.34 @@ -51,7 +51,7 @@ 2.35 memcpy(dest, tmp, sizeof tmp); 2.36 } 2.37 2.38 -void transpose_matrix(float *matrix) 2.39 +void vrimp_transpose_matrix(float *matrix) 2.40 { 2.41 int i, j; 2.42 float tmp[16]; 2.43 @@ -64,7 +64,7 @@ 2.44 memcpy(matrix, tmp, sizeof tmp); 2.45 } 2.46 2.47 -void print_matrix(const float *matrix) 2.48 +void vrimp_print_matrix(const float *matrix) 2.49 { 2.50 int i, j; 2.51
3.1 --- a/src/mathutil.h Fri Sep 19 15:16:51 2014 +0300 3.2 +++ b/src/mathutil.h Sat Sep 20 13:22:53 2014 +0300 3.3 @@ -1,13 +1,13 @@ 3.4 #ifndef MATHUTIL_H_ 3.5 #define MATHUTIL_H_ 3.6 3.7 -void rotation_matrix(const float *quat, float *matrix); 3.8 -void translation_matrix(const float *vec, float *matrix); 3.9 +void vrimp_rotation_matrix(const float *quat, float *matrix); 3.10 +void vrimp_translation_matrix(const float *vec, float *matrix); 3.11 3.12 -void mult_matrix(float *dest, const float *m1, const float *m2); 3.13 +void vrimp_mult_matrix(float *dest, const float *m1, const float *m2); 3.14 3.15 -void transpose_matrix(float *matrix); 3.16 +void vrimp_transpose_matrix(float *matrix); 3.17 3.18 -void print_matrix(const float *matrix); 3.19 +void vrimp_print_matrix(const float *matrix); 3.20 3.21 #endif /* MATHUTIL_H_ */
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/mesh.c Sat Sep 20 13:22:53 2014 +0300 4.3 @@ -0,0 +1,186 @@ 4.4 +#include <stdio.h> 4.5 +#include <stdlib.h> 4.6 +#include <string.h> 4.7 +#include "opengl.h" 4.8 +#include "mesh.h" 4.9 + 4.10 +static void distort_texcoords(float *tc, float aspect, float lens_center_offset, float scale, 4.11 + const float *dist_factors); 4.12 +static float barrel_scale(float rad, const float *k); 4.13 + 4.14 +/* let's avoid a glew dependency in the library just for this */ 4.15 +#ifndef GL_ARRAY_BUFFER 4.16 +#define GL_ARRAY_BUFFER 0x8892 4.17 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 4.18 +#define GL_STATIC_DRAW 0x88E4 4.19 +#endif 4.20 + 4.21 +#if !defined(GL_VERSION_1_5) || !defined(GL_GLEXT_PROTOTYPES) 4.22 +static void (*glGenBuffers)(GLsizei, GLuint*); 4.23 +static void (*glDeleteBuffers)(GLsizei, GLuint*); 4.24 +static void (*glBufferData)(GLenum, unsigned int, const GLvoid*, GLenum); 4.25 +static void (*glBindBuffer)(GLenum, GLuint); 4.26 +#endif 4.27 + 4.28 +int vrimp_mesh_init(struct mesh *m) 4.29 +{ 4.30 + m->prim = GL_TRIANGLES; 4.31 + 4.32 + m->varr = 0; 4.33 + m->iarr = 0; 4.34 + m->num_verts = m->num_faces = 0; 4.35 + m->vbo = m->ibo = 0; 4.36 + 4.37 + if(!glGenBuffers) { 4.38 + glGenBuffers = vrimp_glfunc("glGenBuffersARB"); 4.39 + glDeleteBuffers = vrimp_glfunc("glDeleteBuffersARB"); 4.40 + glBufferData = vrimp_glfunc("glBufferDataARB"); 4.41 + glBindBuffer = vrimp_glfunc("glBindBufferARB"); 4.42 + 4.43 + if(!(glGenBuffers && glDeleteBuffers && glBufferData && glBindBuffer)) { 4.44 + fprintf(stderr, "Failed to load VBO functions\n"); 4.45 + return -1; 4.46 + } 4.47 + } 4.48 + 4.49 + return 0; 4.50 +} 4.51 + 4.52 +void vrimp_mesh_destroy(struct mesh *m) 4.53 +{ 4.54 + free(m->varr); 4.55 + free(m->iarr); 4.56 + 4.57 + if(m->vbo) glDeleteBuffers(1, &m->vbo); 4.58 + if(m->ibo) glDeleteBuffers(1, &m->ibo); 4.59 +} 4.60 + 4.61 +void vrimp_mesh_draw(struct mesh *m) 4.62 +{ 4.63 + glEnableClientState(GL_VERTEX_ARRAY); 4.64 + glEnableClientState(GL_TEXTURE_COORD_ARRAY); 4.65 + 4.66 + glBindBuffer(GL_ARRAY_BUFFER, m->vbo); 4.67 + glVertexPointer(3, GL_FLOAT, sizeof(struct vertex), 0); 4.68 + glTexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), (void*)offsetof(struct vertex, tx)); 4.69 + 4.70 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo); 4.71 + glDrawElements(GL_TRIANGLES, m->num_faces * 3, GL_UNSIGNED_INT, 0); 4.72 + 4.73 + glBindBuffer(GL_ARRAY_BUFFER, 0); 4.74 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 4.75 + 4.76 + glDisableClientState(GL_VERTEX_ARRAY); 4.77 + glDisableClientState(GL_TEXTURE_COORD_ARRAY); 4.78 +} 4.79 + 4.80 +int vrimp_mesh_barrel_distortion(struct mesh *m, int usub, int vsub, float aspect, 4.81 + float lens_center_offset, float scale, const float *dist_factors, 4.82 + float tex_scale_x, float tex_scale_y) 4.83 +{ 4.84 + int i, j; 4.85 + int uverts, vverts; 4.86 + int num_verts, num_quads, num_tris; 4.87 + struct vertex *varr, *vptr; 4.88 + unsigned int *iarr, *iptr; 4.89 + float du, dv; 4.90 + 4.91 + uverts = usub + 1; 4.92 + vverts = vsub + 1; 4.93 + 4.94 + num_verts = uverts * vverts; 4.95 + num_quads = usub * vsub; 4.96 + num_tris = num_quads * 2; 4.97 + 4.98 + if(!(varr = malloc(num_verts * sizeof *varr))) { 4.99 + return -1; 4.100 + } 4.101 + if(!(iarr = malloc(num_tris * 3 * sizeof *iarr))) { 4.102 + free(varr); 4.103 + return -1; 4.104 + } 4.105 + 4.106 + du = 1.0 / (float)usub; 4.107 + dv = 1.0 / (float)vsub; 4.108 + 4.109 + vptr = varr; 4.110 + for(i=0; i<vverts; i++) { 4.111 + float v = (float)i * dv; 4.112 + float y = 2.0 * v - 1.0; 4.113 + 4.114 + for(j=0; j<uverts; j++) { 4.115 + float u = (float)j * du; 4.116 + float x = 2.0 * u - 1.0; 4.117 + float tc[2]; 4.118 + tc[0] = u; 4.119 + tc[1] = v; 4.120 + 4.121 + distort_texcoords(tc, aspect, lens_center_offset, scale, dist_factors); 4.122 + 4.123 + vptr->x = x; 4.124 + vptr->y = y; 4.125 + vptr->z = 0; 4.126 + vptr->tx = tc[0] * tex_scale_x; 4.127 + vptr->ty = tc[1] * tex_scale_y; 4.128 + vptr++; 4.129 + } 4.130 + } 4.131 + 4.132 + iptr = iarr; 4.133 + for(i=0; i<vsub; i++) { 4.134 + for(j=0; j<usub; j++) { 4.135 + *iptr++ = i * uverts + j; 4.136 + *iptr++ = (i + 1) * uverts + j; 4.137 + *iptr++ = (i + 1) * uverts + (j + 1); 4.138 + 4.139 + *iptr++ = i * uverts + j; 4.140 + *iptr++ = (i + 1) * uverts + (j + 1); 4.141 + *iptr++ = i * uverts + (j + 1); 4.142 + } 4.143 + } 4.144 + 4.145 + glGenBuffers(1, &m->vbo); 4.146 + glGenBuffers(1, &m->ibo); 4.147 + glBindBuffer(GL_ARRAY_BUFFER, m->vbo); 4.148 + glBufferData(GL_ARRAY_BUFFER, num_verts * sizeof *varr, varr, GL_STATIC_DRAW); 4.149 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo); 4.150 + glBufferData(GL_ELEMENT_ARRAY_BUFFER, num_tris * 3 * sizeof *iarr, iarr, GL_STATIC_DRAW); 4.151 + 4.152 + m->prim = GL_TRIANGLES; 4.153 + m->num_verts = num_verts; 4.154 + m->num_faces = num_tris; 4.155 + return 0; 4.156 +} 4.157 + 4.158 +static void distort_texcoords(float *tc, float aspect, float lens_center_offset, float scale, 4.159 + const float *dist_factors) 4.160 +{ 4.161 + /* map tc [0, 1] -> [-1, 1] */ 4.162 + float ptx = tc[0] * 2.0 - 1.0; 4.163 + float pty = tc[1] * 2.0 - 1.0; 4.164 + float rad; 4.165 + 4.166 + ptx += lens_center_offset * 2.0; 4.167 + pty /= aspect; /* correct for aspect ratio */ 4.168 + 4.169 + rad = barrel_scale(ptx * ptx + pty * pty, dist_factors); 4.170 + ptx *= rad; /* scale the point by the computer distortion radius */ 4.171 + pty *= rad; 4.172 + 4.173 + ptx /= scale; 4.174 + pty /= scale; 4.175 + 4.176 + pty *= aspect; 4.177 + ptx -= lens_center_offset * 2.0; 4.178 + 4.179 + /* map back to range [0, 1] */ 4.180 + tc[0] = ptx * 0.5 + 0.5; 4.181 + tc[1] = pty * 0.5 + 0.5; 4.182 +} 4.183 + 4.184 +static float barrel_scale(float rad, const float *k) 4.185 +{ 4.186 + float radsq = rad * rad; 4.187 + float radquad = radsq * radsq; 4.188 + return k[0] + k[1] * radsq + k[2] * radquad + k[3] * radquad * radsq; 4.189 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/mesh.h Sat Sep 20 13:22:53 2014 +0300 5.3 @@ -0,0 +1,27 @@ 5.4 +#ifndef MESH_H_ 5.5 +#define MESH_H_ 5.6 + 5.7 +struct vertex { 5.8 + float x, y, z; 5.9 + float tx, ty; 5.10 +}; 5.11 + 5.12 +struct mesh { 5.13 + int prim; 5.14 + struct vertex *varr; 5.15 + unsigned int *iarr; 5.16 + int num_verts, num_faces; 5.17 + unsigned int vbo, ibo; 5.18 +}; 5.19 + 5.20 +int vrimp_mesh_init(struct mesh *m); 5.21 +void vrimp_mesh_destroy(struct mesh *m); 5.22 + 5.23 +void vrimp_mesh_draw(struct mesh *m); 5.24 + 5.25 +int vrimp_mesh_barrel_distortion(struct mesh *m, int usub, int vsub, float aspect, 5.26 + float lens_center_offset, float scale, const float *dist_factors, 5.27 + float tex_scale_x, float tex_scale_y); 5.28 + 5.29 + 5.30 +#endif /* MESH_H_ */
6.1 --- a/src/opengl.c Fri Sep 19 15:16:51 2014 +0300 6.2 +++ b/src/opengl.c Sat Sep 20 13:22:53 2014 +0300 6.3 @@ -1,18 +1,28 @@ 6.4 #include "opengl.h" 6.5 6.6 #ifdef __unix__ 6.7 -void vr_gl_swap_buffers(void) 6.8 +void vrimp_swap_buffers(void) 6.9 { 6.10 Display *dpy = glXGetCurrentDisplay(); 6.11 Drawable win = glXGetCurrentDrawable(); 6.12 glXSwapBuffers(dpy, win); 6.13 } 6.14 + 6.15 +void (*vrimp_glfunc(const char *name))() 6.16 +{ 6.17 + return glXGetProcAddress((const unsigned char*)name); 6.18 +} 6.19 #endif 6.20 6.21 #ifdef WIN32 6.22 -void vr_gl_swap_buffers(void) 6.23 +void vrimp_swap_buffers(void) 6.24 { 6.25 HDC dc = wglGetCurrentDC(); 6.26 SwapBuffers(dc); 6.27 } 6.28 + 6.29 +void (*vrimp_glfunc(const char *name))() 6.30 +{ 6.31 + return wglGetProcAddress(name); 6.32 +} 6.33 #endif
7.1 --- a/src/opengl.h Fri Sep 19 15:16:51 2014 +0300 7.2 +++ b/src/opengl.h Sat Sep 20 13:22:53 2014 +0300 7.3 @@ -16,6 +16,8 @@ 7.4 #include <GL/glx.h> 7.5 #endif 7.6 7.7 -void vr_gl_swap_buffers(void); 7.8 +void vrimp_swap_buffers(void); 7.9 + 7.10 +void (*vrimp_glfunc(const char *name))(); 7.11 7.12 #endif /* VR_OPENGL_H_ */
8.1 --- a/src/vr.c Fri Sep 19 15:16:51 2014 +0300 8.2 +++ b/src/vr.c Sat Sep 20 13:22:53 2014 +0300 8.3 @@ -198,9 +198,9 @@ 8.4 offs[1] = -offs[1]; 8.5 offs[2] = -offs[2]; 8.6 8.7 - translation_matrix(offs, tmat); 8.8 - rotation_matrix(quat, rmat); 8.9 - mult_matrix(mat, tmat, rmat); 8.10 + vrimp_translation_matrix(offs, tmat); 8.11 + vrimp_rotation_matrix(quat, rmat); 8.12 + vrimp_mult_matrix(mat, tmat, rmat); 8.13 return 1; 8.14 } 8.15 8.16 @@ -238,7 +238,7 @@ 8.17 8.18 if(!res) { 8.19 fallback_present(); 8.20 - vr_gl_swap_buffers(); 8.21 + vrimp_swap_buffers(); 8.22 } 8.23 return 0; 8.24 }
9.1 --- a/src/vr.h Fri Sep 19 15:16:51 2014 +0300 9.2 +++ b/src/vr.h Sat Sep 20 13:22:53 2014 +0300 9.3 @@ -1,16 +1,18 @@ 9.4 #ifndef VR_H_ 9.5 #define VR_H_ 9.6 9.7 +/* unit: pixels */ 9.8 #define VR_OPT_DISPLAY_WIDTH "display-xres" 9.9 #define VR_OPT_DISPLAY_HEIGHT "display-yres" 9.10 #define VR_OPT_LEYE_XRES "left-eye-xres" 9.11 #define VR_OPT_LEYE_YRES "left-eye-yres" 9.12 #define VR_OPT_REYE_XRES "right-eye-xres" 9.13 #define VR_OPT_REYE_YRES "right-eye-yres" 9.14 +#define VR_OPT_WIN_XOFFS "win-xoffset" 9.15 +#define VR_OPT_WIN_YOFFS "win-yoffset" 9.16 +/* unit: meters */ 9.17 #define VR_OPT_EYE_HEIGHT "eye-height" 9.18 #define VR_OPT_IPD "ipd" 9.19 -#define VR_OPT_WIN_XOFFS "win-xoffset" 9.20 -#define VR_OPT_WIN_YOFFS "win-yoffset" 9.21 9.22 enum { 9.23 VR_EYE_LEFT,
10.1 --- a/src/vr_openhmd.c Fri Sep 19 15:16:51 2014 +0300 10.2 +++ b/src/vr_openhmd.c Sat Sep 20 13:22:53 2014 +0300 10.3 @@ -27,6 +27,7 @@ 10.4 static int init(void) 10.5 { 10.6 int i, num_hmds; 10.7 + float distort_k[6]; 10.8 10.9 if(!(ctx = ohmd_ctx_create())) { 10.10 fprintf(stderr, "failed to create OpenHMD context\n"); 10.11 @@ -69,6 +70,14 @@ 10.12 set_option_int(optdb, VR_OPT_REYE_YRES, (int)(disp_height * FB_EMBIGGEN)); 10.13 } 10.14 10.15 + ohmd_device_getf(dev, OHMD_DISTORTION_K, distort_k); 10.16 + printf("k: %g %g %g %g %g %g\n", distort_k[0], distort_k[1], distort_k[2], 10.17 + distort_k[3], distort_k[4], distort_k[5]); 10.18 + /* TODO: DK2 returns all zeros here ... maybe we should detect that and switch to 10.19 + * using the DK2 distortion mesh from the Oculus SDK. I'll have to connect the DK1 10.20 + * again to finish the barrel distortion method. 10.21 + */ 10.22 + 10.23 return 0; 10.24 } 10.25 10.26 @@ -184,7 +193,7 @@ 10.27 m.proj_matrix = proj_matrix; 10.28 m.begin = begin; 10.29 m.present = present; 10.30 - m.set_eye_texture = set_eye_texture; 10.31 + /*m.set_eye_texture = set_eye_texture;*/ 10.32 m.recenter = recenter; 10.33 } 10.34 return &m;