libgoatvr
view src/mesh.c @ 21:7f9cc8a4d3a5
ported the libovr backend to 0.4.4
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Mon, 12 Jan 2015 07:16:39 +0200 |
parents | d12592558809 |
children | 0fea7c2b25d7 |
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <stddef.h>
5 #include "opengl.h"
6 #include "mesh.h"
8 static void distort_texcoords(float *tc, float aspect, float lens_center_offset, float scale,
9 const float *dist_factors);
10 static float barrel_scale(float rad, const float *k);
12 /* let's avoid a glew dependency in the library just for this */
13 #ifndef GL_ARRAY_BUFFER
14 #define GL_ARRAY_BUFFER 0x8892
15 #define GL_ELEMENT_ARRAY_BUFFER 0x8893
16 #define GL_STATIC_DRAW 0x88E4
17 #endif
19 #ifndef GL_VERSION_1_5
20 static void (*glGenBuffers)(GLsizei, GLuint*);
21 static void (*glDeleteBuffers)(GLsizei, GLuint*);
22 static void (*glBufferData)(GLenum, unsigned int, const GLvoid*, GLenum);
23 static void (*glBindBuffer)(GLenum, GLuint);
24 #else
25 #ifndef GL_GLEXT_PROTOTYPES
26 GLAPI void APIENTRY glGenBuffers(GLsizei, GLuint*);
27 GLAPI void APIENTRY glDeleteBuffers(GLsizei, GLuint*);
28 GLAPI void APIENTRY glBufferData(GLenum, unsigned int, const GLvoid*, GLenum);
29 GLAPI void APIENTRY glBindBuffer(GLenum, GLuint);
30 #endif
31 #endif
33 int vrimp_mesh_init(struct mesh *m)
34 {
35 m->prim = GL_TRIANGLES;
37 m->varr = 0;
38 m->iarr = 0;
39 m->num_verts = m->num_faces = 0;
40 m->vbo = m->ibo = 0;
42 #ifndef GL_VERSION_1_5
43 if(!glGenBuffers) {
44 glGenBuffers = vrimp_glfunc("glGenBuffersARB");
45 glDeleteBuffers = vrimp_glfunc("glDeleteBuffersARB");
46 glBufferData = vrimp_glfunc("glBufferDataARB");
47 glBindBuffer = vrimp_glfunc("glBindBufferARB");
49 if(!(glGenBuffers && glDeleteBuffers && glBufferData && glBindBuffer)) {
50 fprintf(stderr, "Failed to load VBO functions\n");
51 return -1;
52 }
53 }
54 #endif
56 return 0;
57 }
59 void vrimp_mesh_destroy(struct mesh *m)
60 {
61 free(m->varr);
62 free(m->iarr);
64 if(m->vbo) glDeleteBuffers(1, &m->vbo);
65 if(m->ibo) glDeleteBuffers(1, &m->ibo);
66 }
68 void vrimp_mesh_draw(struct mesh *m)
69 {
70 glEnableClientState(GL_VERTEX_ARRAY);
71 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
73 glBindBuffer(GL_ARRAY_BUFFER, m->vbo);
74 glVertexPointer(3, GL_FLOAT, sizeof(struct vertex), 0);
75 glTexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), (void*)offsetof(struct vertex, tx));
77 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo);
78 glDrawElements(GL_TRIANGLES, m->num_faces * 3, GL_UNSIGNED_INT, 0);
80 glBindBuffer(GL_ARRAY_BUFFER, 0);
81 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
83 glDisableClientState(GL_VERTEX_ARRAY);
84 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
85 }
87 int vrimp_mesh_barrel_distortion(struct mesh *m, int usub, int vsub, float aspect,
88 float lens_center_offset, float scale, const float *dist_factors,
89 float tex_scale_x, float tex_scale_y)
90 {
91 int i, j;
92 int uverts, vverts;
93 int num_verts, num_quads, num_tris;
94 struct vertex *varr, *vptr;
95 unsigned int *iarr, *iptr;
96 float du, dv;
98 uverts = usub + 1;
99 vverts = vsub + 1;
101 num_verts = uverts * vverts;
102 num_quads = usub * vsub;
103 num_tris = num_quads * 2;
105 if(!(varr = malloc(num_verts * sizeof *varr))) {
106 return -1;
107 }
108 if(!(iarr = malloc(num_tris * 3 * sizeof *iarr))) {
109 free(varr);
110 return -1;
111 }
113 du = 1.0 / (float)usub;
114 dv = 1.0 / (float)vsub;
116 vptr = varr;
117 for(i=0; i<vverts; i++) {
118 float v = (float)i * dv;
119 float y = 2.0 * v - 1.0;
121 for(j=0; j<uverts; j++) {
122 float u = (float)j * du;
123 float x = 2.0 * u - 1.0;
124 float tc[2];
125 tc[0] = u;
126 tc[1] = v;
128 distort_texcoords(tc, aspect, lens_center_offset, scale, dist_factors);
130 vptr->x = x;
131 vptr->y = y;
132 vptr->z = 0;
133 vptr->tx = tc[0] * tex_scale_x;
134 vptr->ty = tc[1] * tex_scale_y;
135 vptr++;
136 }
137 }
139 iptr = iarr;
140 for(i=0; i<vsub; i++) {
141 for(j=0; j<usub; j++) {
142 *iptr++ = i * uverts + j;
143 *iptr++ = (i + 1) * uverts + j;
144 *iptr++ = (i + 1) * uverts + (j + 1);
146 *iptr++ = i * uverts + j;
147 *iptr++ = (i + 1) * uverts + (j + 1);
148 *iptr++ = i * uverts + (j + 1);
149 }
150 }
152 glGenBuffers(1, &m->vbo);
153 glGenBuffers(1, &m->ibo);
154 glBindBuffer(GL_ARRAY_BUFFER, m->vbo);
155 glBufferData(GL_ARRAY_BUFFER, num_verts * sizeof *varr, varr, GL_STATIC_DRAW);
156 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo);
157 glBufferData(GL_ELEMENT_ARRAY_BUFFER, num_tris * 3 * sizeof *iarr, iarr, GL_STATIC_DRAW);
159 m->prim = GL_TRIANGLES;
160 m->num_verts = num_verts;
161 m->num_faces = num_tris;
162 return 0;
163 }
165 static void distort_texcoords(float *tc, float aspect, float lens_center_offset, float scale,
166 const float *dist_factors)
167 {
168 /* map tc [0, 1] -> [-1, 1] */
169 float ptx = tc[0] * 2.0 - 1.0;
170 float pty = tc[1] * 2.0 - 1.0;
171 float rad;
173 ptx += lens_center_offset * 2.0;
174 pty /= aspect; /* correct for aspect ratio */
176 rad = barrel_scale(ptx * ptx + pty * pty, dist_factors);
177 ptx *= rad; /* scale the point by the computer distortion radius */
178 pty *= rad;
180 ptx /= scale;
181 pty /= scale;
183 pty *= aspect;
184 ptx -= lens_center_offset * 2.0;
186 /* map back to range [0, 1] */
187 tc[0] = ptx * 0.5 + 0.5;
188 tc[1] = pty * 0.5 + 0.5;
189 }
191 static float barrel_scale(float rad, const float *k)
192 {
193 float radsq = rad * rad;
194 float radquad = radsq * radsq;
195 return k[0] + k[1] * radsq + k[2] * radquad + k[3] * radquad * radsq;
196 }