libgoatvr

view src/mesh.c @ 24:d659cbedde1d

works on linux with 0.4.4
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 14 Jan 2015 08:03:27 +0200
parents 827ec716c275
children 1a8343ea54ce
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
27 #ifndef GLAPI
28 #define GLAPI
29 #endif
30 #ifndef APIENTRY
31 #define APIENTRY
32 #endif
34 GLAPI void APIENTRY glGenBuffers(GLsizei, GLuint*);
35 GLAPI void APIENTRY glDeleteBuffers(GLsizei, const GLuint*);
36 GLAPI void APIENTRY glBufferData();
37 GLAPI void APIENTRY glBindBuffer(GLenum, GLuint);
38 #endif
39 #endif
41 int vrimp_mesh_init(struct mesh *m)
42 {
43 m->prim = GL_TRIANGLES;
45 m->varr = 0;
46 m->iarr = 0;
47 m->num_verts = m->num_faces = 0;
48 m->vbo = m->ibo = 0;
50 #ifndef GL_VERSION_1_5
51 if(!glGenBuffers) {
52 glGenBuffers = vrimp_glfunc("glGenBuffersARB");
53 glDeleteBuffers = vrimp_glfunc("glDeleteBuffersARB");
54 glBufferData = vrimp_glfunc("glBufferDataARB");
55 glBindBuffer = vrimp_glfunc("glBindBufferARB");
57 if(!(glGenBuffers && glDeleteBuffers && glBufferData && glBindBuffer)) {
58 fprintf(stderr, "Failed to load VBO functions\n");
59 return -1;
60 }
61 }
62 #endif
64 return 0;
65 }
67 void vrimp_mesh_destroy(struct mesh *m)
68 {
69 free(m->varr);
70 free(m->iarr);
72 if(m->vbo) glDeleteBuffers(1, &m->vbo);
73 if(m->ibo) glDeleteBuffers(1, &m->ibo);
74 }
76 void vrimp_mesh_draw(struct mesh *m)
77 {
78 glEnableClientState(GL_VERTEX_ARRAY);
79 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
81 glBindBuffer(GL_ARRAY_BUFFER, m->vbo);
82 glVertexPointer(3, GL_FLOAT, sizeof(struct vertex), 0);
83 glTexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), (void*)offsetof(struct vertex, tx));
85 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo);
86 glDrawElements(GL_TRIANGLES, m->num_faces * 3, GL_UNSIGNED_INT, 0);
88 glBindBuffer(GL_ARRAY_BUFFER, 0);
89 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
91 glDisableClientState(GL_VERTEX_ARRAY);
92 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
93 }
95 int vrimp_mesh_barrel_distortion(struct mesh *m, int usub, int vsub, float aspect,
96 float lens_center_offset, float scale, const float *dist_factors,
97 float tex_scale_x, float tex_scale_y)
98 {
99 int i, j;
100 int uverts, vverts;
101 int num_verts, num_quads, num_tris;
102 struct vertex *varr, *vptr;
103 unsigned int *iarr, *iptr;
104 float du, dv;
106 uverts = usub + 1;
107 vverts = vsub + 1;
109 num_verts = uverts * vverts;
110 num_quads = usub * vsub;
111 num_tris = num_quads * 2;
113 if(!(varr = malloc(num_verts * sizeof *varr))) {
114 return -1;
115 }
116 if(!(iarr = malloc(num_tris * 3 * sizeof *iarr))) {
117 free(varr);
118 return -1;
119 }
121 du = 1.0 / (float)usub;
122 dv = 1.0 / (float)vsub;
124 vptr = varr;
125 for(i=0; i<vverts; i++) {
126 float v = (float)i * dv;
127 float y = 2.0 * v - 1.0;
129 for(j=0; j<uverts; j++) {
130 float u = (float)j * du;
131 float x = 2.0 * u - 1.0;
132 float tc[2];
133 tc[0] = u;
134 tc[1] = v;
136 distort_texcoords(tc, aspect, lens_center_offset, scale, dist_factors);
138 vptr->x = x;
139 vptr->y = y;
140 vptr->z = 0;
141 vptr->tx = tc[0] * tex_scale_x;
142 vptr->ty = tc[1] * tex_scale_y;
143 vptr++;
144 }
145 }
147 iptr = iarr;
148 for(i=0; i<vsub; i++) {
149 for(j=0; j<usub; j++) {
150 *iptr++ = i * uverts + j;
151 *iptr++ = (i + 1) * uverts + j;
152 *iptr++ = (i + 1) * uverts + (j + 1);
154 *iptr++ = i * uverts + j;
155 *iptr++ = (i + 1) * uverts + (j + 1);
156 *iptr++ = i * uverts + (j + 1);
157 }
158 }
160 glGenBuffers(1, &m->vbo);
161 glGenBuffers(1, &m->ibo);
162 glBindBuffer(GL_ARRAY_BUFFER, m->vbo);
163 glBufferData(GL_ARRAY_BUFFER, num_verts * sizeof *varr, varr, GL_STATIC_DRAW);
164 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo);
165 glBufferData(GL_ELEMENT_ARRAY_BUFFER, num_tris * 3 * sizeof *iarr, iarr, GL_STATIC_DRAW);
167 m->prim = GL_TRIANGLES;
168 m->num_verts = num_verts;
169 m->num_faces = num_tris;
170 return 0;
171 }
173 static void distort_texcoords(float *tc, float aspect, float lens_center_offset, float scale,
174 const float *dist_factors)
175 {
176 /* map tc [0, 1] -> [-1, 1] */
177 float ptx = tc[0] * 2.0 - 1.0;
178 float pty = tc[1] * 2.0 - 1.0;
179 float rad;
181 ptx += lens_center_offset * 2.0;
182 pty /= aspect; /* correct for aspect ratio */
184 rad = barrel_scale(ptx * ptx + pty * pty, dist_factors);
185 ptx *= rad; /* scale the point by the computer distortion radius */
186 pty *= rad;
188 ptx /= scale;
189 pty /= scale;
191 pty *= aspect;
192 ptx -= lens_center_offset * 2.0;
194 /* map back to range [0, 1] */
195 tc[0] = ptx * 0.5 + 0.5;
196 tc[1] = pty * 0.5 + 0.5;
197 }
199 static float barrel_scale(float rad, const float *k)
200 {
201 float radsq = rad * rad;
202 float radquad = radsq * radsq;
203 return k[0] + k[1] * radsq + k[2] * radquad + k[3] * radquad * radsq;
204 }