nuclear@3: /* nuclear@3: SaneGL - a small library to bring back sanity to OpenGL ES 2.x nuclear@3: Copyright (C) 2011-2013 John Tsiombikas nuclear@3: nuclear@3: This program is free software: you can redistribute it and/or modify nuclear@3: it under the terms of the GNU General Public License as published by nuclear@3: the Free Software Foundation, either version 3 of the License, or nuclear@3: (at your option) any later version. nuclear@3: nuclear@3: This program is distributed in the hope that it will be useful, nuclear@3: but WITHOUT ANY WARRANTY; without even the implied warranty of nuclear@3: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nuclear@3: GNU General Public License for more details. nuclear@3: nuclear@3: You should have received a copy of the GNU General Public License nuclear@3: along with this program. If not, see . nuclear@3: */ nuclear@3: nuclear@3: #include nuclear@3: #include nuclear@3: #include nuclear@3: #include nuclear@3: #include nuclear@3: #include "sanegl.h" nuclear@3: nuclear@3: #define MAX_VERTS 512 nuclear@3: nuclear@3: static void gl_draw_immediate(void); nuclear@3: nuclear@3: typedef struct { float x, y; } vec2_t; nuclear@3: typedef struct { float x, y, z; } vec3_t; nuclear@3: typedef struct { float x, y, z, w; } vec4_t; nuclear@3: nuclear@3: static int prim = -1; nuclear@3: nuclear@3: static vec3_t cur_normal; nuclear@3: static vec4_t cur_color; nuclear@3: static vec2_t cur_texcoord; nuclear@3: nuclear@3: static vec4_t *vert_arr, *col_arr; nuclear@3: static vec3_t *norm_arr; nuclear@3: static vec2_t *texc_arr; nuclear@3: nuclear@3: static int num_verts, vert_calls; nuclear@3: nuclear@3: /* immediate mode rendering */ nuclear@3: void gl_begin(int p) nuclear@3: { nuclear@3: if(!vert_arr) { nuclear@3: vert_arr = malloc(MAX_VERTS * sizeof *vert_arr); nuclear@3: norm_arr = malloc(MAX_VERTS * sizeof *norm_arr); nuclear@3: texc_arr = malloc(MAX_VERTS * sizeof *texc_arr); nuclear@3: col_arr = malloc(MAX_VERTS * sizeof *col_arr); nuclear@3: assert(vert_arr && norm_arr && texc_arr && col_arr); nuclear@3: } nuclear@3: nuclear@3: prim = p; nuclear@3: num_verts = vert_calls = 0; nuclear@3: } nuclear@3: nuclear@3: void gl_end(void) nuclear@3: { nuclear@3: if(num_verts > 0) { nuclear@3: gl_draw_immediate(); nuclear@3: } nuclear@3: } nuclear@3: nuclear@3: static void gl_draw_immediate(void) nuclear@3: { nuclear@3: int glprim; nuclear@3: nuclear@3: glprim = prim == GL_QUADS ? GL_TRIANGLES : prim; nuclear@3: nuclear@3: glEnableClientState(GL_VERTEX_ARRAY); nuclear@3: glEnableClientState(GL_NORMAL_ARRAY); nuclear@3: glEnableClientState(GL_COLOR_ARRAY); nuclear@3: glEnableClientState(GL_TEXTURE_COORD_ARRAY); nuclear@3: nuclear@3: glVertexPointer(4, GL_FLOAT, 0, vert_arr); nuclear@3: glNormalPointer(GL_FLOAT, 0, norm_arr); nuclear@3: glColorPointer(4, GL_FLOAT, 0, col_arr); nuclear@3: glTexCoordPointer(2, GL_FLOAT, 0, texc_arr); nuclear@3: nuclear@3: glDrawArrays(glprim, 0, num_verts); nuclear@3: nuclear@3: glDisableClientState(GL_VERTEX_ARRAY); nuclear@3: glDisableClientState(GL_NORMAL_ARRAY); nuclear@3: glDisableClientState(GL_COLOR_ARRAY); nuclear@3: glDisableClientState(GL_TEXTURE_COORD_ARRAY); nuclear@3: } nuclear@3: nuclear@3: void gl_vertex2f(float x, float y) nuclear@3: { nuclear@3: gl_vertex4f(x, y, 0.0f, 1.0f); nuclear@3: } nuclear@3: nuclear@3: void gl_vertex3f(float x, float y, float z) nuclear@3: { nuclear@3: gl_vertex4f(x, y, z, 1.0f); nuclear@3: } nuclear@3: nuclear@3: void gl_vertex4f(float x, float y, float z, float w) nuclear@3: { nuclear@3: int i, buffer_full; nuclear@3: nuclear@3: if(prim == GL_QUADS && vert_calls % 4 == 3) { nuclear@3: for(i=0; i<2; i++) { nuclear@3: col_arr[num_verts] = col_arr[num_verts - 3 + i]; nuclear@3: texc_arr[num_verts] = texc_arr[num_verts - 3 + i]; nuclear@3: norm_arr[num_verts] = norm_arr[num_verts - 3 + i]; nuclear@3: vert_arr[num_verts] = vert_arr[num_verts - 3 + i]; nuclear@3: num_verts++; nuclear@3: } nuclear@3: } nuclear@3: nuclear@3: vert_arr[num_verts].x = x; nuclear@3: vert_arr[num_verts].y = y; nuclear@3: vert_arr[num_verts].z = z; nuclear@3: vert_arr[num_verts].w = w; nuclear@3: nuclear@3: col_arr[num_verts] = cur_color; nuclear@3: norm_arr[num_verts] = cur_normal; nuclear@3: texc_arr[num_verts] = cur_texcoord; nuclear@3: nuclear@3: vert_calls++; nuclear@3: num_verts++; nuclear@3: nuclear@3: if(prim == GL_QUADS) { nuclear@3: /* leave space for 6 more worst-case and don't allow flushes mid-quad */ nuclear@3: buffer_full = num_verts >= MAX_VERTS - 6 && vert_calls % 4 == 0; nuclear@3: } else { nuclear@3: buffer_full = num_verts >= MAX_VERTS - prim; nuclear@3: } nuclear@3: nuclear@3: if(buffer_full) { nuclear@3: gl_draw_immediate(); nuclear@3: gl_begin(prim); /* reset everything */ nuclear@3: } nuclear@3: } nuclear@3: nuclear@3: nuclear@3: void gl_normal3f(float x, float y, float z) nuclear@3: { nuclear@3: cur_normal.x = x; nuclear@3: cur_normal.y = y; nuclear@3: cur_normal.z = z; nuclear@3: } nuclear@3: nuclear@3: nuclear@3: void gl_color3f(float r, float g, float b) nuclear@3: { nuclear@3: cur_color.x = r; nuclear@3: cur_color.y = g; nuclear@3: cur_color.z = b; nuclear@3: cur_color.w = 1.0f; nuclear@3: } nuclear@3: nuclear@3: void gl_color4f(float r, float g, float b, float a) nuclear@3: { nuclear@3: cur_color.x = r; nuclear@3: cur_color.y = g; nuclear@3: cur_color.z = b; nuclear@3: cur_color.w = a; nuclear@3: } nuclear@3: nuclear@3: nuclear@3: void gl_texcoord1f(float s) nuclear@3: { nuclear@3: cur_texcoord.x = s; nuclear@3: cur_texcoord.y = 0.0f; nuclear@3: } nuclear@3: nuclear@3: void gl_texcoord2f(float s, float t) nuclear@3: { nuclear@3: cur_texcoord.x = s; nuclear@3: cur_texcoord.y = t; nuclear@3: } nuclear@3: nuclear@3: void glu_perspective(float fov, float aspect, float nearz, float farz) nuclear@3: { nuclear@3: float fovrad = M_PI * fov / 180.0; nuclear@3: float halfsz = tan(fovrad) * nearz; nuclear@3: nuclear@3: glFrustumf(-halfsz * aspect, halfsz * aspect, -halfsz, halfsz, nearz, farz); nuclear@3: }