libgoatvr

view src/mesh.c @ 9:d12592558809

build on macosx
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 20 Sep 2014 16:52:42 +0300
parents 3d9ec6fe97d7
children 827ec716c275
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 #endif
26 int vrimp_mesh_init(struct mesh *m)
27 {
28 m->prim = GL_TRIANGLES;
30 m->varr = 0;
31 m->iarr = 0;
32 m->num_verts = m->num_faces = 0;
33 m->vbo = m->ibo = 0;
35 #ifndef GL_VERSION_1_5
36 if(!glGenBuffers) {
37 glGenBuffers = vrimp_glfunc("glGenBuffersARB");
38 glDeleteBuffers = vrimp_glfunc("glDeleteBuffersARB");
39 glBufferData = vrimp_glfunc("glBufferDataARB");
40 glBindBuffer = vrimp_glfunc("glBindBufferARB");
42 if(!(glGenBuffers && glDeleteBuffers && glBufferData && glBindBuffer)) {
43 fprintf(stderr, "Failed to load VBO functions\n");
44 return -1;
45 }
46 }
47 #endif
49 return 0;
50 }
52 void vrimp_mesh_destroy(struct mesh *m)
53 {
54 free(m->varr);
55 free(m->iarr);
57 if(m->vbo) glDeleteBuffers(1, &m->vbo);
58 if(m->ibo) glDeleteBuffers(1, &m->ibo);
59 }
61 void vrimp_mesh_draw(struct mesh *m)
62 {
63 glEnableClientState(GL_VERTEX_ARRAY);
64 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
66 glBindBuffer(GL_ARRAY_BUFFER, m->vbo);
67 glVertexPointer(3, GL_FLOAT, sizeof(struct vertex), 0);
68 glTexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), (void*)offsetof(struct vertex, tx));
70 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo);
71 glDrawElements(GL_TRIANGLES, m->num_faces * 3, GL_UNSIGNED_INT, 0);
73 glBindBuffer(GL_ARRAY_BUFFER, 0);
74 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
76 glDisableClientState(GL_VERTEX_ARRAY);
77 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
78 }
80 int vrimp_mesh_barrel_distortion(struct mesh *m, int usub, int vsub, float aspect,
81 float lens_center_offset, float scale, const float *dist_factors,
82 float tex_scale_x, float tex_scale_y)
83 {
84 int i, j;
85 int uverts, vverts;
86 int num_verts, num_quads, num_tris;
87 struct vertex *varr, *vptr;
88 unsigned int *iarr, *iptr;
89 float du, dv;
91 uverts = usub + 1;
92 vverts = vsub + 1;
94 num_verts = uverts * vverts;
95 num_quads = usub * vsub;
96 num_tris = num_quads * 2;
98 if(!(varr = malloc(num_verts * sizeof *varr))) {
99 return -1;
100 }
101 if(!(iarr = malloc(num_tris * 3 * sizeof *iarr))) {
102 free(varr);
103 return -1;
104 }
106 du = 1.0 / (float)usub;
107 dv = 1.0 / (float)vsub;
109 vptr = varr;
110 for(i=0; i<vverts; i++) {
111 float v = (float)i * dv;
112 float y = 2.0 * v - 1.0;
114 for(j=0; j<uverts; j++) {
115 float u = (float)j * du;
116 float x = 2.0 * u - 1.0;
117 float tc[2];
118 tc[0] = u;
119 tc[1] = v;
121 distort_texcoords(tc, aspect, lens_center_offset, scale, dist_factors);
123 vptr->x = x;
124 vptr->y = y;
125 vptr->z = 0;
126 vptr->tx = tc[0] * tex_scale_x;
127 vptr->ty = tc[1] * tex_scale_y;
128 vptr++;
129 }
130 }
132 iptr = iarr;
133 for(i=0; i<vsub; i++) {
134 for(j=0; j<usub; j++) {
135 *iptr++ = i * uverts + j;
136 *iptr++ = (i + 1) * uverts + j;
137 *iptr++ = (i + 1) * uverts + (j + 1);
139 *iptr++ = i * uverts + j;
140 *iptr++ = (i + 1) * uverts + (j + 1);
141 *iptr++ = i * uverts + (j + 1);
142 }
143 }
145 glGenBuffers(1, &m->vbo);
146 glGenBuffers(1, &m->ibo);
147 glBindBuffer(GL_ARRAY_BUFFER, m->vbo);
148 glBufferData(GL_ARRAY_BUFFER, num_verts * sizeof *varr, varr, GL_STATIC_DRAW);
149 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo);
150 glBufferData(GL_ELEMENT_ARRAY_BUFFER, num_tris * 3 * sizeof *iarr, iarr, GL_STATIC_DRAW);
152 m->prim = GL_TRIANGLES;
153 m->num_verts = num_verts;
154 m->num_faces = num_tris;
155 return 0;
156 }
158 static void distort_texcoords(float *tc, float aspect, float lens_center_offset, float scale,
159 const float *dist_factors)
160 {
161 /* map tc [0, 1] -> [-1, 1] */
162 float ptx = tc[0] * 2.0 - 1.0;
163 float pty = tc[1] * 2.0 - 1.0;
164 float rad;
166 ptx += lens_center_offset * 2.0;
167 pty /= aspect; /* correct for aspect ratio */
169 rad = barrel_scale(ptx * ptx + pty * pty, dist_factors);
170 ptx *= rad; /* scale the point by the computer distortion radius */
171 pty *= rad;
173 ptx /= scale;
174 pty /= scale;
176 pty *= aspect;
177 ptx -= lens_center_offset * 2.0;
179 /* map back to range [0, 1] */
180 tc[0] = ptx * 0.5 + 0.5;
181 tc[1] = pty * 0.5 + 0.5;
182 }
184 static float barrel_scale(float rad, const float *k)
185 {
186 float radsq = rad * rad;
187 float radquad = radsq * radsq;
188 return k[0] + k[1] * radsq + k[2] * radquad + k[3] * radquad * radsq;
189 }