# HG changeset patch # User John Tsiombikas # Date 1411208573 -10800 # Node ID 3d9ec6fe97d7cb51ffc6cc1e3323787fc3f13906 # Parent 6896f9cf96210fe5fa4657201c5a644dd4eba9de - 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 diff -r 6896f9cf9621 -r 3d9ec6fe97d7 example/src/main.c --- a/example/src/main.c Fri Sep 19 15:16:51 2014 +0300 +++ b/example/src/main.c Sat Sep 20 13:22:53 2014 +0300 @@ -139,8 +139,8 @@ void display(void) { int i; - float proj_mat[16]; - float rot_mat[16], view_mat[16]; + float proj_mat[16] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; + float view_mat[16] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; /* start drawing onto our texture render target */ glBindFramebuffer(GL_FRAMEBUFFER, fbo); @@ -164,7 +164,7 @@ * use glLoadTransposeMatrixf instead of glLoadMatrixf to load it. */ if(vr_proj_matrix(i, 0.5, 500.0, proj_mat)) { - glLoadTransposeMatrixf(proj_mat); + glLoadMatrixf(proj_mat); } else { glLoadIdentity(); gluPerspective(50.0, (float)fb_width / 2.0 / (float)fb_height, 0.5, 500.0); @@ -176,7 +176,7 @@ */ glMatrixMode(GL_MODELVIEW); vr_view_matrix(i, view_mat); - glLoadTransposeMatrixf(view_mat); + glLoadMatrixf(view_mat); /* move the camera to the eye level of the user */ glTranslatef(0, -vr_get_optf(VR_OPT_EYE_HEIGHT), 0); diff -r 6896f9cf9621 -r 3d9ec6fe97d7 src/mathutil.c --- a/src/mathutil.c Fri Sep 19 15:16:51 2014 +0300 +++ b/src/mathutil.c Sat Sep 20 13:22:53 2014 +0300 @@ -6,7 +6,7 @@ static const float idmat[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; -void rotation_matrix(const float *quat, float *matrix) +void vrimp_rotation_matrix(const float *quat, float *matrix) { matrix[0] = 1.0 - 2.0 * quat[1] * quat[1] - 2.0 * quat[2] * quat[2]; matrix[1] = 2.0 * quat[0] * quat[1] + 2.0 * quat[3] * quat[2]; @@ -26,10 +26,10 @@ matrix[12] = matrix[13] = matrix[14] = 0.0f; matrix[15] = 1.0f; - transpose_matrix(matrix); + vrimp_transpose_matrix(matrix); } -void translation_matrix(const float *vec, float *matrix) +void vrimp_translation_matrix(const float *vec, float *matrix) { memcpy(matrix, idmat, sizeof idmat); matrix[12] = vec[0]; @@ -37,7 +37,7 @@ matrix[14] = vec[2]; } -void mult_matrix(float *dest, const float *m1, const float *m2) +void vrimp_mult_matrix(float *dest, const float *m1, const float *m2) { int i, j; float tmp[16]; @@ -51,7 +51,7 @@ memcpy(dest, tmp, sizeof tmp); } -void transpose_matrix(float *matrix) +void vrimp_transpose_matrix(float *matrix) { int i, j; float tmp[16]; @@ -64,7 +64,7 @@ memcpy(matrix, tmp, sizeof tmp); } -void print_matrix(const float *matrix) +void vrimp_print_matrix(const float *matrix) { int i, j; diff -r 6896f9cf9621 -r 3d9ec6fe97d7 src/mathutil.h --- a/src/mathutil.h Fri Sep 19 15:16:51 2014 +0300 +++ b/src/mathutil.h Sat Sep 20 13:22:53 2014 +0300 @@ -1,13 +1,13 @@ #ifndef MATHUTIL_H_ #define MATHUTIL_H_ -void rotation_matrix(const float *quat, float *matrix); -void translation_matrix(const float *vec, float *matrix); +void vrimp_rotation_matrix(const float *quat, float *matrix); +void vrimp_translation_matrix(const float *vec, float *matrix); -void mult_matrix(float *dest, const float *m1, const float *m2); +void vrimp_mult_matrix(float *dest, const float *m1, const float *m2); -void transpose_matrix(float *matrix); +void vrimp_transpose_matrix(float *matrix); -void print_matrix(const float *matrix); +void vrimp_print_matrix(const float *matrix); #endif /* MATHUTIL_H_ */ diff -r 6896f9cf9621 -r 3d9ec6fe97d7 src/mesh.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mesh.c Sat Sep 20 13:22:53 2014 +0300 @@ -0,0 +1,186 @@ +#include +#include +#include +#include "opengl.h" +#include "mesh.h" + +static void distort_texcoords(float *tc, float aspect, float lens_center_offset, float scale, + const float *dist_factors); +static float barrel_scale(float rad, const float *k); + +/* let's avoid a glew dependency in the library just for this */ +#ifndef GL_ARRAY_BUFFER +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_STATIC_DRAW 0x88E4 +#endif + +#if !defined(GL_VERSION_1_5) || !defined(GL_GLEXT_PROTOTYPES) +static void (*glGenBuffers)(GLsizei, GLuint*); +static void (*glDeleteBuffers)(GLsizei, GLuint*); +static void (*glBufferData)(GLenum, unsigned int, const GLvoid*, GLenum); +static void (*glBindBuffer)(GLenum, GLuint); +#endif + +int vrimp_mesh_init(struct mesh *m) +{ + m->prim = GL_TRIANGLES; + + m->varr = 0; + m->iarr = 0; + m->num_verts = m->num_faces = 0; + m->vbo = m->ibo = 0; + + if(!glGenBuffers) { + glGenBuffers = vrimp_glfunc("glGenBuffersARB"); + glDeleteBuffers = vrimp_glfunc("glDeleteBuffersARB"); + glBufferData = vrimp_glfunc("glBufferDataARB"); + glBindBuffer = vrimp_glfunc("glBindBufferARB"); + + if(!(glGenBuffers && glDeleteBuffers && glBufferData && glBindBuffer)) { + fprintf(stderr, "Failed to load VBO functions\n"); + return -1; + } + } + + return 0; +} + +void vrimp_mesh_destroy(struct mesh *m) +{ + free(m->varr); + free(m->iarr); + + if(m->vbo) glDeleteBuffers(1, &m->vbo); + if(m->ibo) glDeleteBuffers(1, &m->ibo); +} + +void vrimp_mesh_draw(struct mesh *m) +{ + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + glBindBuffer(GL_ARRAY_BUFFER, m->vbo); + glVertexPointer(3, GL_FLOAT, sizeof(struct vertex), 0); + glTexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), (void*)offsetof(struct vertex, tx)); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo); + glDrawElements(GL_TRIANGLES, m->num_faces * 3, GL_UNSIGNED_INT, 0); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); +} + +int vrimp_mesh_barrel_distortion(struct mesh *m, int usub, int vsub, float aspect, + float lens_center_offset, float scale, const float *dist_factors, + float tex_scale_x, float tex_scale_y) +{ + int i, j; + int uverts, vverts; + int num_verts, num_quads, num_tris; + struct vertex *varr, *vptr; + unsigned int *iarr, *iptr; + float du, dv; + + uverts = usub + 1; + vverts = vsub + 1; + + num_verts = uverts * vverts; + num_quads = usub * vsub; + num_tris = num_quads * 2; + + if(!(varr = malloc(num_verts * sizeof *varr))) { + return -1; + } + if(!(iarr = malloc(num_tris * 3 * sizeof *iarr))) { + free(varr); + return -1; + } + + du = 1.0 / (float)usub; + dv = 1.0 / (float)vsub; + + vptr = varr; + for(i=0; ix = x; + vptr->y = y; + vptr->z = 0; + vptr->tx = tc[0] * tex_scale_x; + vptr->ty = tc[1] * tex_scale_y; + vptr++; + } + } + + iptr = iarr; + for(i=0; ivbo); + glGenBuffers(1, &m->ibo); + glBindBuffer(GL_ARRAY_BUFFER, m->vbo); + glBufferData(GL_ARRAY_BUFFER, num_verts * sizeof *varr, varr, GL_STATIC_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, num_tris * 3 * sizeof *iarr, iarr, GL_STATIC_DRAW); + + m->prim = GL_TRIANGLES; + m->num_verts = num_verts; + m->num_faces = num_tris; + return 0; +} + +static void distort_texcoords(float *tc, float aspect, float lens_center_offset, float scale, + const float *dist_factors) +{ + /* map tc [0, 1] -> [-1, 1] */ + float ptx = tc[0] * 2.0 - 1.0; + float pty = tc[1] * 2.0 - 1.0; + float rad; + + ptx += lens_center_offset * 2.0; + pty /= aspect; /* correct for aspect ratio */ + + rad = barrel_scale(ptx * ptx + pty * pty, dist_factors); + ptx *= rad; /* scale the point by the computer distortion radius */ + pty *= rad; + + ptx /= scale; + pty /= scale; + + pty *= aspect; + ptx -= lens_center_offset * 2.0; + + /* map back to range [0, 1] */ + tc[0] = ptx * 0.5 + 0.5; + tc[1] = pty * 0.5 + 0.5; +} + +static float barrel_scale(float rad, const float *k) +{ + float radsq = rad * rad; + float radquad = radsq * radsq; + return k[0] + k[1] * radsq + k[2] * radquad + k[3] * radquad * radsq; +} diff -r 6896f9cf9621 -r 3d9ec6fe97d7 src/mesh.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mesh.h Sat Sep 20 13:22:53 2014 +0300 @@ -0,0 +1,27 @@ +#ifndef MESH_H_ +#define MESH_H_ + +struct vertex { + float x, y, z; + float tx, ty; +}; + +struct mesh { + int prim; + struct vertex *varr; + unsigned int *iarr; + int num_verts, num_faces; + unsigned int vbo, ibo; +}; + +int vrimp_mesh_init(struct mesh *m); +void vrimp_mesh_destroy(struct mesh *m); + +void vrimp_mesh_draw(struct mesh *m); + +int vrimp_mesh_barrel_distortion(struct mesh *m, int usub, int vsub, float aspect, + float lens_center_offset, float scale, const float *dist_factors, + float tex_scale_x, float tex_scale_y); + + +#endif /* MESH_H_ */ diff -r 6896f9cf9621 -r 3d9ec6fe97d7 src/opengl.c --- a/src/opengl.c Fri Sep 19 15:16:51 2014 +0300 +++ b/src/opengl.c Sat Sep 20 13:22:53 2014 +0300 @@ -1,18 +1,28 @@ #include "opengl.h" #ifdef __unix__ -void vr_gl_swap_buffers(void) +void vrimp_swap_buffers(void) { Display *dpy = glXGetCurrentDisplay(); Drawable win = glXGetCurrentDrawable(); glXSwapBuffers(dpy, win); } + +void (*vrimp_glfunc(const char *name))() +{ + return glXGetProcAddress((const unsigned char*)name); +} #endif #ifdef WIN32 -void vr_gl_swap_buffers(void) +void vrimp_swap_buffers(void) { HDC dc = wglGetCurrentDC(); SwapBuffers(dc); } + +void (*vrimp_glfunc(const char *name))() +{ + return wglGetProcAddress(name); +} #endif diff -r 6896f9cf9621 -r 3d9ec6fe97d7 src/opengl.h --- a/src/opengl.h Fri Sep 19 15:16:51 2014 +0300 +++ b/src/opengl.h Sat Sep 20 13:22:53 2014 +0300 @@ -16,6 +16,8 @@ #include #endif -void vr_gl_swap_buffers(void); +void vrimp_swap_buffers(void); + +void (*vrimp_glfunc(const char *name))(); #endif /* VR_OPENGL_H_ */ diff -r 6896f9cf9621 -r 3d9ec6fe97d7 src/vr.c --- a/src/vr.c Fri Sep 19 15:16:51 2014 +0300 +++ b/src/vr.c Sat Sep 20 13:22:53 2014 +0300 @@ -198,9 +198,9 @@ offs[1] = -offs[1]; offs[2] = -offs[2]; - translation_matrix(offs, tmat); - rotation_matrix(quat, rmat); - mult_matrix(mat, tmat, rmat); + vrimp_translation_matrix(offs, tmat); + vrimp_rotation_matrix(quat, rmat); + vrimp_mult_matrix(mat, tmat, rmat); return 1; } @@ -238,7 +238,7 @@ if(!res) { fallback_present(); - vr_gl_swap_buffers(); + vrimp_swap_buffers(); } return 0; } diff -r 6896f9cf9621 -r 3d9ec6fe97d7 src/vr.h --- a/src/vr.h Fri Sep 19 15:16:51 2014 +0300 +++ b/src/vr.h Sat Sep 20 13:22:53 2014 +0300 @@ -1,16 +1,18 @@ #ifndef VR_H_ #define VR_H_ +/* unit: pixels */ #define VR_OPT_DISPLAY_WIDTH "display-xres" #define VR_OPT_DISPLAY_HEIGHT "display-yres" #define VR_OPT_LEYE_XRES "left-eye-xres" #define VR_OPT_LEYE_YRES "left-eye-yres" #define VR_OPT_REYE_XRES "right-eye-xres" #define VR_OPT_REYE_YRES "right-eye-yres" +#define VR_OPT_WIN_XOFFS "win-xoffset" +#define VR_OPT_WIN_YOFFS "win-yoffset" +/* unit: meters */ #define VR_OPT_EYE_HEIGHT "eye-height" #define VR_OPT_IPD "ipd" -#define VR_OPT_WIN_XOFFS "win-xoffset" -#define VR_OPT_WIN_YOFFS "win-yoffset" enum { VR_EYE_LEFT, diff -r 6896f9cf9621 -r 3d9ec6fe97d7 src/vr_openhmd.c --- a/src/vr_openhmd.c Fri Sep 19 15:16:51 2014 +0300 +++ b/src/vr_openhmd.c Sat Sep 20 13:22:53 2014 +0300 @@ -27,6 +27,7 @@ static int init(void) { int i, num_hmds; + float distort_k[6]; if(!(ctx = ohmd_ctx_create())) { fprintf(stderr, "failed to create OpenHMD context\n"); @@ -69,6 +70,14 @@ set_option_int(optdb, VR_OPT_REYE_YRES, (int)(disp_height * FB_EMBIGGEN)); } + ohmd_device_getf(dev, OHMD_DISTORTION_K, distort_k); + printf("k: %g %g %g %g %g %g\n", distort_k[0], distort_k[1], distort_k[2], + distort_k[3], distort_k[4], distort_k[5]); + /* TODO: DK2 returns all zeros here ... maybe we should detect that and switch to + * using the DK2 distortion mesh from the Oculus SDK. I'll have to connect the DK1 + * again to finish the barrel distortion method. + */ + return 0; } @@ -184,7 +193,7 @@ m.proj_matrix = proj_matrix; m.begin = begin; m.present = present; - m.set_eye_texture = set_eye_texture; + /*m.set_eye_texture = set_eye_texture;*/ m.recenter = recenter; } return &m;