nuclear@1: #include nuclear@1: #include nuclear@1: #include "sanegl.h" nuclear@1: nuclear@1: #define MMODE_IDX(x) ((x) - GL_MODELVIEW) nuclear@1: #define MAT_STACK_SIZE 32 nuclear@1: #define MAT_IDENT {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1} nuclear@1: nuclear@1: #define MAX_VERTS 512 nuclear@1: nuclear@1: typedef struct { float x, y; } vec2_t; nuclear@1: typedef struct { float x, y, z; } vec3_t; nuclear@1: typedef struct { float x, y, z, w; } vec4_t; nuclear@1: nuclear@1: static int mm_idx = 0; nuclear@1: static float mat_stack[3][MAT_STACK_SIZE][16] = {{MAT_IDENT}, {MAT_IDENT}, {MAT_IDENT}}; nuclear@1: static int stack_top[3]; nuclear@1: static float mat_mvp[16]; nuclear@1: static int mvp_valid; nuclear@1: static int prim = -1; nuclear@1: nuclear@1: static vec3_t cur_normal; nuclear@1: static vec4_t cur_color, cur_attrib; nuclear@1: static vec2_t cur_texcoord; nuclear@1: nuclear@1: static vec4_t *vert_arr, *col_arr, *attr_arr; nuclear@1: static vec3_t *norm_arr; nuclear@1: static vec2_t *texc_arr; nuclear@1: static int vloc, nloc, cloc, tloc, aloc; nuclear@1: nuclear@1: nuclear@1: void gl_matrix_mode(int mm) nuclear@1: { nuclear@1: mm_idx = MMODE_IDX(mm); nuclear@1: } nuclear@1: nuclear@1: void gl_push_matrix(void) nuclear@1: { nuclear@1: int top = stack_top[mm_idx]; nuclear@1: nuclear@1: memcpy(mat_stack[mm_idx][top + 1], mat_stack[mm_idx][top], 16 * sizeof(float)); nuclear@1: stack_top[mm_idx]++; nuclear@1: mvp_valid = 0; nuclear@1: } nuclear@1: nuclear@1: void gl_pop_matrix(void) nuclear@1: { nuclear@1: stack_top[mm_idx]--; nuclear@1: mvp_valid = 0; nuclear@1: } nuclear@1: nuclear@1: void gl_load_identity(void) nuclear@1: { nuclear@1: static const float idmat[] = MAT_IDENT; nuclear@1: int top = stack_top[mm_idx]; nuclear@1: float *mat = mat_stack[mm_idx][top]; nuclear@1: nuclear@1: memcpy(mat, idmat, sizeof idmat); nuclear@1: mvp_valid = 0; nuclear@1: } nuclear@1: nuclear@1: void gl_load_matrixf(const float *m) nuclear@1: { nuclear@1: int top = stack_top[mm_idx]; nuclear@1: float *mat = mat_stack[mm_idx][top]; nuclear@1: nuclear@1: memcpy(mat, m, 16 * sizeof *mat); nuclear@1: mvp_valid = 0; nuclear@1: } nuclear@1: nuclear@1: #define M(i, j) ((i << 2) + j) nuclear@1: nuclear@1: void gl_mult_matrixf(const float *m2) nuclear@1: { nuclear@1: int i, j; nuclear@1: int top = stack_top[mm_idx]; nuclear@1: float *m1 = mat_stack[mm_idx][top]; nuclear@1: float res[16]; nuclear@1: nuclear@1: for(i=0; i<4; i++) { nuclear@1: for(j=0; j<4; j++) { nuclear@1: res[M(i,j)] = m1[M(i,0)] * m2[M(0,j)] + nuclear@1: m1[M(i,1)] * m2[M(1,j)] + nuclear@1: m1[M(i,2)] * m2[M(2,j)] + nuclear@1: m1[M(i,3)] * m2[M(3,j)]; nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: memcpy(m1, res, sizeof res); nuclear@1: mvp_valid = 0; nuclear@1: } nuclear@1: nuclear@1: void gl_translatef(float x, float y, float z) nuclear@1: { nuclear@1: float mat[] = MAT_IDENT; nuclear@1: nuclear@1: mat[12] = x; nuclear@1: mat[13] = y; nuclear@1: mat[14] = z; nuclear@1: nuclear@1: gl_mult_matrixf(mat); nuclear@1: } nuclear@1: nuclear@1: void gl_rotatef(float angle, float x, float y, float z) nuclear@1: { nuclear@1: float mat[] = MAT_IDENT; nuclear@1: nuclear@1: float angle_rad = M_PI * angle / 180.0; nuclear@1: float sina = sin(angle_rad); nuclear@1: float cosa = cos(angle_rad); nuclear@1: float one_minus_cosa = 1.0 - cosa; nuclear@1: float nxsq = x * x; nuclear@1: float nysq = y * y; nuclear@1: float nzsq = z * z; nuclear@1: nuclear@1: mat[0] = nxsq + (1.0 - nxsq) * cosa; nuclear@1: mat[4] = x * y * one_minus_cosa - z * sina; nuclear@1: mat[8] = x * z * one_minus_cosa + y * sina; nuclear@1: mat[1] = x * y * one_minus_cosa + z * sina; nuclear@1: mat[5] = nysq + (1.0 - nysq) * cosa; nuclear@1: mat[9] = y * z * one_minus_cosa - x * sina; nuclear@1: mat[2] = x * z * one_minus_cosa - y * sina; nuclear@1: mat[6] = y * z * one_minus_cosa + x * sina; nuclear@1: mat[10] = nzsq + (1.0 - nzsq) * cosa; nuclear@1: nuclear@1: gl_mult_matrixf(mat); nuclear@1: } nuclear@1: nuclear@1: void gl_scalef(float x, float y, float z) nuclear@1: { nuclear@1: float mat[] = MAT_IDENT; nuclear@1: nuclear@1: mat[0] = x; nuclear@1: mat[5] = y; nuclear@1: mat[10] = z; nuclear@1: nuclear@1: gl_mult_matrixf(mat); nuclear@1: } nuclear@1: nuclear@1: void gl_ortho(float left, float right, float bottom, float top, float near, float far) nuclear@1: { nuclear@1: float mat[] = MAT_IDENT; nuclear@1: nuclear@1: float dx = right - left; nuclear@1: float dy = top - bottom; nuclear@1: float dz = far - near; nuclear@1: nuclear@1: float tx = -(right + left) / dx; nuclear@1: float ty = -(top + bottom) / dy; nuclear@1: float tz = -(far + near) / dz; nuclear@1: nuclear@1: float sx = 2.0 / dx; nuclear@1: float sy = 2.0 / dy; nuclear@1: float sz = -2.0 / dz; nuclear@1: nuclear@1: mat[0] = sx; nuclear@1: mat[5] = sy; nuclear@1: mat[10] = sz; nuclear@1: mat[12] = tx; nuclear@1: mat[13] = ty; nuclear@1: mat[14] = tz; nuclear@1: nuclear@1: gl_mult_matrixf(mat); nuclear@1: } nuclear@1: nuclear@1: void gl_frustum(float left, float right, float bottom, float top, float near, float far) nuclear@1: { nuclear@1: float mat[] = MAT_IDENT; nuclear@1: nuclear@1: float dx = right - left; nuclear@1: float dy = top - bottom; nuclear@1: float dz = far - near; nuclear@1: nuclear@1: float a = (right + left) / dx; nuclear@1: float b = (top + bottom) / dy; nuclear@1: float c = -(far + near) / dz; nuclear@1: float d = -2.0 * far * near / dz; nuclear@1: nuclear@1: mat[0] = 2.0 * near / dx; nuclear@1: mat[5] = 2.0 * near / dy; nuclear@1: mat[8] = a; nuclear@1: mat[9] = b; nuclear@1: mat[10] = c; nuclear@1: mat[11] = -1.0; nuclear@1: mat[14] = d; nuclear@1: nuclear@1: gl_mult_matrixf(mat); nuclear@1: } nuclear@1: nuclear@1: void glu_perspective(float vfov, float aspect, float near, float far) nuclear@1: { nuclear@1: float x = near * tan(vfov / 2.0); nuclear@1: gl_frustum(-aspect * x, aspect * x, -x, x, near, far); nuclear@1: } nuclear@1: nuclear@1: void gl_apply_xform(unsigned int prog) nuclear@1: { nuclear@1: int loc, mvidx, pidx, tidx, mvtop, ptop, ttop; nuclear@1: nuclear@1: mvidx = MMODE_IDX(GL_MODELVIEW); nuclear@1: pidx = MMODE_IDX(GL_PROJECTION); nuclear@1: tidx = MMODE_IDX(GL_TEXTURE); nuclear@1: nuclear@1: mvtop = stack_top[mvidx]; nuclear@1: ptop = stack_top[pidx]; nuclear@1: ttop = stack_top[tidx]; nuclear@1: nuclear@1: if((loc = glGetUniformLocation(prog, "matrix_modelview")) != -1) { nuclear@1: glUniformMatrix4fv(loc, 16, 0, mat_stack[mvidx][mvtop]); nuclear@1: } nuclear@1: nuclear@1: if((loc = glGetUniformLocation(prog, "matrix_projection")) != -1) { nuclear@1: glUniformMatrix4fv(loc, 16, 0, mat_stack[pidx][ptop]); nuclear@1: } nuclear@1: nuclear@1: if((loc = glGetUniformLocation(prog, "matrix_texture")) != -1) { nuclear@1: glUniformMatrix4fv(loc, 16, 0, mat_stack[tidx][ttop]); nuclear@1: } nuclear@1: nuclear@1: if((loc = glGetUniformLocation(prog, "matrix_normal")) != -1) { nuclear@1: float nmat[9]; nuclear@1: nuclear@1: nmat[0] = mat_stack[mvidx][mvtop][0]; nuclear@1: nmat[1] = mat_stack[mvidx][mvtop][1]; nuclear@1: nmat[2] = mat_stack[mvidx][mvtop][2]; nuclear@1: nmat[3] = mat_stack[mvidx][mvtop][4]; nuclear@1: nmat[4] = mat_stack[mvidx][mvtop][5]; nuclear@1: nmat[5] = mat_stack[mvidx][mvtop][6]; nuclear@1: nmat[6] = mat_stack[mvidx][mvtop][8]; nuclear@1: nmat[7] = mat_stack[mvidx][mvtop][9]; nuclear@1: nmat[8] = mat_stack[mvidx][mvtop][10]; nuclear@1: glUniformMatrix3fv(loc, 9, 0, nmat); nuclear@1: } nuclear@1: nuclear@1: if((loc = glGetUniformLocation(prog, "matrix_modelview_projection")) != -1) { nuclear@1: if(!mvp_valid) { nuclear@1: /* TODO calc mvp */ nuclear@1: } nuclear@1: glUniformMatrix4fv(loc, 16, 0, mat_mvp); nuclear@1: } nuclear@1: }