3dphotoshoot

diff src/sanegl.c @ 11:ad49e1f9b627

foo
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 31 May 2015 06:02:08 +0300
parents
children a460b1e5af4a
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/sanegl.c	Sun May 31 06:02:08 2015 +0300
     1.3 @@ -0,0 +1,802 @@
     1.4 +/*
     1.5 +SaneGL - a small library to bring back sanity to OpenGL ES 2.x
     1.6 +Copyright (C) 2011-2013  John Tsiombikas <nuclear@member.fsf.org>
     1.7 +
     1.8 +This program is free software: you can redistribute it and/or modify
     1.9 +it under the terms of the GNU General Public License as published by
    1.10 +the Free Software Foundation, either version 3 of the License, or
    1.11 +(at your option) any later version.
    1.12 +
    1.13 +This program is distributed in the hope that it will be useful,
    1.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.16 +GNU General Public License for more details.
    1.17 +
    1.18 +You should have received a copy of the GNU General Public License
    1.19 +along with this program.  If not, see <http://www.gnu.org/licenses/>.
    1.20 +*/
    1.21 +
    1.22 +#include <stdio.h>
    1.23 +#include <stdlib.h>
    1.24 +#include <string.h>
    1.25 +#include <math.h>
    1.26 +#include <assert.h>
    1.27 +#include "sanegl.h"
    1.28 +
    1.29 +#define MMODE_IDX(x)	((x) - GL_MODELVIEW)
    1.30 +#define MAT_STACK_SIZE	32
    1.31 +#define MAT_IDENT	{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}
    1.32 +
    1.33 +#define MAX_VERTS	512
    1.34 +
    1.35 +static void gl_draw_immediate(void);
    1.36 +static void m4_transpose(double *res, double *m);
    1.37 +static double m4_determinant(double *m);
    1.38 +static void m4_adjoint(double *res, double *m);
    1.39 +static void m4_inverse(double *res, double *m);
    1.40 +
    1.41 +
    1.42 +typedef struct { float x, y; } vec2_t;
    1.43 +typedef struct { float x, y, z; } vec3_t;
    1.44 +typedef struct { float x, y, z, w; } vec4_t;
    1.45 +
    1.46 +static int mm_idx = 0;
    1.47 +static float mat_stack[3][MAT_STACK_SIZE][16] = {{MAT_IDENT}, {MAT_IDENT}, {MAT_IDENT}};
    1.48 +static int stack_top[3];
    1.49 +static float mat_mvp[16];
    1.50 +static int mvp_valid;
    1.51 +static int prim = -1;
    1.52 +
    1.53 +static vec3_t cur_normal;
    1.54 +static vec4_t cur_color, cur_attrib;
    1.55 +static vec2_t cur_texcoord;
    1.56 +
    1.57 +static vec4_t *vert_arr, *col_arr, *attr_arr;
    1.58 +static vec3_t *norm_arr;
    1.59 +static vec2_t *texc_arr;
    1.60 +/*static unsigned int vbuf, cbuf, nbuf, tbuf, abuf;*/
    1.61 +static int vloc, nloc, cloc, tloc, aloc = -1;
    1.62 +
    1.63 +static int num_verts, vert_calls;
    1.64 +static int cur_prog;
    1.65 +
    1.66 +#ifdef GLDEF
    1.67 +#undef glEnable
    1.68 +#undef glDisable
    1.69 +#endif
    1.70 +
    1.71 +void gl_enable(int state)
    1.72 +{
    1.73 +	switch(state) {
    1.74 +	case GL_TEXTURE_2D:
    1.75 +		break;
    1.76 +
    1.77 +	default:
    1.78 +		glEnable(state);
    1.79 +	}
    1.80 +}
    1.81 +
    1.82 +void gl_disable(int state)
    1.83 +{
    1.84 +	switch(state) {
    1.85 +	case GL_TEXTURE_2D:
    1.86 +		glBindTexture(state, 0);
    1.87 +		break;
    1.88 +
    1.89 +	default:
    1.90 +		glDisable(state);
    1.91 +	}
    1.92 +}
    1.93 +
    1.94 +void gl_matrix_mode(int mm)
    1.95 +{
    1.96 +	mm_idx = MMODE_IDX(mm);
    1.97 +}
    1.98 +
    1.99 +void gl_push_matrix(void)
   1.100 +{
   1.101 +	int top = stack_top[mm_idx];
   1.102 +
   1.103 +	memcpy(mat_stack[mm_idx][top + 1], mat_stack[mm_idx][top], 16 * sizeof(float));
   1.104 +	stack_top[mm_idx]++;
   1.105 +	mvp_valid = 0;
   1.106 +}
   1.107 +
   1.108 +void gl_pop_matrix(void)
   1.109 +{
   1.110 +	stack_top[mm_idx]--;
   1.111 +	mvp_valid = 0;
   1.112 +}
   1.113 +
   1.114 +void gl_load_identity(void)
   1.115 +{
   1.116 +	static const float idmat[] = MAT_IDENT;
   1.117 +	int top = stack_top[mm_idx];
   1.118 +	float *mat = mat_stack[mm_idx][top];
   1.119 +
   1.120 +	memcpy(mat, idmat, sizeof idmat);
   1.121 +	mvp_valid = 0;
   1.122 +}
   1.123 +
   1.124 +void gl_load_matrixf(const float *m)
   1.125 +{
   1.126 +	int top = stack_top[mm_idx];
   1.127 +	float *mat = mat_stack[mm_idx][top];
   1.128 +
   1.129 +	memcpy(mat, m, 16 * sizeof *mat);
   1.130 +	mvp_valid = 0;
   1.131 +}
   1.132 +
   1.133 +void gl_load_matrixd(const double *m)
   1.134 +{
   1.135 +	int i;
   1.136 +	float mf[16];
   1.137 +
   1.138 +	for(i=0; i<16; i++) {
   1.139 +		mf[i] = (float)m[i];
   1.140 +	}
   1.141 +	gl_load_matrixf(mf);
   1.142 +}
   1.143 +
   1.144 +#define M(i, j)	((i << 2) + j)
   1.145 +
   1.146 +void gl_mult_matrixf(const float *m2)
   1.147 +{
   1.148 +	int i, j;
   1.149 +	int top = stack_top[mm_idx];
   1.150 +	float *m1 = mat_stack[mm_idx][top];
   1.151 +	float res[16];
   1.152 +
   1.153 +	for(i=0; i<4; i++) {
   1.154 +		for(j=0; j<4; j++) {
   1.155 +			res[M(i,j)] = m2[M(i,0)] * m1[M(0,j)] +
   1.156 +						m2[M(i,1)] * m1[M(1,j)] +
   1.157 +						m2[M(i,2)] * m1[M(2,j)] +
   1.158 +						m2[M(i,3)] * m1[M(3,j)];
   1.159 +		}
   1.160 +	}
   1.161 +
   1.162 +	memcpy(m1, res, sizeof res);
   1.163 +	mvp_valid = 0;
   1.164 +}
   1.165 +
   1.166 +void gl_mult_matrixd(const double *m)
   1.167 +{
   1.168 +	int i;
   1.169 +	float mf[16];
   1.170 +
   1.171 +	for(i=0; i<16; i++) {
   1.172 +		mf[i] = (float)m[i];
   1.173 +	}
   1.174 +	gl_mult_matrixf(mf);
   1.175 +}
   1.176 +
   1.177 +void gl_translatef(float x, float y, float z)
   1.178 +{
   1.179 +	float mat[] = MAT_IDENT;
   1.180 +
   1.181 +	mat[12] = x;
   1.182 +	mat[13] = y;
   1.183 +	mat[14] = z;
   1.184 +
   1.185 +	gl_mult_matrixf(mat);
   1.186 +}
   1.187 +
   1.188 +void gl_rotatef(float angle, float x, float y, float z)
   1.189 +{
   1.190 +	float mat[] = MAT_IDENT;
   1.191 +
   1.192 +	float angle_rad = M_PI * angle / 180.0;
   1.193 +	float sina = sin(angle_rad);
   1.194 +	float cosa = cos(angle_rad);
   1.195 +	float one_minus_cosa = 1.0 - cosa;
   1.196 +	float nxsq = x * x;
   1.197 +	float nysq = y * y;
   1.198 +	float nzsq = z * z;
   1.199 +
   1.200 +	mat[0] = nxsq + (1.0 - nxsq) * cosa;
   1.201 +	mat[4] = x * y * one_minus_cosa - z * sina;
   1.202 +	mat[8] = x * z * one_minus_cosa + y * sina;
   1.203 +	mat[1] = x * y * one_minus_cosa + z * sina;
   1.204 +	mat[5] = nysq + (1.0 - nysq) * cosa;
   1.205 +	mat[9] = y * z * one_minus_cosa - x * sina;
   1.206 +	mat[2] = x * z * one_minus_cosa - y * sina;
   1.207 +	mat[6] = y * z * one_minus_cosa + x * sina;
   1.208 +	mat[10] = nzsq + (1.0 - nzsq) * cosa;
   1.209 +
   1.210 +	gl_mult_matrixf(mat);
   1.211 +}
   1.212 +
   1.213 +void gl_scalef(float x, float y, float z)
   1.214 +{
   1.215 +	float mat[] = MAT_IDENT;
   1.216 +
   1.217 +	mat[0] = x;
   1.218 +	mat[5] = y;
   1.219 +	mat[10] = z;
   1.220 +
   1.221 +	gl_mult_matrixf(mat);
   1.222 +}
   1.223 +
   1.224 +void gl_ortho(float left, float right, float bottom, float top, float near, float far)
   1.225 +{
   1.226 +	float mat[] = MAT_IDENT;
   1.227 +
   1.228 +	float dx = right - left;
   1.229 +	float dy = top - bottom;
   1.230 +	float dz = far - near;
   1.231 +
   1.232 +	float tx = -(right + left) / dx;
   1.233 +	float ty = -(top + bottom) / dy;
   1.234 +	float tz = -(far + near) / dz;
   1.235 +
   1.236 +	float sx = 2.0 / dx;
   1.237 +	float sy = 2.0 / dy;
   1.238 +	float sz = -2.0 / dz;
   1.239 +
   1.240 +	mat[0] = sx;
   1.241 +	mat[5] = sy;
   1.242 +	mat[10] = sz;
   1.243 +	mat[12] = tx;
   1.244 +	mat[13] = ty;
   1.245 +	mat[14] = tz;
   1.246 +
   1.247 +	gl_mult_matrixf(mat);
   1.248 +}
   1.249 +
   1.250 +void gl_frustum(float left, float right, float bottom, float top, float near, float far)
   1.251 +{
   1.252 +	float mat[] = MAT_IDENT;
   1.253 +
   1.254 +	float dx = right - left;
   1.255 +	float dy = top - bottom;
   1.256 +	float dz = far - near;
   1.257 +
   1.258 +	float a = (right + left) / dx;
   1.259 +	float b = (top + bottom) / dy;
   1.260 +	float c = -(far + near) / dz;
   1.261 +	float d = -2.0 * far * near / dz;
   1.262 +
   1.263 +	mat[0] = 2.0 * near / dx;
   1.264 +	mat[5] = 2.0 * near / dy;
   1.265 +	mat[8] = a;
   1.266 +	mat[9] = b;
   1.267 +	mat[10] = c;
   1.268 +	mat[11] = -1.0;
   1.269 +	mat[14] = d;
   1.270 +	mat[15] = 0.0;
   1.271 +
   1.272 +	gl_mult_matrixf(mat);
   1.273 +}
   1.274 +
   1.275 +void glu_perspective(float vfov, float aspect, float near, float far)
   1.276 +{
   1.277 +	float vfov_rad = M_PI * vfov / 180.0;
   1.278 +	float x = near * tan(vfov_rad / 2.0);
   1.279 +	gl_frustum(-aspect * x, aspect * x, -x, x, near, far);
   1.280 +}
   1.281 +
   1.282 +int glu_un_project(double winx, double winy, double winz,
   1.283 +		const double *model, const double *proj, const int *viewp,
   1.284 +		double *objx, double *objy, double *objz)
   1.285 +{
   1.286 +	double mvp[16], inv_mvp[16];
   1.287 +
   1.288 +	double ndcx = 2.0 * (winx - viewp[0]) / viewp[2] - 1.0;
   1.289 +	double ndcy = 2.0 * (winy - viewp[1]) / viewp[3] - 1.0;
   1.290 +	double ndcz = 2.0 * winz - 1.0;
   1.291 +
   1.292 +	// calculate modelviewprojection
   1.293 +	gl_matrix_mode(GL_MODELVIEW);
   1.294 +	gl_push_matrix();
   1.295 +	gl_load_matrixd(proj);
   1.296 +	gl_mult_matrixd(model);
   1.297 +	gl_get_doublev(GL_MODELVIEW_MATRIX, mvp);
   1.298 +	gl_pop_matrix();
   1.299 +
   1.300 +	// invert modelviewprojection
   1.301 +	m4_inverse(inv_mvp, mvp);
   1.302 +
   1.303 +	// transform ndc by modelview -> obj
   1.304 +	/**objx = inv_mvp[0] * ndcx + inv_mvp[4] * ndcy + inv_mvp[8] * ndcz + inv_mvp[12];
   1.305 +	*objy = inv_mvp[1] * ndcx + inv_mvp[5] * ndcy + inv_mvp[9] * ndcz + inv_mvp[13];
   1.306 +	*objz = inv_mvp[2] * ndcx + inv_mvp[6] * ndcy + inv_mvp[10] * ndcz + inv_mvp[14];*/
   1.307 +	*objx = inv_mvp[0] * ndcx + inv_mvp[1] * ndcy + inv_mvp[2] * ndcz + inv_mvp[3];
   1.308 +	*objy = inv_mvp[4] * ndcx + inv_mvp[5] * ndcy + inv_mvp[6] * ndcz + inv_mvp[7];
   1.309 +	*objz = inv_mvp[8] * ndcx + inv_mvp[9] * ndcy + inv_mvp[10] * ndcz + inv_mvp[11];
   1.310 +	return 0;
   1.311 +}
   1.312 +
   1.313 +void gl_apply_xform(unsigned int prog)
   1.314 +{
   1.315 +	int loc, mvidx, pidx, tidx, mvtop, ptop, ttop;
   1.316 +
   1.317 +	mvidx = MMODE_IDX(GL_MODELVIEW);
   1.318 +	pidx = MMODE_IDX(GL_PROJECTION);
   1.319 +	tidx = MMODE_IDX(GL_TEXTURE);
   1.320 +
   1.321 +	mvtop = stack_top[mvidx];
   1.322 +	ptop = stack_top[pidx];
   1.323 +	ttop = stack_top[tidx];
   1.324 +
   1.325 +	assert(prog);
   1.326 +
   1.327 +	/*printf("APPLY XFORM\n");*/
   1.328 +
   1.329 +	CHECK_GLERROR;
   1.330 +	if((loc = glGetUniformLocation(prog, "matrix_modelview")) != -1) {
   1.331 +		CHECK_GLERROR;
   1.332 +		/*printf("  MODELVIEW:\n");
   1.333 +		for(i=0; i<16; i+=4) {
   1.334 +			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]);
   1.335 +		}*/
   1.336 +		glUniformMatrix4fv(loc, 1, 0, mat_stack[mvidx][mvtop]);
   1.337 +		CHECK_GLERROR;
   1.338 +	}
   1.339 +	CHECK_GLERROR;
   1.340 +
   1.341 +	if((loc = glGetUniformLocation(prog, "matrix_projection")) != -1) {
   1.342 +		CHECK_GLERROR;
   1.343 +		/*printf("  PROJECTION:\n");
   1.344 +		for(i=0; i<16; i+=4) {
   1.345 +			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]);
   1.346 +		}*/
   1.347 +		glUniformMatrix4fv(loc, 1, 0, mat_stack[pidx][ptop]);
   1.348 +		CHECK_GLERROR;
   1.349 +	}
   1.350 +	CHECK_GLERROR;
   1.351 +
   1.352 +	if((loc = glGetUniformLocation(prog, "matrix_texture")) != -1) {
   1.353 +		CHECK_GLERROR;
   1.354 +		glUniformMatrix4fv(loc, 1, 0, mat_stack[tidx][ttop]);
   1.355 +		CHECK_GLERROR;
   1.356 +	}
   1.357 +	CHECK_GLERROR;
   1.358 +
   1.359 +	if((loc = glGetUniformLocation(prog, "matrix_normal")) != -1) {
   1.360 +		float nmat[9];
   1.361 +
   1.362 +		CHECK_GLERROR;
   1.363 +
   1.364 +		nmat[0] = mat_stack[mvidx][mvtop][0];
   1.365 +		nmat[1] = mat_stack[mvidx][mvtop][1];
   1.366 +		nmat[2] = mat_stack[mvidx][mvtop][2];
   1.367 +		nmat[3] = mat_stack[mvidx][mvtop][4];
   1.368 +		nmat[4] = mat_stack[mvidx][mvtop][5];
   1.369 +		nmat[5] = mat_stack[mvidx][mvtop][6];
   1.370 +		nmat[6] = mat_stack[mvidx][mvtop][8];
   1.371 +		nmat[7] = mat_stack[mvidx][mvtop][9];
   1.372 +		nmat[8] = mat_stack[mvidx][mvtop][10];
   1.373 +		glUniformMatrix3fv(loc, 1, 0, nmat);
   1.374 +		CHECK_GLERROR;
   1.375 +	}
   1.376 +	CHECK_GLERROR;
   1.377 +
   1.378 +	if((loc = glGetUniformLocation(prog, "matrix_modelview_projection")) != -1) {
   1.379 +		CHECK_GLERROR;
   1.380 +		if(!mvp_valid) {
   1.381 +			/* TODO calc mvp */
   1.382 +		}
   1.383 +		glUniformMatrix4fv(loc, 1, 0, mat_mvp);
   1.384 +		CHECK_GLERROR;
   1.385 +	}
   1.386 +	CHECK_GLERROR;
   1.387 +}
   1.388 +
   1.389 +
   1.390 +/* immediate mode rendering */
   1.391 +void gl_begin(int p)
   1.392 +{
   1.393 +	if(!vert_arr) {
   1.394 +		vert_arr = malloc(MAX_VERTS * sizeof *vert_arr);
   1.395 +		norm_arr = malloc(MAX_VERTS * sizeof *norm_arr);
   1.396 +		texc_arr = malloc(MAX_VERTS * sizeof *texc_arr);
   1.397 +		col_arr = malloc(MAX_VERTS * sizeof *col_arr);
   1.398 +		attr_arr = malloc(MAX_VERTS * sizeof *attr_arr);
   1.399 +		assert(vert_arr && norm_arr && texc_arr && col_arr && attr_arr);
   1.400 +	}
   1.401 +
   1.402 +	prim = p;
   1.403 +	num_verts = vert_calls = 0;
   1.404 +
   1.405 +	glGetIntegerv(GL_CURRENT_PROGRAM, &cur_prog);
   1.406 +	CHECK_GLERROR;
   1.407 +	assert(cur_prog);
   1.408 +
   1.409 +	gl_apply_xform(cur_prog);
   1.410 +	CHECK_GLERROR;
   1.411 +
   1.412 +	vloc = glGetAttribLocation(cur_prog, "attr_vertex");
   1.413 +	CHECK_GLERROR;
   1.414 +	nloc = glGetAttribLocation(cur_prog, "attr_normal");
   1.415 +	CHECK_GLERROR;
   1.416 +	cloc = glGetAttribLocation(cur_prog, "attr_color");
   1.417 +	CHECK_GLERROR;
   1.418 +	tloc = glGetAttribLocation(cur_prog, "attr_texcoord");
   1.419 +	CHECK_GLERROR;
   1.420 +}
   1.421 +
   1.422 +void gl_end(void)
   1.423 +{
   1.424 +	if(num_verts > 0) {
   1.425 +		gl_draw_immediate();
   1.426 +	}
   1.427 +	aloc = -1;
   1.428 +}
   1.429 +
   1.430 +static void gl_draw_immediate(void)
   1.431 +{
   1.432 +	int glprim;
   1.433 +
   1.434 +	if(vloc == -1) {
   1.435 +		fprintf(stderr, "gl_draw_immediate call with vloc == -1\n");
   1.436 +		return;
   1.437 +	}
   1.438 +
   1.439 +	glprim = prim == GL_QUADS ? GL_TRIANGLES : prim;
   1.440 +
   1.441 +	CHECK_GLERROR;
   1.442 +	glVertexAttribPointer(vloc, 4, GL_FLOAT, 0, 0, vert_arr);
   1.443 +	CHECK_GLERROR;
   1.444 +	glEnableVertexAttribArray(vloc);
   1.445 +	CHECK_GLERROR;
   1.446 +
   1.447 +	if(nloc != -1) {
   1.448 +		glVertexAttribPointer(nloc, 3, GL_FLOAT, 0, 0, norm_arr);
   1.449 +		CHECK_GLERROR;
   1.450 +		glEnableVertexAttribArray(nloc);
   1.451 +		CHECK_GLERROR;
   1.452 +	}
   1.453 +
   1.454 +	if(cloc != -1) {
   1.455 +		glVertexAttribPointer(cloc, 4, GL_FLOAT, 1, 0, col_arr);
   1.456 +		CHECK_GLERROR;
   1.457 +		glEnableVertexAttribArray(cloc);
   1.458 +		CHECK_GLERROR;
   1.459 +	}
   1.460 +
   1.461 +	if(tloc != -1) {
   1.462 +		glVertexAttribPointer(tloc, 2, GL_FLOAT, 0, 0, texc_arr);
   1.463 +		CHECK_GLERROR;
   1.464 +		glEnableVertexAttribArray(tloc);
   1.465 +		CHECK_GLERROR;
   1.466 +	}
   1.467 +
   1.468 +	if(aloc != -1) {
   1.469 +		glVertexAttribPointer(aloc, 4, GL_FLOAT, 0, 0, attr_arr);
   1.470 +		CHECK_GLERROR;
   1.471 +		glEnableVertexAttribArray(aloc);
   1.472 +		CHECK_GLERROR;
   1.473 +	}
   1.474 +
   1.475 +	glDrawArrays(glprim, 0, num_verts);
   1.476 +	CHECK_GLERROR;
   1.477 +
   1.478 +	glDisableVertexAttribArray(vloc);
   1.479 +	CHECK_GLERROR;
   1.480 +	if(nloc != -1) {
   1.481 +		glDisableVertexAttribArray(nloc);
   1.482 +		CHECK_GLERROR;
   1.483 +	}
   1.484 +	if(cloc != -1) {
   1.485 +		glDisableVertexAttribArray(cloc);
   1.486 +		CHECK_GLERROR;
   1.487 +	}
   1.488 +	if(tloc != -1) {
   1.489 +		glDisableVertexAttribArray(tloc);
   1.490 +		CHECK_GLERROR;
   1.491 +	}
   1.492 +	if(aloc != -1) {
   1.493 +		glDisableVertexAttribArray(aloc);
   1.494 +		CHECK_GLERROR;
   1.495 +	}
   1.496 +}
   1.497 +
   1.498 +
   1.499 +void gl_vertex2f(float x, float y)
   1.500 +{
   1.501 +	gl_vertex4f(x, y, 0.0f, 1.0f);
   1.502 +}
   1.503 +
   1.504 +void gl_vertex3f(float x, float y, float z)
   1.505 +{
   1.506 +	gl_vertex4f(x, y, z, 1.0f);
   1.507 +}
   1.508 +
   1.509 +void gl_vertex4f(float x, float y, float z, float w)
   1.510 +{
   1.511 +	int i, buffer_full;
   1.512 +
   1.513 +	if(prim == GL_QUADS && vert_calls % 4 == 3) {
   1.514 +		for(i=0; i<2; i++) {
   1.515 +			if(aloc != -1) {
   1.516 +				attr_arr[num_verts] = attr_arr[num_verts - 3 + i];
   1.517 +			}
   1.518 +			if(cloc != -1) {
   1.519 +				col_arr[num_verts] = col_arr[num_verts - 3 + i];
   1.520 +			}
   1.521 +			if(tloc != -1) {
   1.522 +				texc_arr[num_verts] = texc_arr[num_verts - 3 + i];
   1.523 +			}
   1.524 +			if(nloc != -1) {
   1.525 +				norm_arr[num_verts] = norm_arr[num_verts - 3 + i];
   1.526 +			}
   1.527 +			vert_arr[num_verts] = vert_arr[num_verts - 3 + i];
   1.528 +			num_verts++;
   1.529 +		}
   1.530 +	}
   1.531 +
   1.532 +	vert_arr[num_verts].x = x;
   1.533 +	vert_arr[num_verts].y = y;
   1.534 +	vert_arr[num_verts].z = z;
   1.535 +	vert_arr[num_verts].w = w;
   1.536 +
   1.537 +	if(cloc != -1) {
   1.538 +		col_arr[num_verts] = cur_color;
   1.539 +	}
   1.540 +	if(nloc != -1) {
   1.541 +		norm_arr[num_verts] = cur_normal;
   1.542 +	}
   1.543 +	if(tloc != -1) {
   1.544 +		texc_arr[num_verts] = cur_texcoord;
   1.545 +	}
   1.546 +	if(aloc != -1) {
   1.547 +		attr_arr[num_verts] = cur_attrib;
   1.548 +	}
   1.549 +
   1.550 +	vert_calls++;
   1.551 +	num_verts++;
   1.552 +
   1.553 +	if(prim == GL_QUADS) {
   1.554 +		/* leave space for 6 more worst-case and don't allow flushes mid-quad */
   1.555 +		buffer_full = num_verts >= MAX_VERTS - 6 && vert_calls % 4 == 0;
   1.556 +	} else {
   1.557 +		buffer_full = num_verts >= MAX_VERTS - prim;
   1.558 +	}
   1.559 +
   1.560 +	if(buffer_full) {
   1.561 +		gl_draw_immediate();
   1.562 +		gl_begin(prim);	/* reset everything */
   1.563 +	}
   1.564 +}
   1.565 +
   1.566 +
   1.567 +void gl_normal3f(float x, float y, float z)
   1.568 +{
   1.569 +	cur_normal.x = x;
   1.570 +	cur_normal.y = y;
   1.571 +	cur_normal.z = z;
   1.572 +}
   1.573 +
   1.574 +
   1.575 +void gl_color3f(float r, float g, float b)
   1.576 +{
   1.577 +	cur_color.x = r;
   1.578 +	cur_color.y = g;
   1.579 +	cur_color.z = b;
   1.580 +	cur_color.w = 1.0f;
   1.581 +}
   1.582 +
   1.583 +void gl_color4f(float r, float g, float b, float a)
   1.584 +{
   1.585 +	cur_color.x = r;
   1.586 +	cur_color.y = g;
   1.587 +	cur_color.z = b;
   1.588 +	cur_color.w = a;
   1.589 +}
   1.590 +
   1.591 +
   1.592 +void gl_texcoord1f(float s)
   1.593 +{
   1.594 +	cur_texcoord.x = s;
   1.595 +	cur_texcoord.y = 0.0f;
   1.596 +}
   1.597 +
   1.598 +void gl_texcoord2f(float s, float t)
   1.599 +{
   1.600 +	cur_texcoord.x = s;
   1.601 +	cur_texcoord.y = t;
   1.602 +}
   1.603 +
   1.604 +void gl_vertex_attrib2f(int loc, float x, float y)
   1.605 +{
   1.606 +	aloc = loc;
   1.607 +	cur_attrib.x = x;
   1.608 +	cur_attrib.y = y;
   1.609 +	cur_attrib.z = 0.0f;
   1.610 +	cur_attrib.w = 1.0f;
   1.611 +}
   1.612 +
   1.613 +void gl_vertex_attrib3f(int loc, float x, float y, float z)
   1.614 +{
   1.615 +	aloc = loc;
   1.616 +	cur_attrib.x = x;
   1.617 +	cur_attrib.y = y;
   1.618 +	cur_attrib.z = z;
   1.619 +	cur_attrib.w = 1.0f;
   1.620 +}
   1.621 +
   1.622 +void gl_vertex_attrib4f(int loc, float x, float y, float z, float w)
   1.623 +{
   1.624 +	aloc = loc;
   1.625 +	cur_attrib.x = x;
   1.626 +	cur_attrib.y = y;
   1.627 +	cur_attrib.z = z;
   1.628 +	cur_attrib.w = w;
   1.629 +}
   1.630 +
   1.631 +#ifdef GLDEF
   1.632 +#undef glGetFloatv
   1.633 +#endif
   1.634 +
   1.635 +void gl_get_floatv(int what, float *res)
   1.636 +{
   1.637 +	int idx;
   1.638 +
   1.639 +	switch(what) {
   1.640 +	case GL_MODELVIEW_MATRIX:
   1.641 +		idx = MMODE_IDX(GL_MODELVIEW);
   1.642 +		memcpy(res, mat_stack[idx][stack_top[idx]], 16 * sizeof *res);
   1.643 +		break;
   1.644 +
   1.645 +	case GL_PROJECTION_MATRIX:
   1.646 +		idx = MMODE_IDX(GL_PROJECTION);
   1.647 +		memcpy(res, mat_stack[idx][stack_top[idx]], 16 * sizeof *res);
   1.648 +		break;
   1.649 +
   1.650 +	default:
   1.651 +		glGetFloatv(what, res);
   1.652 +	}
   1.653 +}
   1.654 +
   1.655 +void gl_get_doublev(int what, double *res)
   1.656 +{
   1.657 +	int i, idx;
   1.658 +	float tmp[16];
   1.659 +
   1.660 +	switch(what) {
   1.661 +	case GL_MODELVIEW_MATRIX:
   1.662 +		if(1) {
   1.663 +			idx = MMODE_IDX(GL_MODELVIEW);
   1.664 +		} else {
   1.665 +	case GL_PROJECTION_MATRIX:
   1.666 +			idx = MMODE_IDX(GL_PROJECTION);
   1.667 +		}
   1.668 +		for(i=0; i<16; i++) {
   1.669 +			res[i] = mat_stack[idx][stack_top[idx]][i];
   1.670 +		}
   1.671 +		break;
   1.672 +
   1.673 +	default:
   1.674 +		glGetFloatv(what, tmp);
   1.675 +		for(i=0; i<16; i++) {
   1.676 +			res[i] = tmp[i];
   1.677 +		}
   1.678 +	}
   1.679 +}
   1.680 +
   1.681 +
   1.682 +/* ---- matrix inversion stuff ---- */
   1.683 +static void m4_transpose(double *res, double *m)
   1.684 +{
   1.685 +	int i, j;
   1.686 +	double tmp[16];
   1.687 +
   1.688 +	if(res == m) {
   1.689 +		memcpy(tmp, m, 16 * sizeof *m);
   1.690 +		m = tmp;
   1.691 +	}
   1.692 +
   1.693 +	for(i=0; i<4; i++) {
   1.694 +		for(j=0; j<4; j++) {
   1.695 +			res[M(i, j)] = m[M(j, i)];
   1.696 +		}
   1.697 +	}
   1.698 +}
   1.699 +
   1.700 +static double m4_determinant(double *m)
   1.701 +{
   1.702 +	double det11, det12, det13, det14;
   1.703 +
   1.704 +	det11 = (m[M(1, 1)] * (m[M(2, 2)] * m[M(3, 3)] - m[M(3, 2)] * m[M(2, 3)])) -
   1.705 +			(m[M(1, 2)] * (m[M(2, 1)] * m[M(3, 3)] - m[M(3, 1)] * m[M(2, 3)])) +
   1.706 +			(m[M(1, 3)] * (m[M(2, 1)] * m[M(3, 2)] - m[M(3, 1)] * m[M(2, 2)]));
   1.707 +
   1.708 +	det12 =	(m[M(1, 0)] * (m[M(2, 2)] * m[M(3, 3)] - m[M(3, 2)] * m[M(2, 3)])) -
   1.709 +			(m[M(1, 2)] * (m[M(2, 0)] * m[M(3, 3)] - m[M(3, 0)] * m[M(2, 3)])) +
   1.710 +			(m[M(1, 3)] * (m[M(2, 0)] * m[M(3, 2)] - m[M(3, 0)] * m[M(2, 2)]));
   1.711 +
   1.712 +	det13 =	(m[M(1, 0)] * (m[M(2, 1)] * m[M(3, 3)] - m[M(3, 1)] * m[M(2, 3)])) -
   1.713 +			(m[M(1, 1)] * (m[M(2, 0)] * m[M(3, 3)] - m[M(3, 0)] * m[M(2, 3)])) +
   1.714 +			(m[M(1, 3)] * (m[M(2, 0)] * m[M(3, 1)] - m[M(3, 0)] * m[M(2, 1)]));
   1.715 +
   1.716 +	det14 =	(m[M(1, 0)] * (m[M(2, 1)] * m[M(3, 2)] - m[M(3, 1)] * m[M(2, 2)])) -
   1.717 +			(m[M(1, 1)] * (m[M(2, 0)] * m[M(3, 2)] - m[M(3, 0)] * m[M(2, 2)])) +
   1.718 +			(m[M(1, 2)] * (m[M(2, 0)] * m[M(3, 1)] - m[M(3, 0)] * m[M(2, 1)]));
   1.719 +
   1.720 +	return m[M(0, 0)] * det11 - m[M(0, 1)] * det12 + m[M(0, 2)] * det13 - m[M(0, 3)] * det14;
   1.721 +}
   1.722 +
   1.723 +static void m4_adjoint(double *res, double *m)
   1.724 +{
   1.725 +	int i, j;
   1.726 +	double coef[16];
   1.727 +
   1.728 +	coef[M(0, 0)] =	(m[M(1, 1)] * (m[M(2, 2)] * m[M(3, 3)] - m[M(3, 2)] * m[M(2, 3)])) -
   1.729 +					(m[M(1, 2)] * (m[M(2, 1)] * m[M(3, 3)] - m[M(3, 1)] * m[M(2, 3)])) +
   1.730 +					(m[M(1, 3)] * (m[M(2, 1)] * m[M(3, 2)] - m[M(3, 1)] * m[M(2, 2)]));
   1.731 +	coef[M(0, 1)] =	(m[M(1, 0)] * (m[M(2, 2)] * m[M(3, 3)] - m[M(3, 2)] * m[M(2, 3)])) -
   1.732 +					(m[M(1, 2)] * (m[M(2, 0)] * m[M(3, 3)] - m[M(3, 0)] * m[M(2, 3)])) +
   1.733 +					(m[M(1, 3)] * (m[M(2, 0)] * m[M(3, 2)] - m[M(3, 0)] * m[M(2, 2)]));
   1.734 +	coef[M(0, 2)] =	(m[M(1, 0)] * (m[M(2, 1)] * m[M(3, 3)] - m[M(3, 1)] * m[M(2, 3)])) -
   1.735 +					(m[M(1, 1)] * (m[M(2, 0)] * m[M(3, 3)] - m[M(3, 0)] * m[M(2, 3)])) +
   1.736 +					(m[M(1, 3)] * (m[M(2, 0)] * m[M(3, 1)] - m[M(3, 0)] * m[M(2, 1)]));
   1.737 +	coef[M(0, 3)] =	(m[M(1, 0)] * (m[M(2, 1)] * m[M(3, 2)] - m[M(3, 1)] * m[M(2, 2)])) -
   1.738 +					(m[M(1, 1)] * (m[M(2, 0)] * m[M(3, 2)] - m[M(3, 0)] * m[M(2, 2)])) +
   1.739 +					(m[M(1, 2)] * (m[M(2, 0)] * m[M(3, 1)] - m[M(3, 0)] * m[M(2, 1)]));
   1.740 +
   1.741 +	coef[M(1, 0)] =	(m[M(0, 1)] * (m[M(2, 2)] * m[M(3, 3)] - m[M(3, 2)] * m[M(2, 3)])) -
   1.742 +					(m[M(0, 2)] * (m[M(2, 1)] * m[M(3, 3)] - m[M(3, 1)] * m[M(2, 3)])) +
   1.743 +					(m[M(0, 3)] * (m[M(2, 1)] * m[M(3, 2)] - m[M(3, 1)] * m[M(2, 2)]));
   1.744 +	coef[M(1, 1)] =	(m[M(0, 0)] * (m[M(2, 2)] * m[M(3, 3)] - m[M(3, 2)] * m[M(2, 3)])) -
   1.745 +					(m[M(0, 2)] * (m[M(2, 0)] * m[M(3, 3)] - m[M(3, 0)] * m[M(2, 3)])) +
   1.746 +					(m[M(0, 3)] * (m[M(2, 0)] * m[M(3, 2)] - m[M(3, 0)] * m[M(2, 2)]));
   1.747 +	coef[M(1, 2)] =	(m[M(0, 0)] * (m[M(2, 1)] * m[M(3, 3)] - m[M(3, 1)] * m[M(2, 3)])) -
   1.748 +					(m[M(0, 1)] * (m[M(2, 0)] * m[M(3, 3)] - m[M(3, 0)] * m[M(2, 3)])) +
   1.749 +					(m[M(0, 3)] * (m[M(2, 0)] * m[M(3, 1)] - m[M(3, 0)] * m[M(2, 1)]));
   1.750 +	coef[M(1, 3)] =	(m[M(0, 0)] * (m[M(2, 1)] * m[M(3, 2)] - m[M(3, 1)] * m[M(2, 2)])) -
   1.751 +					(m[M(0, 1)] * (m[M(2, 0)] * m[M(3, 2)] - m[M(3, 0)] * m[M(2, 2)])) +
   1.752 +					(m[M(0, 2)] * (m[M(2, 0)] * m[M(3, 1)] - m[M(3, 0)] * m[M(2, 1)]));
   1.753 +
   1.754 +	coef[M(2, 0)] =	(m[M(0, 1)] * (m[M(1, 2)] * m[M(3, 3)] - m[M(3, 2)] * m[M(1, 3)])) -
   1.755 +					(m[M(0, 2)] * (m[M(1, 1)] * m[M(3, 3)] - m[M(3, 1)] * m[M(1, 3)])) +
   1.756 +					(m[M(0, 3)] * (m[M(1, 1)] * m[M(3, 2)] - m[M(3, 1)] * m[M(1, 2)]));
   1.757 +	coef[M(2, 1)] =	(m[M(0, 0)] * (m[M(1, 2)] * m[M(3, 3)] - m[M(3, 2)] * m[M(1, 3)])) -
   1.758 +					(m[M(0, 2)] * (m[M(1, 0)] * m[M(3, 3)] - m[M(3, 0)] * m[M(1, 3)])) +
   1.759 +					(m[M(0, 3)] * (m[M(1, 0)] * m[M(3, 2)] - m[M(3, 0)] * m[M(1, 2)]));
   1.760 +	coef[M(2, 2)] =	(m[M(0, 0)] * (m[M(1, 1)] * m[M(3, 3)] - m[M(3, 1)] * m[M(1, 3)])) -
   1.761 +					(m[M(0, 1)] * (m[M(1, 0)] * m[M(3, 3)] - m[M(3, 0)] * m[M(1, 3)])) +
   1.762 +					(m[M(0, 3)] * (m[M(1, 0)] * m[M(3, 1)] - m[M(3, 0)] * m[M(1, 1)]));
   1.763 +	coef[M(2, 3)] =	(m[M(0, 0)] * (m[M(1, 1)] * m[M(3, 2)] - m[M(3, 1)] * m[M(1, 2)])) -
   1.764 +					(m[M(0, 1)] * (m[M(1, 0)] * m[M(3, 2)] - m[M(3, 0)] * m[M(1, 2)])) +
   1.765 +					(m[M(0, 2)] * (m[M(1, 0)] * m[M(3, 1)] - m[M(3, 0)] * m[M(1, 1)]));
   1.766 +
   1.767 +	coef[M(3, 0)] =	(m[M(0, 1)] * (m[M(1, 2)] * m[M(2, 3)] - m[M(2, 2)] * m[M(1, 3)])) -
   1.768 +					(m[M(0, 2)] * (m[M(1, 1)] * m[M(2, 3)] - m[M(2, 1)] * m[M(1, 3)])) +
   1.769 +					(m[M(0, 3)] * (m[M(1, 1)] * m[M(2, 2)] - m[M(2, 1)] * m[M(1, 2)]));
   1.770 +	coef[M(3, 1)] =	(m[M(0, 0)] * (m[M(1, 2)] * m[M(2, 3)] - m[M(2, 2)] * m[M(1, 3)])) -
   1.771 +					(m[M(0, 2)] * (m[M(1, 0)] * m[M(2, 3)] - m[M(2, 0)] * m[M(1, 3)])) +
   1.772 +					(m[M(0, 3)] * (m[M(1, 0)] * m[M(2, 2)] - m[M(2, 0)] * m[M(1, 2)]));
   1.773 +	coef[M(3, 2)] =	(m[M(0, 0)] * (m[M(1, 1)] * m[M(2, 3)] - m[M(2, 1)] * m[M(1, 3)])) -
   1.774 +					(m[M(0, 1)] * (m[M(1, 0)] * m[M(2, 3)] - m[M(2, 0)] * m[M(1, 3)])) +
   1.775 +					(m[M(0, 3)] * (m[M(1, 0)] * m[M(2, 1)] - m[M(2, 0)] * m[M(1, 1)]));
   1.776 +	coef[M(3, 3)] =	(m[M(0, 0)] * (m[M(1, 1)] * m[M(2, 2)] - m[M(2, 1)] * m[M(1, 2)])) -
   1.777 +					(m[M(0, 1)] * (m[M(1, 0)] * m[M(2, 2)] - m[M(2, 0)] * m[M(1, 2)])) +
   1.778 +					(m[M(0, 2)] * (m[M(1, 0)] * m[M(2, 1)] - m[M(2, 0)] * m[M(1, 1)]));
   1.779 +
   1.780 +	m4_transpose(res, coef);
   1.781 +
   1.782 +	for(i=0; i<4; i++) {
   1.783 +		for(j=0; j<4; j++) {
   1.784 +			res[M(i, j)] = j % 2 ? -res[M(i, j)] : res[M(i, j)];
   1.785 +			if(i % 2) res[M(i, j)] = -res[M(i, j)];
   1.786 +		}
   1.787 +	}
   1.788 +}
   1.789 +
   1.790 +static void m4_inverse(double *res, double *m)
   1.791 +{
   1.792 +	int i, j;
   1.793 +	double adj[16];
   1.794 +	double det;
   1.795 +
   1.796 +	m4_adjoint(adj, m);
   1.797 +	det = m4_determinant(m);
   1.798 +
   1.799 +	for(i=0; i<4; i++) {
   1.800 +		for(j=0; j<4; j++) {
   1.801 +			res[M(i, j)] = adj[M(i, j)] / det;
   1.802 +		}
   1.803 +	}
   1.804 +}
   1.805 +