14 #define MMODE_IDX(x) ((x) - GL_MODELVIEW)
15 #define MAT_STACK_SIZE 32
16 #define MAT_IDENT {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}
20 static void gl_draw_immediate(void);
22 typedef struct { float x, y; } vec2_t;
23 typedef struct { float x, y, z; } vec3_t;
24 typedef struct { float x, y, z, w; } vec4_t;
26 static int mm_idx = 0;
27 static float mat_stack[3][MAT_STACK_SIZE][16] = {{MAT_IDENT}, {MAT_IDENT}, {MAT_IDENT}};
28 static int stack_top[3];
29 static float mat_mvp[16];
33 static vec3_t cur_normal;
34 static vec4_t cur_color, cur_attrib;
35 static vec2_t cur_texcoord;
37 static vec4_t *vert_arr, *col_arr, *attr_arr;
38 static vec3_t *norm_arr;
39 static vec2_t *texc_arr;
40 /*static unsigned int vbuf, cbuf, nbuf, tbuf, abuf;*/
41 static int vloc, nloc, cloc, tloc, aloc = -1;
43 static int num_verts, vert_calls;
47 void gl_matrix_mode(int mm)
49 mm_idx = MMODE_IDX(mm);
52 void gl_push_matrix(void)
54 int top = stack_top[mm_idx];
56 memcpy(mat_stack[mm_idx][top + 1], mat_stack[mm_idx][top], 16 * sizeof(float));
61 void gl_pop_matrix(void)
67 void gl_load_identity(void)
69 static const float idmat[] = MAT_IDENT;
70 int top = stack_top[mm_idx];
71 float *mat = mat_stack[mm_idx][top];
73 memcpy(mat, idmat, sizeof idmat);
77 void gl_load_matrixf(const float *m)
79 int top = stack_top[mm_idx];
80 float *mat = mat_stack[mm_idx][top];
82 memcpy(mat, m, 16 * sizeof *mat);
86 #define M(i, j) ((i << 2) + j)
88 void gl_mult_matrixf(const float *m2)
91 int top = stack_top[mm_idx];
92 float *m1 = mat_stack[mm_idx][top];
97 res[M(i,j)] = m1[M(i,0)] * m2[M(0,j)] +
98 m1[M(i,1)] * m2[M(1,j)] +
99 m1[M(i,2)] * m2[M(2,j)] +
100 m1[M(i,3)] * m2[M(3,j)];
104 memcpy(m1, res, sizeof res);
108 void gl_translatef(float x, float y, float z)
110 float mat[] = MAT_IDENT;
116 gl_mult_matrixf(mat);
119 void gl_rotatef(float angle, float x, float y, float z)
121 float mat[] = MAT_IDENT;
123 float angle_rad = M_PI * angle / 180.0;
124 float sina = sin(angle_rad);
125 float cosa = cos(angle_rad);
126 float one_minus_cosa = 1.0 - cosa;
131 mat[0] = nxsq + (1.0 - nxsq) * cosa;
132 mat[4] = x * y * one_minus_cosa - z * sina;
133 mat[8] = x * z * one_minus_cosa + y * sina;
134 mat[1] = x * y * one_minus_cosa + z * sina;
135 mat[5] = nysq + (1.0 - nysq) * cosa;
136 mat[9] = y * z * one_minus_cosa - x * sina;
137 mat[2] = x * z * one_minus_cosa - y * sina;
138 mat[6] = y * z * one_minus_cosa + x * sina;
139 mat[10] = nzsq + (1.0 - nzsq) * cosa;
141 gl_mult_matrixf(mat);
144 void gl_scalef(float x, float y, float z)
146 float mat[] = MAT_IDENT;
152 gl_mult_matrixf(mat);
155 void gl_ortho(float left, float right, float bottom, float top, float znear, float zfar)
157 float mat[] = MAT_IDENT;
159 float dx = right - left;
160 float dy = top - bottom;
161 float dz = zfar - znear;
163 float tx = -(right + left) / dx;
164 float ty = -(top + bottom) / dy;
165 float tz = -(zfar + znear) / dz;
169 float sz = -2.0 / dz;
178 gl_mult_matrixf(mat);
181 void gl_frustum(float left, float right, float bottom, float top, float znear, float zfar)
183 float mat[] = MAT_IDENT;
185 float dx = right - left;
186 float dy = top - bottom;
187 float dz = zfar - znear;
189 float a = (right + left) / dx;
190 float b = (top + bottom) / dy;
191 float c = -(zfar + znear) / dz;
192 float d = -2.0 * zfar * znear / dz;
194 mat[0] = 2.0 * znear / dx;
195 mat[5] = 2.0 * znear / dy;
202 gl_mult_matrixf(mat);
205 void glu_perspective(float vfov, float aspect, float znear, float zfar)
207 float vfov_rad = M_PI * vfov / 180.0;
208 float x = znear * tan(vfov_rad / 2.0);
209 gl_frustum(-aspect * x, aspect * x, -x, x, znear, zfar);
212 void gl_apply_xform(unsigned int prog)
214 int loc, mvidx, pidx, tidx, mvtop, ptop, ttop;
216 mvidx = MMODE_IDX(GL_MODELVIEW);
217 pidx = MMODE_IDX(GL_PROJECTION);
218 tidx = MMODE_IDX(GL_TEXTURE);
220 mvtop = stack_top[mvidx];
221 ptop = stack_top[pidx];
222 ttop = stack_top[tidx];
226 if((loc = glGetUniformLocation(prog, "matrix_modelview")) != -1) {
227 glUniformMatrix4fv(loc, 1, 0, mat_stack[mvidx][mvtop]);
230 if((loc = glGetUniformLocation(prog, "matrix_projection")) != -1) {
231 glUniformMatrix4fv(loc, 1, 0, mat_stack[pidx][ptop]);
234 if((loc = glGetUniformLocation(prog, "matrix_texture")) != -1) {
235 glUniformMatrix4fv(loc, 1, 0, mat_stack[tidx][ttop]);
238 if((loc = glGetUniformLocation(prog, "matrix_normal")) != -1) {
241 nmat[0] = mat_stack[mvidx][mvtop][0];
242 nmat[1] = mat_stack[mvidx][mvtop][1];
243 nmat[2] = mat_stack[mvidx][mvtop][2];
244 nmat[3] = mat_stack[mvidx][mvtop][4];
245 nmat[4] = mat_stack[mvidx][mvtop][5];
246 nmat[5] = mat_stack[mvidx][mvtop][6];
247 nmat[6] = mat_stack[mvidx][mvtop][8];
248 nmat[7] = mat_stack[mvidx][mvtop][9];
249 nmat[8] = mat_stack[mvidx][mvtop][10];
250 glUniformMatrix3fv(loc, 1, 0, nmat);
253 if((loc = glGetUniformLocation(prog, "matrix_modelview_projection")) != -1) {
257 glUniformMatrix4fv(loc, 1, 0, mat_mvp);
262 /* immediate mode rendering */
266 vert_arr = malloc(MAX_VERTS * sizeof *vert_arr);
267 norm_arr = malloc(MAX_VERTS * sizeof *norm_arr);
268 texc_arr = malloc(MAX_VERTS * sizeof *texc_arr);
269 col_arr = malloc(MAX_VERTS * sizeof *col_arr);
270 attr_arr = malloc(MAX_VERTS * sizeof *attr_arr);
271 assert(vert_arr && norm_arr && texc_arr && col_arr && attr_arr);
275 num_verts = vert_calls = 0;
277 glGetIntegerv(GL_CURRENT_PROGRAM, &cur_prog);
280 gl_apply_xform(cur_prog);
282 vloc = glGetAttribLocation(cur_prog, "attr_vertex");
283 nloc = glGetAttribLocation(cur_prog, "attr_normal");
284 cloc = glGetAttribLocation(cur_prog, "attr_color");
285 tloc = glGetAttribLocation(cur_prog, "attr_texcoord");
296 static void gl_draw_immediate(void)
301 fprintf(stderr, "gl_draw_immediate call with vloc == -1\n");
305 glprim = prim == GL_QUADS ? GL_TRIANGLES : prim;
307 glVertexAttribPointer(vloc, 4, GL_FLOAT, 0, 0, vert_arr);
308 glEnableVertexAttribArray(vloc);
311 glVertexAttribPointer(nloc, 3, GL_FLOAT, 0, 0, norm_arr);
312 glEnableVertexAttribArray(nloc);
316 glVertexAttribPointer(cloc, 4, GL_FLOAT, 1, 0, col_arr);
317 glEnableVertexAttribArray(cloc);
321 glVertexAttribPointer(tloc, 2, GL_FLOAT, 0, 0, texc_arr);
322 glEnableVertexAttribArray(tloc);
326 glVertexAttribPointer(aloc, 4, GL_FLOAT, 0, 0, attr_arr);
327 glEnableVertexAttribArray(aloc);
330 glDrawArrays(glprim, 0, num_verts);
332 glDisableVertexAttribArray(vloc);
334 glDisableVertexAttribArray(nloc);
337 glDisableVertexAttribArray(cloc);
340 glDisableVertexAttribArray(tloc);
343 glDisableVertexAttribArray(aloc);
348 void gl_vertex2f(float x, float y)
350 gl_vertex4f(x, y, 0.0f, 1.0f);
353 void gl_vertex3f(float x, float y, float z)
355 gl_vertex4f(x, y, z, 1.0f);
358 void gl_vertex4f(float x, float y, float z, float w)
362 if(prim == GL_QUADS && vert_calls % 4 == 3) {
365 attr_arr[num_verts] = attr_arr[num_verts - 3 + i];
368 col_arr[num_verts] = col_arr[num_verts - 3 + i];
371 texc_arr[num_verts] = texc_arr[num_verts - 3 + i];
374 norm_arr[num_verts] = norm_arr[num_verts - 3 + i];
376 vert_arr[num_verts] = vert_arr[num_verts - 3 + i];
381 vert_arr[num_verts].x = x;
382 vert_arr[num_verts].y = y;
383 vert_arr[num_verts].z = z;
384 vert_arr[num_verts].w = w;
387 col_arr[num_verts] = cur_color;
390 norm_arr[num_verts] = cur_normal;
393 texc_arr[num_verts] = cur_texcoord;
396 attr_arr[num_verts] = cur_attrib;
402 if(prim == GL_QUADS) {
403 /* leave space for 6 more worst-case and don't allow flushes mid-quad */
404 buffer_full = num_verts >= MAX_VERTS - 6 && vert_calls % 4 == 0;
406 buffer_full = num_verts >= MAX_VERTS - prim;
411 gl_begin(prim); /* reset everything */
416 void gl_normal3f(float x, float y, float z)
424 void gl_color3f(float r, float g, float b)
432 void gl_color4f(float r, float g, float b, float a)
441 void gl_texcoord1f(float s)
444 cur_texcoord.y = 0.0f;
447 void gl_texcoord2f(float s, float t)
453 void gl_vertex_attrib2f(int loc, float x, float y)
462 void gl_vertex_attrib3f(int loc, float x, float y, float z)
471 void gl_vertex_attrib4f(int loc, float x, float y, float z, float w)