# HG changeset patch # User John Tsiombikas # Date 1433041328 -10800 # Node ID ad49e1f9b627824bdca0b3dcb9a62409801b9d36 # Parent c71c477521ca982bfebdac20230de93ba02ba2ff foo diff -r c71c477521ca -r ad49e1f9b627 src/game.c --- a/src/game.c Sun May 31 00:40:26 2015 +0300 +++ b/src/game.c Sun May 31 06:02:08 2015 +0300 @@ -1,10 +1,12 @@ #include #include #include +#include #include "opengl.h" #include "game.h" #include "camera.h" #include "sdr.h" +#include "sanegl.h" static void draw_quad(float hsz, float vsz); @@ -13,22 +15,22 @@ static int video_width, video_height; static float video_aspect; static unsigned int sdrprog; -static int aloc_vertex, aloc_texcoord, uloc_texmat, uloc_wmat, uloc_vmat, uloc_pmat; +static int aloc_vertex, aloc_texcoord, uloc_tex; static const char *vsdr_source = - "attribute vec4 attr_pos, attr_tex;\n" - "uniform mat4 world_matrix, proj_matrix, tex_matrix;\n" + "attribute vec4 attr_vertex, attr_texcoord;\n" + "uniform mat4 matrix_modelview, matrix_projection, matrix_texture;\n" "varying vec4 tex_coords;\n" "void main()\n" "{\n" - "\tmat4 mvp = proj_matrix * world_matrix;\n" - "\tgl_Position = mvp * attr_pos;\n" - "\ttex_coords = tex_matrix * attr_tex;\n" + "\tmat4 mvp = matrix_projection * matrix_modelview;\n" + "\tgl_Position = mvp * attr_vertex;\n" + "\ttex_coords = matrix_texture * attr_texcoord;\n" "}\n"; static const char *psdr_source = "#extension GL_OES_EGL_image_external : require\n" - "precision lowp float;\n" + "precision mediump float;\n" "uniform samplerExternalOES tex;\n" "varying vec4 tex_coords;\n" "void main()\n" @@ -49,19 +51,18 @@ if(!(vsdr = create_vertex_shader(vsdr_source))) return -1; + assert(glGetError() == GL_NO_ERROR); if(!(psdr = create_pixel_shader(psdr_source))) return -1; + assert(glGetError() == GL_NO_ERROR); if(!(sdrprog = create_program_link(vsdr, psdr))) { fprintf(stderr, "failed to create shader program\n"); return -1; } glUseProgram(sdrprog); - aloc_vertex = glGetAttribLocation(sdrprog, "attr_pos"); - aloc_texcoord = glGetAttribLocation(sdrprog, "attr_tex"); - uloc_texmat = glGetUniformLocation(sdrprog, "tex_matrix"); - uloc_wmat = glGetUniformLocation(sdrprog, "world_matrix"); - uloc_vmat = glGetUniformLocation(sdrprog, "view_matrix"); - uloc_pmat = glGetUniformLocation(sdrprog, "proj_matrix"); + aloc_vertex = glGetAttribLocation(sdrprog, "attr_vertex"); + aloc_texcoord = glGetAttribLocation(sdrprog, "attr_texcoord"); + uloc_tex = glGetUniformLocation(sdrprog, "tex"); cam_start_video(); cam_video_size(&video_width, &video_height); @@ -96,9 +97,16 @@ //glClearColor(sin(tsec * 10.0), cos(tsec * 10.0), -sin(tsec * 10.0), 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + gl_matrix_mode(GL_MODELVIEW); + gl_load_identity(); + gl_matrix_mode(GL_TEXTURE); + gl_load_matrixf(tex_matrix); + glUseProgram(sdrprog); - glUniformMatrix4fv(uloc_texmat, 1, 0, tex_matrix); glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex); + if(uloc_tex >= 0) { + glUniform1i(uloc_tex, 0); + } if(video_aspect > win_aspect) { xscale = 1.0; @@ -114,19 +122,20 @@ { static const float varr[] = {-1, -1, 1, -1, 1, 1, -1, 1}; static const float tcarr[] = {0, 0, 1, 0, 1, 1, 0, 1}; - float xform[16] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; if(aloc_vertex == -1) { return; } - xform[0] = hsz; - xform[5] = vsz; - glUniformMatrix4fv(uloc_wmat, 1, 0, xform); + gl_matrix_mode(GL_MODELVIEW); + gl_push_matrix(); + gl_scalef(hsz, vsz, 1); + + gl_apply_xform(sdrprog); glEnableVertexAttribArray(aloc_vertex); glVertexAttribPointer(aloc_vertex, 2, GL_FLOAT, 0, 0, varr); - if(aloc_texcoord) { + if(aloc_texcoord != -1) { glEnableVertexAttribArray(aloc_texcoord); glVertexAttribPointer(aloc_texcoord, 2, GL_FLOAT, 0, 0, tcarr); } @@ -134,9 +143,11 @@ glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glDisableVertexAttribArray(aloc_vertex); - if(aloc_texcoord) { + if(aloc_texcoord != -1) { glDisableVertexAttribArray(aloc_texcoord); } + + gl_pop_matrix(); } void game_reshape(int x, int y) @@ -146,9 +157,9 @@ win_aspect = y ? (float)x / (float)y : 1.0; glViewport(0, 0, x, y); - /*glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glScalef((float)win_height / (float)win_width, 1.0, 1.0);*/ + gl_matrix_mode(GL_PROJECTION); + gl_load_identity(); + gl_scalef((float)win_height / (float)win_width, 1, 1); } void game_keyboard(int key, int pressed) diff -r c71c477521ca -r ad49e1f9b627 src/gfxstate.cc --- a/src/gfxstate.cc Sun May 31 00:40:26 2015 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -#include -#include "vmath/vmath.h" -#include "gfxstate.h" - -static std::stack mstack[NUM_MATRICES]; - -static bool init_stack(int midx) -{ - if(mstack[midx].empty()) { - mstack[midx].push(Matrix4x4::identity); - return true; - } - return false; -} - -void push_matrix(int midx) -{ - init_stack(midx); - mstack[midx].push(mstack[midx].top()); -} - -void pop_matrix(int midx) -{ - if(!mstack[midx].empty()) { - mstack[midx].pop(); - } -} - -void set_identity_matrix(int midx) -{ - set_matrix4x4(midx, Matrix4x4::identity); -} - -void set_matrix(int midx, const float *m) -{ - Matrix4x4 tmp; - memcpy(tmp[0], m, 16 * sizeof *m); - set_matrix4x4(midx, tmp.transposed()); -} - -void mult_matrix(int midx, const float *m) -{ - Matrix4x4 tmp; - memcpy(tmp[0], m, 16 * sizeof *m); - mult_matrix4x4(midx, tmp.transposed()); -} - -void get_matrix(int midx, float *m) -{ - Matrix4x4 tmp = get_matrix4x4(midx); - tmp.transpose(); - memcpy(m, tmp[0], 16 * sizeof *m); -} - -void set_matrix4x4(int midx, const Matrix4x4 &m) -{ - mstack[midx].top() = m; -} - -void mult_matrix4x4(int midx, const Matrix4x4 &m) -{ - mstack[midx].top() *= m; -} - -Matrix4x4 &get_matrix4x4(int midx) -{ - return mstack[midx].top(); -} diff -r c71c477521ca -r ad49e1f9b627 src/gfxstate.h --- a/src/gfxstate.h Sun May 31 00:40:26 2015 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -#ifndef GFXSTATE_H_ -#define GFXSTATE_H_ - -enum { - WORLD_MATRIX, - VIEW_MATRIX, - PROJECTION_MATRIX, - TEXTURE_MATRIX, - - NUM_MATRICES -}; - -#ifdef __cplusplus -extern "C" { -#endif - -void push_matrix(int midx); -void pop_matrix(int midx); - -void set_identity_matrix(int midx); -void set_matrix(int midx, const float *m); -void mult_matrix(int midx, const float *m); -void get_matrix(int midx, float *m); -float *get_matrix_ptr(int midx); - -#ifdef __cplusplus -} - -#ifdef VMATH_MATRIX_H_ -void set_matrix4x4(int midx, const Matrix4x4 &m); -void mult_matrix4x4(int midx, const Matrix4x4 &m); -Matrix4x4 &get_matrix4x4(int midx); -#endif /* VMATH_MATRIX_H_ */ - -#endif /* __cplusplus */ - -#endif /* GFXSTATE_H_ */ diff -r c71c477521ca -r ad49e1f9b627 src/opengl.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/opengl.c Sun May 31 06:02:08 2015 +0300 @@ -0,0 +1,21 @@ +#include "opengl.h" + +static const char *errstr[] = { + "GL_INVALID_ENUM", + "GL_INVALID_VALUE", + "GL_INVALID_OPERATION", + "GL_STACK_OVERFLOW", + "GL_STACK_UNDERFLOW", + "GL_OUT_OF_MEMORY" +}; + +const char *glerrstr(int err) +{ + if(!err) { + return "no error"; + } + if(err < GL_INVALID_ENUM || err > GL_OUT_OF_MEMORY) { + return "unknown error"; + } + return errstr[err - GL_INVALID_ENUM]; +} diff -r c71c477521ca -r ad49e1f9b627 src/opengl.h --- a/src/opengl.h Sun May 31 00:40:26 2015 +0300 +++ b/src/opengl.h Sun May 31 06:02:08 2015 +0300 @@ -9,4 +9,24 @@ #include #endif +#define CHECK_GLERROR \ + do { \ + int err = glGetError(); \ + if(err) { \ + fprintf(stderr, "%s:%d: OpenGL error %d: %s\n", __FILE__, __LINE__, err, glerrstr(err)); \ + abort(); \ + } \ + } while(0) + +#ifdef __cplusplus +extern "C" { +#endif + +const char *glerrstr(int err); + +#ifdef __cplusplus +} +#endif + + #endif /* OPENGL_H_ */ diff -r c71c477521ca -r ad49e1f9b627 src/sanegl.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sanegl.c Sun May 31 06:02:08 2015 +0300 @@ -0,0 +1,802 @@ +/* +SaneGL - a small library to bring back sanity to OpenGL ES 2.x +Copyright (C) 2011-2013 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include +#include +#include +#include +#include +#include "sanegl.h" + +#define MMODE_IDX(x) ((x) - GL_MODELVIEW) +#define MAT_STACK_SIZE 32 +#define MAT_IDENT {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1} + +#define MAX_VERTS 512 + +static void gl_draw_immediate(void); +static void m4_transpose(double *res, double *m); +static double m4_determinant(double *m); +static void m4_adjoint(double *res, double *m); +static void m4_inverse(double *res, double *m); + + +typedef struct { float x, y; } vec2_t; +typedef struct { float x, y, z; } vec3_t; +typedef struct { float x, y, z, w; } vec4_t; + +static int mm_idx = 0; +static float mat_stack[3][MAT_STACK_SIZE][16] = {{MAT_IDENT}, {MAT_IDENT}, {MAT_IDENT}}; +static int stack_top[3]; +static float mat_mvp[16]; +static int mvp_valid; +static int prim = -1; + +static vec3_t cur_normal; +static vec4_t cur_color, cur_attrib; +static vec2_t cur_texcoord; + +static vec4_t *vert_arr, *col_arr, *attr_arr; +static vec3_t *norm_arr; +static vec2_t *texc_arr; +/*static unsigned int vbuf, cbuf, nbuf, tbuf, abuf;*/ +static int vloc, nloc, cloc, tloc, aloc = -1; + +static int num_verts, vert_calls; +static int cur_prog; + +#ifdef GLDEF +#undef glEnable +#undef glDisable +#endif + +void gl_enable(int state) +{ + switch(state) { + case GL_TEXTURE_2D: + break; + + default: + glEnable(state); + } +} + +void gl_disable(int state) +{ + switch(state) { + case GL_TEXTURE_2D: + glBindTexture(state, 0); + break; + + default: + glDisable(state); + } +} + +void gl_matrix_mode(int mm) +{ + mm_idx = MMODE_IDX(mm); +} + +void gl_push_matrix(void) +{ + int top = stack_top[mm_idx]; + + memcpy(mat_stack[mm_idx][top + 1], mat_stack[mm_idx][top], 16 * sizeof(float)); + stack_top[mm_idx]++; + mvp_valid = 0; +} + +void gl_pop_matrix(void) +{ + stack_top[mm_idx]--; + mvp_valid = 0; +} + +void gl_load_identity(void) +{ + static const float idmat[] = MAT_IDENT; + int top = stack_top[mm_idx]; + float *mat = mat_stack[mm_idx][top]; + + memcpy(mat, idmat, sizeof idmat); + mvp_valid = 0; +} + +void gl_load_matrixf(const float *m) +{ + int top = stack_top[mm_idx]; + float *mat = mat_stack[mm_idx][top]; + + memcpy(mat, m, 16 * sizeof *mat); + mvp_valid = 0; +} + +void gl_load_matrixd(const double *m) +{ + int i; + float mf[16]; + + for(i=0; i<16; i++) { + mf[i] = (float)m[i]; + } + gl_load_matrixf(mf); +} + +#define M(i, j) ((i << 2) + j) + +void gl_mult_matrixf(const float *m2) +{ + int i, j; + int top = stack_top[mm_idx]; + float *m1 = mat_stack[mm_idx][top]; + float res[16]; + + for(i=0; i<4; i++) { + for(j=0; j<4; j++) { + res[M(i,j)] = m2[M(i,0)] * m1[M(0,j)] + + m2[M(i,1)] * m1[M(1,j)] + + m2[M(i,2)] * m1[M(2,j)] + + m2[M(i,3)] * m1[M(3,j)]; + } + } + + memcpy(m1, res, sizeof res); + mvp_valid = 0; +} + +void gl_mult_matrixd(const double *m) +{ + int i; + float mf[16]; + + for(i=0; i<16; i++) { + mf[i] = (float)m[i]; + } + gl_mult_matrixf(mf); +} + +void gl_translatef(float x, float y, float z) +{ + float mat[] = MAT_IDENT; + + mat[12] = x; + mat[13] = y; + mat[14] = z; + + gl_mult_matrixf(mat); +} + +void gl_rotatef(float angle, float x, float y, float z) +{ + float mat[] = MAT_IDENT; + + float angle_rad = M_PI * angle / 180.0; + float sina = sin(angle_rad); + float cosa = cos(angle_rad); + float one_minus_cosa = 1.0 - cosa; + float nxsq = x * x; + float nysq = y * y; + float nzsq = z * z; + + mat[0] = nxsq + (1.0 - nxsq) * cosa; + mat[4] = x * y * one_minus_cosa - z * sina; + mat[8] = x * z * one_minus_cosa + y * sina; + mat[1] = x * y * one_minus_cosa + z * sina; + mat[5] = nysq + (1.0 - nysq) * cosa; + mat[9] = y * z * one_minus_cosa - x * sina; + mat[2] = x * z * one_minus_cosa - y * sina; + mat[6] = y * z * one_minus_cosa + x * sina; + mat[10] = nzsq + (1.0 - nzsq) * cosa; + + gl_mult_matrixf(mat); +} + +void gl_scalef(float x, float y, float z) +{ + float mat[] = MAT_IDENT; + + mat[0] = x; + mat[5] = y; + mat[10] = z; + + gl_mult_matrixf(mat); +} + +void gl_ortho(float left, float right, float bottom, float top, float near, float far) +{ + float mat[] = MAT_IDENT; + + float dx = right - left; + float dy = top - bottom; + float dz = far - near; + + float tx = -(right + left) / dx; + float ty = -(top + bottom) / dy; + float tz = -(far + near) / dz; + + float sx = 2.0 / dx; + float sy = 2.0 / dy; + float sz = -2.0 / dz; + + mat[0] = sx; + mat[5] = sy; + mat[10] = sz; + mat[12] = tx; + mat[13] = ty; + mat[14] = tz; + + gl_mult_matrixf(mat); +} + +void gl_frustum(float left, float right, float bottom, float top, float near, float far) +{ + float mat[] = MAT_IDENT; + + float dx = right - left; + float dy = top - bottom; + float dz = far - near; + + float a = (right + left) / dx; + float b = (top + bottom) / dy; + float c = -(far + near) / dz; + float d = -2.0 * far * near / dz; + + mat[0] = 2.0 * near / dx; + mat[5] = 2.0 * near / dy; + mat[8] = a; + mat[9] = b; + mat[10] = c; + mat[11] = -1.0; + mat[14] = d; + mat[15] = 0.0; + + gl_mult_matrixf(mat); +} + +void glu_perspective(float vfov, float aspect, float near, float far) +{ + float vfov_rad = M_PI * vfov / 180.0; + float x = near * tan(vfov_rad / 2.0); + gl_frustum(-aspect * x, aspect * x, -x, x, near, far); +} + +int glu_un_project(double winx, double winy, double winz, + const double *model, const double *proj, const int *viewp, + double *objx, double *objy, double *objz) +{ + double mvp[16], inv_mvp[16]; + + double ndcx = 2.0 * (winx - viewp[0]) / viewp[2] - 1.0; + double ndcy = 2.0 * (winy - viewp[1]) / viewp[3] - 1.0; + double ndcz = 2.0 * winz - 1.0; + + // calculate modelviewprojection + gl_matrix_mode(GL_MODELVIEW); + gl_push_matrix(); + gl_load_matrixd(proj); + gl_mult_matrixd(model); + gl_get_doublev(GL_MODELVIEW_MATRIX, mvp); + gl_pop_matrix(); + + // invert modelviewprojection + m4_inverse(inv_mvp, mvp); + + // transform ndc by modelview -> obj + /**objx = inv_mvp[0] * ndcx + inv_mvp[4] * ndcy + inv_mvp[8] * ndcz + inv_mvp[12]; + *objy = inv_mvp[1] * ndcx + inv_mvp[5] * ndcy + inv_mvp[9] * ndcz + inv_mvp[13]; + *objz = inv_mvp[2] * ndcx + inv_mvp[6] * ndcy + inv_mvp[10] * ndcz + inv_mvp[14];*/ + *objx = inv_mvp[0] * ndcx + inv_mvp[1] * ndcy + inv_mvp[2] * ndcz + inv_mvp[3]; + *objy = inv_mvp[4] * ndcx + inv_mvp[5] * ndcy + inv_mvp[6] * ndcz + inv_mvp[7]; + *objz = inv_mvp[8] * ndcx + inv_mvp[9] * ndcy + inv_mvp[10] * ndcz + inv_mvp[11]; + return 0; +} + +void gl_apply_xform(unsigned int prog) +{ + int loc, mvidx, pidx, tidx, mvtop, ptop, ttop; + + mvidx = MMODE_IDX(GL_MODELVIEW); + pidx = MMODE_IDX(GL_PROJECTION); + tidx = MMODE_IDX(GL_TEXTURE); + + mvtop = stack_top[mvidx]; + ptop = stack_top[pidx]; + ttop = stack_top[tidx]; + + assert(prog); + + /*printf("APPLY XFORM\n");*/ + + CHECK_GLERROR; + if((loc = glGetUniformLocation(prog, "matrix_modelview")) != -1) { + CHECK_GLERROR; + /*printf(" MODELVIEW:\n"); + for(i=0; i<16; i+=4) { + printf("%.2f %.2f %.2f %.2f\n", mat_stack[mvidx][mvtop][i], mat_stack[mvidx][mvtop][i + 1], mat_stack[mvidx][mvtop][i + 2], mat_stack[mvidx][mvtop][i + 3]); + }*/ + glUniformMatrix4fv(loc, 1, 0, mat_stack[mvidx][mvtop]); + CHECK_GLERROR; + } + CHECK_GLERROR; + + if((loc = glGetUniformLocation(prog, "matrix_projection")) != -1) { + CHECK_GLERROR; + /*printf(" PROJECTION:\n"); + for(i=0; i<16; i+=4) { + printf("%.2f %.2f %.2f %.2f\n", mat_stack[pidx][ptop][i], mat_stack[pidx][ptop][i + 1], mat_stack[pidx][ptop][i + 2], mat_stack[pidx][ptop][i + 3]); + }*/ + glUniformMatrix4fv(loc, 1, 0, mat_stack[pidx][ptop]); + CHECK_GLERROR; + } + CHECK_GLERROR; + + if((loc = glGetUniformLocation(prog, "matrix_texture")) != -1) { + CHECK_GLERROR; + glUniformMatrix4fv(loc, 1, 0, mat_stack[tidx][ttop]); + CHECK_GLERROR; + } + CHECK_GLERROR; + + if((loc = glGetUniformLocation(prog, "matrix_normal")) != -1) { + float nmat[9]; + + CHECK_GLERROR; + + nmat[0] = mat_stack[mvidx][mvtop][0]; + nmat[1] = mat_stack[mvidx][mvtop][1]; + nmat[2] = mat_stack[mvidx][mvtop][2]; + nmat[3] = mat_stack[mvidx][mvtop][4]; + nmat[4] = mat_stack[mvidx][mvtop][5]; + nmat[5] = mat_stack[mvidx][mvtop][6]; + nmat[6] = mat_stack[mvidx][mvtop][8]; + nmat[7] = mat_stack[mvidx][mvtop][9]; + nmat[8] = mat_stack[mvidx][mvtop][10]; + glUniformMatrix3fv(loc, 1, 0, nmat); + CHECK_GLERROR; + } + CHECK_GLERROR; + + if((loc = glGetUniformLocation(prog, "matrix_modelview_projection")) != -1) { + CHECK_GLERROR; + if(!mvp_valid) { + /* TODO calc mvp */ + } + glUniformMatrix4fv(loc, 1, 0, mat_mvp); + CHECK_GLERROR; + } + CHECK_GLERROR; +} + + +/* immediate mode rendering */ +void gl_begin(int p) +{ + if(!vert_arr) { + vert_arr = malloc(MAX_VERTS * sizeof *vert_arr); + norm_arr = malloc(MAX_VERTS * sizeof *norm_arr); + texc_arr = malloc(MAX_VERTS * sizeof *texc_arr); + col_arr = malloc(MAX_VERTS * sizeof *col_arr); + attr_arr = malloc(MAX_VERTS * sizeof *attr_arr); + assert(vert_arr && norm_arr && texc_arr && col_arr && attr_arr); + } + + prim = p; + num_verts = vert_calls = 0; + + glGetIntegerv(GL_CURRENT_PROGRAM, &cur_prog); + CHECK_GLERROR; + assert(cur_prog); + + gl_apply_xform(cur_prog); + CHECK_GLERROR; + + vloc = glGetAttribLocation(cur_prog, "attr_vertex"); + CHECK_GLERROR; + nloc = glGetAttribLocation(cur_prog, "attr_normal"); + CHECK_GLERROR; + cloc = glGetAttribLocation(cur_prog, "attr_color"); + CHECK_GLERROR; + tloc = glGetAttribLocation(cur_prog, "attr_texcoord"); + CHECK_GLERROR; +} + +void gl_end(void) +{ + if(num_verts > 0) { + gl_draw_immediate(); + } + aloc = -1; +} + +static void gl_draw_immediate(void) +{ + int glprim; + + if(vloc == -1) { + fprintf(stderr, "gl_draw_immediate call with vloc == -1\n"); + return; + } + + glprim = prim == GL_QUADS ? GL_TRIANGLES : prim; + + CHECK_GLERROR; + glVertexAttribPointer(vloc, 4, GL_FLOAT, 0, 0, vert_arr); + CHECK_GLERROR; + glEnableVertexAttribArray(vloc); + CHECK_GLERROR; + + if(nloc != -1) { + glVertexAttribPointer(nloc, 3, GL_FLOAT, 0, 0, norm_arr); + CHECK_GLERROR; + glEnableVertexAttribArray(nloc); + CHECK_GLERROR; + } + + if(cloc != -1) { + glVertexAttribPointer(cloc, 4, GL_FLOAT, 1, 0, col_arr); + CHECK_GLERROR; + glEnableVertexAttribArray(cloc); + CHECK_GLERROR; + } + + if(tloc != -1) { + glVertexAttribPointer(tloc, 2, GL_FLOAT, 0, 0, texc_arr); + CHECK_GLERROR; + glEnableVertexAttribArray(tloc); + CHECK_GLERROR; + } + + if(aloc != -1) { + glVertexAttribPointer(aloc, 4, GL_FLOAT, 0, 0, attr_arr); + CHECK_GLERROR; + glEnableVertexAttribArray(aloc); + CHECK_GLERROR; + } + + glDrawArrays(glprim, 0, num_verts); + CHECK_GLERROR; + + glDisableVertexAttribArray(vloc); + CHECK_GLERROR; + if(nloc != -1) { + glDisableVertexAttribArray(nloc); + CHECK_GLERROR; + } + if(cloc != -1) { + glDisableVertexAttribArray(cloc); + CHECK_GLERROR; + } + if(tloc != -1) { + glDisableVertexAttribArray(tloc); + CHECK_GLERROR; + } + if(aloc != -1) { + glDisableVertexAttribArray(aloc); + CHECK_GLERROR; + } +} + + +void gl_vertex2f(float x, float y) +{ + gl_vertex4f(x, y, 0.0f, 1.0f); +} + +void gl_vertex3f(float x, float y, float z) +{ + gl_vertex4f(x, y, z, 1.0f); +} + +void gl_vertex4f(float x, float y, float z, float w) +{ + int i, buffer_full; + + if(prim == GL_QUADS && vert_calls % 4 == 3) { + for(i=0; i<2; i++) { + if(aloc != -1) { + attr_arr[num_verts] = attr_arr[num_verts - 3 + i]; + } + if(cloc != -1) { + col_arr[num_verts] = col_arr[num_verts - 3 + i]; + } + if(tloc != -1) { + texc_arr[num_verts] = texc_arr[num_verts - 3 + i]; + } + if(nloc != -1) { + norm_arr[num_verts] = norm_arr[num_verts - 3 + i]; + } + vert_arr[num_verts] = vert_arr[num_verts - 3 + i]; + num_verts++; + } + } + + vert_arr[num_verts].x = x; + vert_arr[num_verts].y = y; + vert_arr[num_verts].z = z; + vert_arr[num_verts].w = w; + + if(cloc != -1) { + col_arr[num_verts] = cur_color; + } + if(nloc != -1) { + norm_arr[num_verts] = cur_normal; + } + if(tloc != -1) { + texc_arr[num_verts] = cur_texcoord; + } + if(aloc != -1) { + attr_arr[num_verts] = cur_attrib; + } + + vert_calls++; + num_verts++; + + if(prim == GL_QUADS) { + /* leave space for 6 more worst-case and don't allow flushes mid-quad */ + buffer_full = num_verts >= MAX_VERTS - 6 && vert_calls % 4 == 0; + } else { + buffer_full = num_verts >= MAX_VERTS - prim; + } + + if(buffer_full) { + gl_draw_immediate(); + gl_begin(prim); /* reset everything */ + } +} + + +void gl_normal3f(float x, float y, float z) +{ + cur_normal.x = x; + cur_normal.y = y; + cur_normal.z = z; +} + + +void gl_color3f(float r, float g, float b) +{ + cur_color.x = r; + cur_color.y = g; + cur_color.z = b; + cur_color.w = 1.0f; +} + +void gl_color4f(float r, float g, float b, float a) +{ + cur_color.x = r; + cur_color.y = g; + cur_color.z = b; + cur_color.w = a; +} + + +void gl_texcoord1f(float s) +{ + cur_texcoord.x = s; + cur_texcoord.y = 0.0f; +} + +void gl_texcoord2f(float s, float t) +{ + cur_texcoord.x = s; + cur_texcoord.y = t; +} + +void gl_vertex_attrib2f(int loc, float x, float y) +{ + aloc = loc; + cur_attrib.x = x; + cur_attrib.y = y; + cur_attrib.z = 0.0f; + cur_attrib.w = 1.0f; +} + +void gl_vertex_attrib3f(int loc, float x, float y, float z) +{ + aloc = loc; + cur_attrib.x = x; + cur_attrib.y = y; + cur_attrib.z = z; + cur_attrib.w = 1.0f; +} + +void gl_vertex_attrib4f(int loc, float x, float y, float z, float w) +{ + aloc = loc; + cur_attrib.x = x; + cur_attrib.y = y; + cur_attrib.z = z; + cur_attrib.w = w; +} + +#ifdef GLDEF +#undef glGetFloatv +#endif + +void gl_get_floatv(int what, float *res) +{ + int idx; + + switch(what) { + case GL_MODELVIEW_MATRIX: + idx = MMODE_IDX(GL_MODELVIEW); + memcpy(res, mat_stack[idx][stack_top[idx]], 16 * sizeof *res); + break; + + case GL_PROJECTION_MATRIX: + idx = MMODE_IDX(GL_PROJECTION); + memcpy(res, mat_stack[idx][stack_top[idx]], 16 * sizeof *res); + break; + + default: + glGetFloatv(what, res); + } +} + +void gl_get_doublev(int what, double *res) +{ + int i, idx; + float tmp[16]; + + switch(what) { + case GL_MODELVIEW_MATRIX: + if(1) { + idx = MMODE_IDX(GL_MODELVIEW); + } else { + case GL_PROJECTION_MATRIX: + idx = MMODE_IDX(GL_PROJECTION); + } + for(i=0; i<16; i++) { + res[i] = mat_stack[idx][stack_top[idx]][i]; + } + break; + + default: + glGetFloatv(what, tmp); + for(i=0; i<16; i++) { + res[i] = tmp[i]; + } + } +} + + +/* ---- matrix inversion stuff ---- */ +static void m4_transpose(double *res, double *m) +{ + int i, j; + double tmp[16]; + + if(res == m) { + memcpy(tmp, m, 16 * sizeof *m); + m = tmp; + } + + for(i=0; i<4; i++) { + for(j=0; j<4; j++) { + res[M(i, j)] = m[M(j, i)]; + } + } +} + +static double m4_determinant(double *m) +{ + double det11, det12, det13, det14; + + det11 = (m[M(1, 1)] * (m[M(2, 2)] * m[M(3, 3)] - m[M(3, 2)] * m[M(2, 3)])) - + (m[M(1, 2)] * (m[M(2, 1)] * m[M(3, 3)] - m[M(3, 1)] * m[M(2, 3)])) + + (m[M(1, 3)] * (m[M(2, 1)] * m[M(3, 2)] - m[M(3, 1)] * m[M(2, 2)])); + + det12 = (m[M(1, 0)] * (m[M(2, 2)] * m[M(3, 3)] - m[M(3, 2)] * m[M(2, 3)])) - + (m[M(1, 2)] * (m[M(2, 0)] * m[M(3, 3)] - m[M(3, 0)] * m[M(2, 3)])) + + (m[M(1, 3)] * (m[M(2, 0)] * m[M(3, 2)] - m[M(3, 0)] * m[M(2, 2)])); + + det13 = (m[M(1, 0)] * (m[M(2, 1)] * m[M(3, 3)] - m[M(3, 1)] * m[M(2, 3)])) - + (m[M(1, 1)] * (m[M(2, 0)] * m[M(3, 3)] - m[M(3, 0)] * m[M(2, 3)])) + + (m[M(1, 3)] * (m[M(2, 0)] * m[M(3, 1)] - m[M(3, 0)] * m[M(2, 1)])); + + det14 = (m[M(1, 0)] * (m[M(2, 1)] * m[M(3, 2)] - m[M(3, 1)] * m[M(2, 2)])) - + (m[M(1, 1)] * (m[M(2, 0)] * m[M(3, 2)] - m[M(3, 0)] * m[M(2, 2)])) + + (m[M(1, 2)] * (m[M(2, 0)] * m[M(3, 1)] - m[M(3, 0)] * m[M(2, 1)])); + + return m[M(0, 0)] * det11 - m[M(0, 1)] * det12 + m[M(0, 2)] * det13 - m[M(0, 3)] * det14; +} + +static void m4_adjoint(double *res, double *m) +{ + int i, j; + double coef[16]; + + coef[M(0, 0)] = (m[M(1, 1)] * (m[M(2, 2)] * m[M(3, 3)] - m[M(3, 2)] * m[M(2, 3)])) - + (m[M(1, 2)] * (m[M(2, 1)] * m[M(3, 3)] - m[M(3, 1)] * m[M(2, 3)])) + + (m[M(1, 3)] * (m[M(2, 1)] * m[M(3, 2)] - m[M(3, 1)] * m[M(2, 2)])); + coef[M(0, 1)] = (m[M(1, 0)] * (m[M(2, 2)] * m[M(3, 3)] - m[M(3, 2)] * m[M(2, 3)])) - + (m[M(1, 2)] * (m[M(2, 0)] * m[M(3, 3)] - m[M(3, 0)] * m[M(2, 3)])) + + (m[M(1, 3)] * (m[M(2, 0)] * m[M(3, 2)] - m[M(3, 0)] * m[M(2, 2)])); + coef[M(0, 2)] = (m[M(1, 0)] * (m[M(2, 1)] * m[M(3, 3)] - m[M(3, 1)] * m[M(2, 3)])) - + (m[M(1, 1)] * (m[M(2, 0)] * m[M(3, 3)] - m[M(3, 0)] * m[M(2, 3)])) + + (m[M(1, 3)] * (m[M(2, 0)] * m[M(3, 1)] - m[M(3, 0)] * m[M(2, 1)])); + coef[M(0, 3)] = (m[M(1, 0)] * (m[M(2, 1)] * m[M(3, 2)] - m[M(3, 1)] * m[M(2, 2)])) - + (m[M(1, 1)] * (m[M(2, 0)] * m[M(3, 2)] - m[M(3, 0)] * m[M(2, 2)])) + + (m[M(1, 2)] * (m[M(2, 0)] * m[M(3, 1)] - m[M(3, 0)] * m[M(2, 1)])); + + coef[M(1, 0)] = (m[M(0, 1)] * (m[M(2, 2)] * m[M(3, 3)] - m[M(3, 2)] * m[M(2, 3)])) - + (m[M(0, 2)] * (m[M(2, 1)] * m[M(3, 3)] - m[M(3, 1)] * m[M(2, 3)])) + + (m[M(0, 3)] * (m[M(2, 1)] * m[M(3, 2)] - m[M(3, 1)] * m[M(2, 2)])); + coef[M(1, 1)] = (m[M(0, 0)] * (m[M(2, 2)] * m[M(3, 3)] - m[M(3, 2)] * m[M(2, 3)])) - + (m[M(0, 2)] * (m[M(2, 0)] * m[M(3, 3)] - m[M(3, 0)] * m[M(2, 3)])) + + (m[M(0, 3)] * (m[M(2, 0)] * m[M(3, 2)] - m[M(3, 0)] * m[M(2, 2)])); + coef[M(1, 2)] = (m[M(0, 0)] * (m[M(2, 1)] * m[M(3, 3)] - m[M(3, 1)] * m[M(2, 3)])) - + (m[M(0, 1)] * (m[M(2, 0)] * m[M(3, 3)] - m[M(3, 0)] * m[M(2, 3)])) + + (m[M(0, 3)] * (m[M(2, 0)] * m[M(3, 1)] - m[M(3, 0)] * m[M(2, 1)])); + coef[M(1, 3)] = (m[M(0, 0)] * (m[M(2, 1)] * m[M(3, 2)] - m[M(3, 1)] * m[M(2, 2)])) - + (m[M(0, 1)] * (m[M(2, 0)] * m[M(3, 2)] - m[M(3, 0)] * m[M(2, 2)])) + + (m[M(0, 2)] * (m[M(2, 0)] * m[M(3, 1)] - m[M(3, 0)] * m[M(2, 1)])); + + coef[M(2, 0)] = (m[M(0, 1)] * (m[M(1, 2)] * m[M(3, 3)] - m[M(3, 2)] * m[M(1, 3)])) - + (m[M(0, 2)] * (m[M(1, 1)] * m[M(3, 3)] - m[M(3, 1)] * m[M(1, 3)])) + + (m[M(0, 3)] * (m[M(1, 1)] * m[M(3, 2)] - m[M(3, 1)] * m[M(1, 2)])); + coef[M(2, 1)] = (m[M(0, 0)] * (m[M(1, 2)] * m[M(3, 3)] - m[M(3, 2)] * m[M(1, 3)])) - + (m[M(0, 2)] * (m[M(1, 0)] * m[M(3, 3)] - m[M(3, 0)] * m[M(1, 3)])) + + (m[M(0, 3)] * (m[M(1, 0)] * m[M(3, 2)] - m[M(3, 0)] * m[M(1, 2)])); + coef[M(2, 2)] = (m[M(0, 0)] * (m[M(1, 1)] * m[M(3, 3)] - m[M(3, 1)] * m[M(1, 3)])) - + (m[M(0, 1)] * (m[M(1, 0)] * m[M(3, 3)] - m[M(3, 0)] * m[M(1, 3)])) + + (m[M(0, 3)] * (m[M(1, 0)] * m[M(3, 1)] - m[M(3, 0)] * m[M(1, 1)])); + coef[M(2, 3)] = (m[M(0, 0)] * (m[M(1, 1)] * m[M(3, 2)] - m[M(3, 1)] * m[M(1, 2)])) - + (m[M(0, 1)] * (m[M(1, 0)] * m[M(3, 2)] - m[M(3, 0)] * m[M(1, 2)])) + + (m[M(0, 2)] * (m[M(1, 0)] * m[M(3, 1)] - m[M(3, 0)] * m[M(1, 1)])); + + coef[M(3, 0)] = (m[M(0, 1)] * (m[M(1, 2)] * m[M(2, 3)] - m[M(2, 2)] * m[M(1, 3)])) - + (m[M(0, 2)] * (m[M(1, 1)] * m[M(2, 3)] - m[M(2, 1)] * m[M(1, 3)])) + + (m[M(0, 3)] * (m[M(1, 1)] * m[M(2, 2)] - m[M(2, 1)] * m[M(1, 2)])); + coef[M(3, 1)] = (m[M(0, 0)] * (m[M(1, 2)] * m[M(2, 3)] - m[M(2, 2)] * m[M(1, 3)])) - + (m[M(0, 2)] * (m[M(1, 0)] * m[M(2, 3)] - m[M(2, 0)] * m[M(1, 3)])) + + (m[M(0, 3)] * (m[M(1, 0)] * m[M(2, 2)] - m[M(2, 0)] * m[M(1, 2)])); + coef[M(3, 2)] = (m[M(0, 0)] * (m[M(1, 1)] * m[M(2, 3)] - m[M(2, 1)] * m[M(1, 3)])) - + (m[M(0, 1)] * (m[M(1, 0)] * m[M(2, 3)] - m[M(2, 0)] * m[M(1, 3)])) + + (m[M(0, 3)] * (m[M(1, 0)] * m[M(2, 1)] - m[M(2, 0)] * m[M(1, 1)])); + coef[M(3, 3)] = (m[M(0, 0)] * (m[M(1, 1)] * m[M(2, 2)] - m[M(2, 1)] * m[M(1, 2)])) - + (m[M(0, 1)] * (m[M(1, 0)] * m[M(2, 2)] - m[M(2, 0)] * m[M(1, 2)])) + + (m[M(0, 2)] * (m[M(1, 0)] * m[M(2, 1)] - m[M(2, 0)] * m[M(1, 1)])); + + m4_transpose(res, coef); + + for(i=0; i<4; i++) { + for(j=0; j<4; j++) { + res[M(i, j)] = j % 2 ? -res[M(i, j)] : res[M(i, j)]; + if(i % 2) res[M(i, j)] = -res[M(i, j)]; + } + } +} + +static void m4_inverse(double *res, double *m) +{ + int i, j; + double adj[16]; + double det; + + m4_adjoint(adj, m); + det = m4_determinant(m); + + for(i=0; i<4; i++) { + for(j=0; j<4; j++) { + res[M(i, j)] = adj[M(i, j)] / det; + } + } +} + diff -r c71c477521ca -r ad49e1f9b627 src/sanegl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sanegl.h Sun May 31 06:02:08 2015 +0300 @@ -0,0 +1,154 @@ +/* +SaneGL - a small library to bring back sanity to OpenGL ES 2.x +Copyright (C) 2011-2013 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#ifndef SANEGL_H_ +#define SANEGL_H_ + +#include "opengl.h" + +#ifndef GL_MODELVIEW +#define GL_MODELVIEW 0x1700 +#endif +#ifndef GL_PROJECTION +#define GL_PROJECTION 0x1701 +#endif +#ifndef GL_TEXTURE +#define GL_TEXTURE 0x1702 +#endif + +#ifndef GL_POINTS +#define GL_POINTS 0 +#endif +#ifndef GL_LINES +#define GL_LINES 1 +#endif +#ifndef GL_TRIANGLES +#define GL_TRIANGLES 4 +#endif +#ifndef GL_QUADS +#define GL_QUADS 7 +#endif + +/* glGet stuff */ +#ifndef GL_VIEWPORT +#define GL_VIEWPORT 0x0BA2 +#endif +#ifndef GL_MODELVIEW_MATRIX +#define GL_MODELVIEW_MATRIX 0x0BA6 +#endif +#ifndef GL_PROJECTION_MATRIX +#define GL_PROJECTION_MATRIX 0x0BA7 +#endif + +#ifdef GLDEF + +#define glEnable gl_enable +#define glDisable gl_disable + +#define glMatrixMode gl_matrix_mode +#define glPushMatrix gl_push_matrix +#define glPopMatrix gl_pop_matrix +#define glLoadIdentity gl_load_identity +#define glLoadMatrixf gl_load_matrixf +#define glLoadMatrixd gl_load_matrixd +#define glMultMatrixf gl_mult_matrixf +#define glMultMatrixd gl_mult_matrixd +#define glTranslatef gl_translatef +#define glRotatef gl_rotatef +#define glScalef gl_scalef +#define glOrtho gl_ortho +#define glFrustum gl_frustum +#define gluPerspective glu_perspective +#define gluUnProject glu_un_project + +#define glBegin gl_begin +#define glEnd gl_end +#define glVertex2f gl_vertex2f +#define glVertex3f gl_vertex3f +#define glVertex4f gl_vertex4f +#define glNormal3f gl_normal3f +#define glColor3f gl_color3f +#define glColor4f gl_color4f +#define glTexCoord1f gl_texcoord1f +#define glTexCoord2f gl_texcoord2f +#define glVertexAttrib2f gl_vertex_attrib2f +#define glVertexAttrib3f gl_vertex_attrib3f +#define glVertexAttrib4f gl_vertex_attrib4f + +#define glGetFloatv gl_get_floatv +#define glGetDoublev gl_get_doublev +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +void gl_enable(int state); +void gl_disable(int state); + +/* matrix stuff */ +void gl_matrix_mode(int mmode); +void gl_push_matrix(void); +void gl_pop_matrix(void); +void gl_load_identity(void); +void gl_load_matrixf(const float *mat); +void gl_load_matrixd(const double *mat); +void gl_mult_matrixf(const float *mat); +void gl_mult_matrixd(const double *mat); +void gl_translatef(float x, float y, float z); +void gl_rotatef(float angle, float x, float y, float z); +void gl_scalef(float x, float y, float z); +void gl_ortho(float left, float right, float bottom, float top, float near, float far); +void gl_frustum(float left, float right, float bottom, float top, float near, float far); +void glu_perspective(float vfov, float aspect, float near, float far); +int glu_un_project(double winx, double winy, double winz, + const double *model, const double *proj, const int *viewp, + double *objx, double *objy, double *objz); + +void gl_apply_xform(unsigned int prog); + + +/* immediate mode rendering */ +void gl_begin(int prim); +void gl_end(void); + +void gl_vertex2f(float x, float y); +void gl_vertex3f(float x, float y, float z); +void gl_vertex4f(float x, float y, float z, float w); + +void gl_normal3f(float x, float y, float z); + +void gl_color3f(float r, float g, float b); +void gl_color4f(float r, float g, float b, float a); + +void gl_texcoord1f(float s); +void gl_texcoord2f(float s, float t); + +void gl_vertex_attrib2f(int loc, float x, float y); +void gl_vertex_attrib3f(int loc, float x, float y, float z); +void gl_vertex_attrib4f(int loc, float x, float y, float z, float w); + +/* state retrieval */ +void gl_get_floatv(int what, float *res); +void gl_get_doublev(int what, double *res); + +#ifdef __cplusplus +} +#endif + +#endif /* SANEGL_H_ */