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;