libgoatvr
diff src/mesh.c @ 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 | |
children | d12592558809 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/mesh.c Sat Sep 20 13:22:53 2014 +0300 1.3 @@ -0,0 +1,186 @@ 1.4 +#include <stdio.h> 1.5 +#include <stdlib.h> 1.6 +#include <string.h> 1.7 +#include "opengl.h" 1.8 +#include "mesh.h" 1.9 + 1.10 +static void distort_texcoords(float *tc, float aspect, float lens_center_offset, float scale, 1.11 + const float *dist_factors); 1.12 +static float barrel_scale(float rad, const float *k); 1.13 + 1.14 +/* let's avoid a glew dependency in the library just for this */ 1.15 +#ifndef GL_ARRAY_BUFFER 1.16 +#define GL_ARRAY_BUFFER 0x8892 1.17 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 1.18 +#define GL_STATIC_DRAW 0x88E4 1.19 +#endif 1.20 + 1.21 +#if !defined(GL_VERSION_1_5) || !defined(GL_GLEXT_PROTOTYPES) 1.22 +static void (*glGenBuffers)(GLsizei, GLuint*); 1.23 +static void (*glDeleteBuffers)(GLsizei, GLuint*); 1.24 +static void (*glBufferData)(GLenum, unsigned int, const GLvoid*, GLenum); 1.25 +static void (*glBindBuffer)(GLenum, GLuint); 1.26 +#endif 1.27 + 1.28 +int vrimp_mesh_init(struct mesh *m) 1.29 +{ 1.30 + m->prim = GL_TRIANGLES; 1.31 + 1.32 + m->varr = 0; 1.33 + m->iarr = 0; 1.34 + m->num_verts = m->num_faces = 0; 1.35 + m->vbo = m->ibo = 0; 1.36 + 1.37 + if(!glGenBuffers) { 1.38 + glGenBuffers = vrimp_glfunc("glGenBuffersARB"); 1.39 + glDeleteBuffers = vrimp_glfunc("glDeleteBuffersARB"); 1.40 + glBufferData = vrimp_glfunc("glBufferDataARB"); 1.41 + glBindBuffer = vrimp_glfunc("glBindBufferARB"); 1.42 + 1.43 + if(!(glGenBuffers && glDeleteBuffers && glBufferData && glBindBuffer)) { 1.44 + fprintf(stderr, "Failed to load VBO functions\n"); 1.45 + return -1; 1.46 + } 1.47 + } 1.48 + 1.49 + return 0; 1.50 +} 1.51 + 1.52 +void vrimp_mesh_destroy(struct mesh *m) 1.53 +{ 1.54 + free(m->varr); 1.55 + free(m->iarr); 1.56 + 1.57 + if(m->vbo) glDeleteBuffers(1, &m->vbo); 1.58 + if(m->ibo) glDeleteBuffers(1, &m->ibo); 1.59 +} 1.60 + 1.61 +void vrimp_mesh_draw(struct mesh *m) 1.62 +{ 1.63 + glEnableClientState(GL_VERTEX_ARRAY); 1.64 + glEnableClientState(GL_TEXTURE_COORD_ARRAY); 1.65 + 1.66 + glBindBuffer(GL_ARRAY_BUFFER, m->vbo); 1.67 + glVertexPointer(3, GL_FLOAT, sizeof(struct vertex), 0); 1.68 + glTexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), (void*)offsetof(struct vertex, tx)); 1.69 + 1.70 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo); 1.71 + glDrawElements(GL_TRIANGLES, m->num_faces * 3, GL_UNSIGNED_INT, 0); 1.72 + 1.73 + glBindBuffer(GL_ARRAY_BUFFER, 0); 1.74 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 1.75 + 1.76 + glDisableClientState(GL_VERTEX_ARRAY); 1.77 + glDisableClientState(GL_TEXTURE_COORD_ARRAY); 1.78 +} 1.79 + 1.80 +int vrimp_mesh_barrel_distortion(struct mesh *m, int usub, int vsub, float aspect, 1.81 + float lens_center_offset, float scale, const float *dist_factors, 1.82 + float tex_scale_x, float tex_scale_y) 1.83 +{ 1.84 + int i, j; 1.85 + int uverts, vverts; 1.86 + int num_verts, num_quads, num_tris; 1.87 + struct vertex *varr, *vptr; 1.88 + unsigned int *iarr, *iptr; 1.89 + float du, dv; 1.90 + 1.91 + uverts = usub + 1; 1.92 + vverts = vsub + 1; 1.93 + 1.94 + num_verts = uverts * vverts; 1.95 + num_quads = usub * vsub; 1.96 + num_tris = num_quads * 2; 1.97 + 1.98 + if(!(varr = malloc(num_verts * sizeof *varr))) { 1.99 + return -1; 1.100 + } 1.101 + if(!(iarr = malloc(num_tris * 3 * sizeof *iarr))) { 1.102 + free(varr); 1.103 + return -1; 1.104 + } 1.105 + 1.106 + du = 1.0 / (float)usub; 1.107 + dv = 1.0 / (float)vsub; 1.108 + 1.109 + vptr = varr; 1.110 + for(i=0; i<vverts; i++) { 1.111 + float v = (float)i * dv; 1.112 + float y = 2.0 * v - 1.0; 1.113 + 1.114 + for(j=0; j<uverts; j++) { 1.115 + float u = (float)j * du; 1.116 + float x = 2.0 * u - 1.0; 1.117 + float tc[2]; 1.118 + tc[0] = u; 1.119 + tc[1] = v; 1.120 + 1.121 + distort_texcoords(tc, aspect, lens_center_offset, scale, dist_factors); 1.122 + 1.123 + vptr->x = x; 1.124 + vptr->y = y; 1.125 + vptr->z = 0; 1.126 + vptr->tx = tc[0] * tex_scale_x; 1.127 + vptr->ty = tc[1] * tex_scale_y; 1.128 + vptr++; 1.129 + } 1.130 + } 1.131 + 1.132 + iptr = iarr; 1.133 + for(i=0; i<vsub; i++) { 1.134 + for(j=0; j<usub; j++) { 1.135 + *iptr++ = i * uverts + j; 1.136 + *iptr++ = (i + 1) * uverts + j; 1.137 + *iptr++ = (i + 1) * uverts + (j + 1); 1.138 + 1.139 + *iptr++ = i * uverts + j; 1.140 + *iptr++ = (i + 1) * uverts + (j + 1); 1.141 + *iptr++ = i * uverts + (j + 1); 1.142 + } 1.143 + } 1.144 + 1.145 + glGenBuffers(1, &m->vbo); 1.146 + glGenBuffers(1, &m->ibo); 1.147 + glBindBuffer(GL_ARRAY_BUFFER, m->vbo); 1.148 + glBufferData(GL_ARRAY_BUFFER, num_verts * sizeof *varr, varr, GL_STATIC_DRAW); 1.149 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo); 1.150 + glBufferData(GL_ELEMENT_ARRAY_BUFFER, num_tris * 3 * sizeof *iarr, iarr, GL_STATIC_DRAW); 1.151 + 1.152 + m->prim = GL_TRIANGLES; 1.153 + m->num_verts = num_verts; 1.154 + m->num_faces = num_tris; 1.155 + return 0; 1.156 +} 1.157 + 1.158 +static void distort_texcoords(float *tc, float aspect, float lens_center_offset, float scale, 1.159 + const float *dist_factors) 1.160 +{ 1.161 + /* map tc [0, 1] -> [-1, 1] */ 1.162 + float ptx = tc[0] * 2.0 - 1.0; 1.163 + float pty = tc[1] * 2.0 - 1.0; 1.164 + float rad; 1.165 + 1.166 + ptx += lens_center_offset * 2.0; 1.167 + pty /= aspect; /* correct for aspect ratio */ 1.168 + 1.169 + rad = barrel_scale(ptx * ptx + pty * pty, dist_factors); 1.170 + ptx *= rad; /* scale the point by the computer distortion radius */ 1.171 + pty *= rad; 1.172 + 1.173 + ptx /= scale; 1.174 + pty /= scale; 1.175 + 1.176 + pty *= aspect; 1.177 + ptx -= lens_center_offset * 2.0; 1.178 + 1.179 + /* map back to range [0, 1] */ 1.180 + tc[0] = ptx * 0.5 + 0.5; 1.181 + tc[1] = pty * 0.5 + 0.5; 1.182 +} 1.183 + 1.184 +static float barrel_scale(float rad, const float *k) 1.185 +{ 1.186 + float radsq = rad * rad; 1.187 + float radquad = radsq * radsq; 1.188 + return k[0] + k[1] * radsq + k[2] * radquad + k[3] * radquad * radsq; 1.189 +}