libgoatvr

view src/mesh.c @ 33:1102327fe85f

added red-cyan anaglyph fallback drawing
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 30 Oct 2015 06:34:00 +0200
parents 0fea7c2b25d7
children
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 static PFNGLGENBUFFERSARBPROC gl_gen_buffers;
13 static PFNGLDELETEBUFFERSARBPROC gl_delete_buffers;
14 static PFNGLBUFFERDATAARBPROC gl_buffer_data;
15 static PFNGLBINDBUFFERARBPROC gl_bind_buffer;
17 int vrimp_mesh_init(struct mesh *m)
18 {
19 m->prim = GL_TRIANGLES;
21 m->varr = 0;
22 m->iarr = 0;
23 m->num_verts = m->num_faces = 0;
24 m->vbo = m->ibo = 0;
26 if(!gl_gen_buffers) {
27 gl_gen_buffers = (PFNGLGENBUFFERSARBPROC)vrimp_glfunc("glGenBuffersARB");
28 gl_delete_buffers = (PFNGLDELETEBUFFERSARBPROC)vrimp_glfunc("glDeleteBuffersARB");
29 gl_buffer_data = (PFNGLBUFFERDATAARBPROC)vrimp_glfunc("glBufferDataARB");
30 gl_bind_buffer = (PFNGLBINDBUFFERARBPROC)vrimp_glfunc("glBindBufferARB");
32 if(!(gl_gen_buffers && gl_delete_buffers && gl_buffer_data && gl_bind_buffer)) {
33 fprintf(stderr, "Failed to load VBO functions\n");
34 return -1;
35 }
36 }
38 return 0;
39 }
41 void vrimp_mesh_destroy(struct mesh *m)
42 {
43 free(m->varr);
44 free(m->iarr);
46 if(m->vbo) gl_delete_buffers(1, &m->vbo);
47 if(m->ibo) gl_delete_buffers(1, &m->ibo);
48 }
50 void vrimp_mesh_draw(struct mesh *m)
51 {
52 glEnableClientState(GL_VERTEX_ARRAY);
53 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
55 gl_bind_buffer(GL_ARRAY_BUFFER, m->vbo);
56 glVertexPointer(3, GL_FLOAT, sizeof(struct vertex), 0);
57 glTexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), (void*)offsetof(struct vertex, tx));
59 gl_bind_buffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo);
60 glDrawElements(GL_TRIANGLES, m->num_faces * 3, GL_UNSIGNED_INT, 0);
62 gl_bind_buffer(GL_ARRAY_BUFFER, 0);
63 gl_bind_buffer(GL_ELEMENT_ARRAY_BUFFER, 0);
65 glDisableClientState(GL_VERTEX_ARRAY);
66 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
67 }
69 int vrimp_mesh_barrel_distortion(struct mesh *m, int usub, int vsub, float aspect,
70 float lens_center_offset, float scale, const float *dist_factors,
71 float tex_scale_x, float tex_scale_y)
72 {
73 int i, j;
74 int uverts, vverts;
75 int num_verts, num_quads, num_tris;
76 struct vertex *varr, *vptr;
77 unsigned int *iarr, *iptr;
78 float du, dv;
80 uverts = usub + 1;
81 vverts = vsub + 1;
83 num_verts = uverts * vverts;
84 num_quads = usub * vsub;
85 num_tris = num_quads * 2;
87 if(!(varr = malloc(num_verts * sizeof *varr))) {
88 return -1;
89 }
90 if(!(iarr = malloc(num_tris * 3 * sizeof *iarr))) {
91 free(varr);
92 return -1;
93 }
95 du = 1.0 / (float)usub;
96 dv = 1.0 / (float)vsub;
98 vptr = varr;
99 for(i=0; i<vverts; i++) {
100 float v = (float)i * dv;
101 float y = 2.0 * v - 1.0;
103 for(j=0; j<uverts; j++) {
104 float u = (float)j * du;
105 float x = 2.0 * u - 1.0;
106 float tc[2];
107 tc[0] = u;
108 tc[1] = v;
110 distort_texcoords(tc, aspect, lens_center_offset, scale, dist_factors);
112 vptr->x = x;
113 vptr->y = y;
114 vptr->z = 0;
115 vptr->tx = tc[0] * tex_scale_x;
116 vptr->ty = tc[1] * tex_scale_y;
117 vptr++;
118 }
119 }
121 iptr = iarr;
122 for(i=0; i<vsub; i++) {
123 for(j=0; j<usub; j++) {
124 *iptr++ = i * uverts + j;
125 *iptr++ = (i + 1) * uverts + j;
126 *iptr++ = (i + 1) * uverts + (j + 1);
128 *iptr++ = i * uverts + j;
129 *iptr++ = (i + 1) * uverts + (j + 1);
130 *iptr++ = i * uverts + (j + 1);
131 }
132 }
134 gl_gen_buffers(1, &m->vbo);
135 gl_gen_buffers(1, &m->ibo);
136 gl_bind_buffer(GL_ARRAY_BUFFER, m->vbo);
137 gl_buffer_data(GL_ARRAY_BUFFER, num_verts * sizeof *varr, varr, GL_STATIC_DRAW);
138 gl_bind_buffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo);
139 gl_buffer_data(GL_ELEMENT_ARRAY_BUFFER, num_tris * 3 * sizeof *iarr, iarr, GL_STATIC_DRAW);
141 m->prim = GL_TRIANGLES;
142 m->num_verts = num_verts;
143 m->num_faces = num_tris;
144 return 0;
145 }
147 static void distort_texcoords(float *tc, float aspect, float lens_center_offset, float scale,
148 const float *dist_factors)
149 {
150 /* map tc [0, 1] -> [-1, 1] */
151 float ptx = tc[0] * 2.0 - 1.0;
152 float pty = tc[1] * 2.0 - 1.0;
153 float rad;
155 ptx += lens_center_offset * 2.0;
156 pty /= aspect; /* correct for aspect ratio */
158 rad = barrel_scale(ptx * ptx + pty * pty, dist_factors);
159 ptx *= rad; /* scale the point by the computer distortion radius */
160 pty *= rad;
162 ptx /= scale;
163 pty /= scale;
165 pty *= aspect;
166 ptx -= lens_center_offset * 2.0;
168 /* map back to range [0, 1] */
169 tc[0] = ptx * 0.5 + 0.5;
170 tc[1] = pty * 0.5 + 0.5;
171 }
173 static float barrel_scale(float rad, const float *k)
174 {
175 float radsq = rad * rad;
176 float radquad = radsq * radsq;
177 return k[0] + k[1] * radsq + k[2] * radquad + k[3] * radquad * radsq;
178 }