X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Fxgl.c;fp=src%2Fxgl.c;h=376d792bf7a62f8adb4ca211d09b3dd5a15cf727;hb=5b98299a1aa716cc17cb5f70498c8e23cac945cb;hp=0000000000000000000000000000000000000000;hpb=ca3123df6cd875b1361533020c1f4eebfe9da295;p=gba_blender diff --git a/src/xgl.c b/src/xgl.c new file mode 100644 index 0000000..376d792 --- /dev/null +++ b/src/xgl.c @@ -0,0 +1,179 @@ +/* +blender for the Gameboy Advance +Copyright (C) 2021 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 "xgl.h" +#include "polyfill.h" + +#define MAT_STACK_SIZE 4 + +static int vp[4]; +static int32_t mat[MAT_STACK_SIZE][16]; +static int mtop; + +void xgl_init(void) +{ + xgl_viewport(0, 0, 240, 160); + xgl_load_identity(); +} + +void xgl_viewport(int x, int y, int w, int h) +{ + vp[0] = x; + vp[1] = y; + vp[2] = w; + vp[3] = h; +} + +void xgl_push_matrix(void) +{ + int prev; + + if(mtop >= MAT_STACK_SIZE - 1) return; + + prev = mtop++; + memcpy(mat[mtop], mat[prev], sizeof mat[0]); +} + +void xgl_pop_matrix(void) +{ + if(mtop > 0) mtop--; +} + +static const int32_t id[] = { + 0x10000, 0, 0, 0, + 0, 0x10000, 0, 0, + 0, 0, 0x10000, 0, + 0, 0, 0, 0x10000 +}; + +void xgl_load_identity(void) +{ + xgl_load_matrix(id); +} + +void xgl_load_matrix(const int32_t *m) +{ + memcpy(mat[mtop], m, sizeof mat[0]); +} + +#define M(i,j) (((i) << 2) + (j)) +#define XMUL(a, b) (((a) >> 8) * ((b) >> 8)) +void xgl_mult_matrix(const int32_t *m2) +{ + int i, j; + int32_t m1[16]; + int32_t *dest = mat[mtop]; + + memcpy(m1, dest, sizeof m1); + + for(i=0; i<4; i++) { + for(j=0; j<4; j++) { + *dest++ = XMUL(m1[M(0, j)], m2[M(i, 0)]) + + XMUL(m1[M(1, j)], m2[M(i, 1)]) + + XMUL(m1[M(2, j)], m2[M(i, 2)]) + + XMUL(m1[M(3, j)], m2[M(i, 3)]); + } + } +} + +#define XSIN(x) (int32_t)(sin(x / 65536.0f) * 65536.0f) +#define XCOS(x) (int32_t)(cos(x / 65536.0f) * 65536.0f) + +void xgl_translate(int32_t x, int32_t y, int32_t z) +{ + int32_t m[16] = {0x10000, 0, 0, 0, 0, 0x10000, 0, 0, 0, 0, 0x10000, 0, 0, 0, 0, 0x10000}; + m[12] = x; + m[13] = y; + m[14] = z; + xgl_mult_matrix(m); +} + +void xgl_rotate_x(int32_t angle) +{ + int32_t m[16] = {0x10000, 0, 0, 0, 0, 0x10000, 0, 0, 0, 0, 0x10000, 0, 0, 0, 0, 0x10000}; + int32_t sa = XSIN(angle); + int32_t ca = XCOS(angle); + m[5] = ca; + m[6] = sa; + m[9] = -sa; + m[10] = ca; + xgl_mult_matrix(m); +} + +void xgl_rotate_y(int32_t angle) +{ + int32_t m[16] = {0x10000, 0, 0, 0, 0, 0x10000, 0, 0, 0, 0, 0x10000, 0, 0, 0, 0, 0x10000}; + int32_t sa = XSIN(angle); + int32_t ca = XCOS(angle); + m[0] = ca; + m[2] = -sa; + m[8] = sa; + m[10] = ca; + xgl_mult_matrix(m); +} + +void xgl_rotate_z(int32_t angle) +{ + int32_t m[16] = {0x10000, 0, 0, 0, 0, 0x10000, 0, 0, 0, 0, 0x10000, 0, 0, 0, 0, 0x10000}; + int32_t sa = XSIN(angle); + int32_t ca = XCOS(angle); + m[0] = ca; + m[1] = sa; + m[4] = -sa; + m[5] = ca; + xgl_mult_matrix(m); +} + +void xgl_scale(int32_t x, int32_t y, int32_t z) +{ + int32_t m[16] = {0}; + m[0] = x; + m[5] = y; + m[10] = z; + m[15] = 0x10000; + xgl_mult_matrix(m); +} + +static void xform(struct xvertex *out, const struct xvertex *in, const int32_t *m) +{ + out->x = XMUL(m[0], in->x) + XMUL(m[4], in->y) + XMUL(m[8], in->z) + m[12]; + out->y = XMUL(m[1], in->x) + XMUL(m[5], in->y) + XMUL(m[9], in->z) + m[13]; + out->z = XMUL(m[2], in->x) + XMUL(m[6], in->y) + XMUL(m[10], in->z) + m[14]; +} + +void xgl_draw(int prim, const struct xvertex *varr, int vcount) +{ + int i; + struct xvertex xv[4]; + struct pvertex pv[4]; + + while(vcount >= prim) { + for(i=0; i> 1) * vp[2]) >> 8) + (vp[0] << 8); + pv[i].y = ((((xv[i].y + 0x10000) >> 1) * vp[3]) >> 8) + (vp[1] << 8); + } + vcount -= prim; + + polyfill_flat(pv, prim, 0xff); + } +}