libgoatvr

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