nuclear@8: #include nuclear@8: #include nuclear@8: #include nuclear@8: #include "opengl.h" nuclear@8: #include "mesh.h" nuclear@8: nuclear@8: static void distort_texcoords(float *tc, float aspect, float lens_center_offset, float scale, nuclear@8: const float *dist_factors); nuclear@8: static float barrel_scale(float rad, const float *k); nuclear@8: nuclear@8: /* let's avoid a glew dependency in the library just for this */ nuclear@8: #ifndef GL_ARRAY_BUFFER nuclear@8: #define GL_ARRAY_BUFFER 0x8892 nuclear@8: #define GL_ELEMENT_ARRAY_BUFFER 0x8893 nuclear@8: #define GL_STATIC_DRAW 0x88E4 nuclear@8: #endif nuclear@8: nuclear@8: #if !defined(GL_VERSION_1_5) || !defined(GL_GLEXT_PROTOTYPES) nuclear@8: static void (*glGenBuffers)(GLsizei, GLuint*); nuclear@8: static void (*glDeleteBuffers)(GLsizei, GLuint*); nuclear@8: static void (*glBufferData)(GLenum, unsigned int, const GLvoid*, GLenum); nuclear@8: static void (*glBindBuffer)(GLenum, GLuint); nuclear@8: #endif nuclear@8: nuclear@8: int vrimp_mesh_init(struct mesh *m) nuclear@8: { nuclear@8: m->prim = GL_TRIANGLES; nuclear@8: nuclear@8: m->varr = 0; nuclear@8: m->iarr = 0; nuclear@8: m->num_verts = m->num_faces = 0; nuclear@8: m->vbo = m->ibo = 0; nuclear@8: nuclear@8: if(!glGenBuffers) { nuclear@8: glGenBuffers = vrimp_glfunc("glGenBuffersARB"); nuclear@8: glDeleteBuffers = vrimp_glfunc("glDeleteBuffersARB"); nuclear@8: glBufferData = vrimp_glfunc("glBufferDataARB"); nuclear@8: glBindBuffer = vrimp_glfunc("glBindBufferARB"); nuclear@8: nuclear@8: if(!(glGenBuffers && glDeleteBuffers && glBufferData && glBindBuffer)) { nuclear@8: fprintf(stderr, "Failed to load VBO functions\n"); nuclear@8: return -1; nuclear@8: } nuclear@8: } nuclear@8: nuclear@8: return 0; nuclear@8: } nuclear@8: nuclear@8: void vrimp_mesh_destroy(struct mesh *m) nuclear@8: { nuclear@8: free(m->varr); nuclear@8: free(m->iarr); nuclear@8: nuclear@8: if(m->vbo) glDeleteBuffers(1, &m->vbo); nuclear@8: if(m->ibo) glDeleteBuffers(1, &m->ibo); nuclear@8: } nuclear@8: nuclear@8: void vrimp_mesh_draw(struct mesh *m) nuclear@8: { nuclear@8: glEnableClientState(GL_VERTEX_ARRAY); nuclear@8: glEnableClientState(GL_TEXTURE_COORD_ARRAY); nuclear@8: nuclear@8: glBindBuffer(GL_ARRAY_BUFFER, m->vbo); nuclear@8: glVertexPointer(3, GL_FLOAT, sizeof(struct vertex), 0); nuclear@8: glTexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), (void*)offsetof(struct vertex, tx)); nuclear@8: nuclear@8: glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo); nuclear@8: glDrawElements(GL_TRIANGLES, m->num_faces * 3, GL_UNSIGNED_INT, 0); nuclear@8: nuclear@8: glBindBuffer(GL_ARRAY_BUFFER, 0); nuclear@8: glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); nuclear@8: nuclear@8: glDisableClientState(GL_VERTEX_ARRAY); nuclear@8: glDisableClientState(GL_TEXTURE_COORD_ARRAY); nuclear@8: } nuclear@8: nuclear@8: int vrimp_mesh_barrel_distortion(struct mesh *m, int usub, int vsub, float aspect, nuclear@8: float lens_center_offset, float scale, const float *dist_factors, nuclear@8: float tex_scale_x, float tex_scale_y) nuclear@8: { nuclear@8: int i, j; nuclear@8: int uverts, vverts; nuclear@8: int num_verts, num_quads, num_tris; nuclear@8: struct vertex *varr, *vptr; nuclear@8: unsigned int *iarr, *iptr; nuclear@8: float du, dv; nuclear@8: nuclear@8: uverts = usub + 1; nuclear@8: vverts = vsub + 1; nuclear@8: nuclear@8: num_verts = uverts * vverts; nuclear@8: num_quads = usub * vsub; nuclear@8: num_tris = num_quads * 2; nuclear@8: nuclear@8: if(!(varr = malloc(num_verts * sizeof *varr))) { nuclear@8: return -1; nuclear@8: } nuclear@8: if(!(iarr = malloc(num_tris * 3 * sizeof *iarr))) { nuclear@8: free(varr); nuclear@8: return -1; nuclear@8: } nuclear@8: nuclear@8: du = 1.0 / (float)usub; nuclear@8: dv = 1.0 / (float)vsub; nuclear@8: nuclear@8: vptr = varr; nuclear@8: for(i=0; ix = x; nuclear@8: vptr->y = y; nuclear@8: vptr->z = 0; nuclear@8: vptr->tx = tc[0] * tex_scale_x; nuclear@8: vptr->ty = tc[1] * tex_scale_y; nuclear@8: vptr++; nuclear@8: } nuclear@8: } nuclear@8: nuclear@8: iptr = iarr; nuclear@8: for(i=0; ivbo); nuclear@8: glGenBuffers(1, &m->ibo); nuclear@8: glBindBuffer(GL_ARRAY_BUFFER, m->vbo); nuclear@8: glBufferData(GL_ARRAY_BUFFER, num_verts * sizeof *varr, varr, GL_STATIC_DRAW); nuclear@8: glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo); nuclear@8: glBufferData(GL_ELEMENT_ARRAY_BUFFER, num_tris * 3 * sizeof *iarr, iarr, GL_STATIC_DRAW); nuclear@8: nuclear@8: m->prim = GL_TRIANGLES; nuclear@8: m->num_verts = num_verts; nuclear@8: m->num_faces = num_tris; nuclear@8: return 0; nuclear@8: } nuclear@8: nuclear@8: static void distort_texcoords(float *tc, float aspect, float lens_center_offset, float scale, nuclear@8: const float *dist_factors) nuclear@8: { nuclear@8: /* map tc [0, 1] -> [-1, 1] */ nuclear@8: float ptx = tc[0] * 2.0 - 1.0; nuclear@8: float pty = tc[1] * 2.0 - 1.0; nuclear@8: float rad; nuclear@8: nuclear@8: ptx += lens_center_offset * 2.0; nuclear@8: pty /= aspect; /* correct for aspect ratio */ nuclear@8: nuclear@8: rad = barrel_scale(ptx * ptx + pty * pty, dist_factors); nuclear@8: ptx *= rad; /* scale the point by the computer distortion radius */ nuclear@8: pty *= rad; nuclear@8: nuclear@8: ptx /= scale; nuclear@8: pty /= scale; nuclear@8: nuclear@8: pty *= aspect; nuclear@8: ptx -= lens_center_offset * 2.0; nuclear@8: nuclear@8: /* map back to range [0, 1] */ nuclear@8: tc[0] = ptx * 0.5 + 0.5; nuclear@8: tc[1] = pty * 0.5 + 0.5; nuclear@8: } nuclear@8: nuclear@8: static float barrel_scale(float rad, const float *k) nuclear@8: { nuclear@8: float radsq = rad * rad; nuclear@8: float radquad = radsq * radsq; nuclear@8: return k[0] + k[1] * radsq + k[2] * radquad + k[3] * radquad * radsq; nuclear@8: }