libgoatvr

view 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 source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include "opengl.h"
5 #include "mesh.h"
7 static void distort_texcoords(float *tc, float aspect, float lens_center_offset, float scale,
8 const float *dist_factors);
9 static float barrel_scale(float rad, const float *k);
11 /* let's avoid a glew dependency in the library just for this */
12 #ifndef GL_ARRAY_BUFFER
13 #define GL_ARRAY_BUFFER 0x8892
14 #define GL_ELEMENT_ARRAY_BUFFER 0x8893
15 #define GL_STATIC_DRAW 0x88E4
16 #endif
18 #if !defined(GL_VERSION_1_5) || !defined(GL_GLEXT_PROTOTYPES)
19 static void (*glGenBuffers)(GLsizei, GLuint*);
20 static void (*glDeleteBuffers)(GLsizei, GLuint*);
21 static void (*glBufferData)(GLenum, unsigned int, const GLvoid*, GLenum);
22 static void (*glBindBuffer)(GLenum, GLuint);
23 #endif
25 int vrimp_mesh_init(struct mesh *m)
26 {
27 m->prim = GL_TRIANGLES;
29 m->varr = 0;
30 m->iarr = 0;
31 m->num_verts = m->num_faces = 0;
32 m->vbo = m->ibo = 0;
34 if(!glGenBuffers) {
35 glGenBuffers = vrimp_glfunc("glGenBuffersARB");
36 glDeleteBuffers = vrimp_glfunc("glDeleteBuffersARB");
37 glBufferData = vrimp_glfunc("glBufferDataARB");
38 glBindBuffer = vrimp_glfunc("glBindBufferARB");
40 if(!(glGenBuffers && glDeleteBuffers && glBufferData && glBindBuffer)) {
41 fprintf(stderr, "Failed to load VBO functions\n");
42 return -1;
43 }
44 }
46 return 0;
47 }
49 void vrimp_mesh_destroy(struct mesh *m)
50 {
51 free(m->varr);
52 free(m->iarr);
54 if(m->vbo) glDeleteBuffers(1, &m->vbo);
55 if(m->ibo) glDeleteBuffers(1, &m->ibo);
56 }
58 void vrimp_mesh_draw(struct mesh *m)
59 {
60 glEnableClientState(GL_VERTEX_ARRAY);
61 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
63 glBindBuffer(GL_ARRAY_BUFFER, m->vbo);
64 glVertexPointer(3, GL_FLOAT, sizeof(struct vertex), 0);
65 glTexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), (void*)offsetof(struct vertex, tx));
67 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo);
68 glDrawElements(GL_TRIANGLES, m->num_faces * 3, GL_UNSIGNED_INT, 0);
70 glBindBuffer(GL_ARRAY_BUFFER, 0);
71 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
73 glDisableClientState(GL_VERTEX_ARRAY);
74 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
75 }
77 int vrimp_mesh_barrel_distortion(struct mesh *m, int usub, int vsub, float aspect,
78 float lens_center_offset, float scale, const float *dist_factors,
79 float tex_scale_x, float tex_scale_y)
80 {
81 int i, j;
82 int uverts, vverts;
83 int num_verts, num_quads, num_tris;
84 struct vertex *varr, *vptr;
85 unsigned int *iarr, *iptr;
86 float du, dv;
88 uverts = usub + 1;
89 vverts = vsub + 1;
91 num_verts = uverts * vverts;
92 num_quads = usub * vsub;
93 num_tris = num_quads * 2;
95 if(!(varr = malloc(num_verts * sizeof *varr))) {
96 return -1;
97 }
98 if(!(iarr = malloc(num_tris * 3 * sizeof *iarr))) {
99 free(varr);
100 return -1;
101 }
103 du = 1.0 / (float)usub;
104 dv = 1.0 / (float)vsub;
106 vptr = varr;
107 for(i=0; i<vverts; i++) {
108 float v = (float)i * dv;
109 float y = 2.0 * v - 1.0;
111 for(j=0; j<uverts; j++) {
112 float u = (float)j * du;
113 float x = 2.0 * u - 1.0;
114 float tc[2];
115 tc[0] = u;
116 tc[1] = v;
118 distort_texcoords(tc, aspect, lens_center_offset, scale, dist_factors);
120 vptr->x = x;
121 vptr->y = y;
122 vptr->z = 0;
123 vptr->tx = tc[0] * tex_scale_x;
124 vptr->ty = tc[1] * tex_scale_y;
125 vptr++;
126 }
127 }
129 iptr = iarr;
130 for(i=0; i<vsub; i++) {
131 for(j=0; j<usub; j++) {
132 *iptr++ = i * uverts + j;
133 *iptr++ = (i + 1) * uverts + j;
134 *iptr++ = (i + 1) * uverts + (j + 1);
136 *iptr++ = i * uverts + j;
137 *iptr++ = (i + 1) * uverts + (j + 1);
138 *iptr++ = i * uverts + (j + 1);
139 }
140 }
142 glGenBuffers(1, &m->vbo);
143 glGenBuffers(1, &m->ibo);
144 glBindBuffer(GL_ARRAY_BUFFER, m->vbo);
145 glBufferData(GL_ARRAY_BUFFER, num_verts * sizeof *varr, varr, GL_STATIC_DRAW);
146 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo);
147 glBufferData(GL_ELEMENT_ARRAY_BUFFER, num_tris * 3 * sizeof *iarr, iarr, GL_STATIC_DRAW);
149 m->prim = GL_TRIANGLES;
150 m->num_verts = num_verts;
151 m->num_faces = num_tris;
152 return 0;
153 }
155 static void distort_texcoords(float *tc, float aspect, float lens_center_offset, float scale,
156 const float *dist_factors)
157 {
158 /* map tc [0, 1] -> [-1, 1] */
159 float ptx = tc[0] * 2.0 - 1.0;
160 float pty = tc[1] * 2.0 - 1.0;
161 float rad;
163 ptx += lens_center_offset * 2.0;
164 pty /= aspect; /* correct for aspect ratio */
166 rad = barrel_scale(ptx * ptx + pty * pty, dist_factors);
167 ptx *= rad; /* scale the point by the computer distortion radius */
168 pty *= rad;
170 ptx /= scale;
171 pty /= scale;
173 pty *= aspect;
174 ptx -= lens_center_offset * 2.0;
176 /* map back to range [0, 1] */
177 tc[0] = ptx * 0.5 + 0.5;
178 tc[1] = pty * 0.5 + 0.5;
179 }
181 static float barrel_scale(float rad, const float *k)
182 {
183 float radsq = rad * rad;
184 float radquad = radsq * radsq;
185 return k[0] + k[1] * radsq + k[2] * radquad + k[3] * radquad * radsq;
186 }