X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=regis;a=blobdiff_plain;f=x3d.c;fp=x3d.c;h=53faa9b1252fb8ffe9c83d8d16b615a4bfba825c;hp=0000000000000000000000000000000000000000;hb=4ac276ea513d4460f9db8c43b4dbde5ebad652b5;hpb=46aa499cb189f9eb533e1e5a95a3770a0b3df8b4 diff --git a/x3d.c b/x3d.c new file mode 100644 index 0000000..53faa9b --- /dev/null +++ b/x3d.c @@ -0,0 +1,265 @@ +#include +#include +#include +#include "x3d.h" +#include "fixed.h" +#include "sincos.h" +#include "regis.h" + +typedef struct pvec3 { + int32_t x, y, z; +} pvec3; + +typedef struct pvec2 { + int32_t x, y; +} pvec2; + + +#define MAT_STACK_SIZE 4 + +struct matrix { + int32_t m[12]; +}; + +static void proc_vertex(const int32_t *vin, pvec3 *vout); + +void draw_poly(int num, const pvec3 *verts, int color); +void draw_point(const pvec3 *v, int color); + + +static int32_t proj_fov = M_PI_X16; +static int32_t proj_aspect = 65536; +static int32_t inv_proj_aspect = 65536; +static int32_t proj_near = ftox16(0.5); +static int32_t proj_far = 500 << 16; +static int32_t inv_tan_half_xfov, inv_tan_half_yfov; + +#define ID_INIT {65536, 0, 0, 0, 0, 65536, 0, 0, 0, 0, 65536, 0} + +static struct matrix identity = { ID_INIT }; + +static short mtop; +static struct matrix mstack[MAT_STACK_SIZE] = { {ID_INIT}, {ID_INIT} }; + +static const int32_t *vertex_array; +static unsigned short vertex_count; + +static uint8_t im_color_index; + + +void x3d_projection(int fov, int32_t aspect, int32_t nearz, int32_t farz) +{ + proj_fov = (M_PI_X16 * fov) / 180; + proj_aspect = aspect; + inv_proj_aspect = x16div(65536, proj_aspect); + proj_near = nearz; + proj_far = farz; + + inv_tan_half_yfov = (int32_t)(65536.0 / tan(0.5 * proj_fov / 65536.0)); + inv_tan_half_xfov = x16mul(inv_tan_half_yfov, aspect); +} + +int x3d_push_matrix(void) +{ + short newtop = mtop + 1; + if(newtop >= MAT_STACK_SIZE) { + return -1; + } + memcpy(mstack + newtop, mstack + mtop, sizeof *mstack); + mtop = newtop; + return 0; +} + +int x3d_pop_matrix(void) +{ + if(mtop <= 0) { + return -1; + } + --mtop; + return 0; +} + +void x3d_load_matrix(int32_t *m) +{ + memcpy(mstack[mtop].m, m, sizeof *mstack); +} + + +#define M(i,j) (((i) << 2) + (j)) +void x3d_mult_matrix(int32_t *m) +{ + int i, j; + struct matrix tmp; + + memcpy(tmp.m, mstack[mtop].m, sizeof tmp); + + for(i=0; i<3; i++) { + for(j=0; j<4; j++) { + mstack[mtop].m[M(i, j)] = + x16mul(m[M(0, j)], tmp.m[M(i, 0)]) + + x16mul(m[M(1, j)], tmp.m[M(i, 1)]) + + x16mul(m[M(2, j)], tmp.m[M(i, 2)]); + } + mstack[mtop].m[M(i, 3)] += tmp.m[M(i, 3)]; + } +} + +void x3d_load_identity(void) +{ + memcpy(mstack[mtop].m, identity.m, sizeof identity); +} + +void x3d_translate(int32_t x, int32_t y, int32_t z) +{ + int32_t m[] = ID_INIT; + m[3] = x; + m[7] = y; + m[11] = z; + + x3d_mult_matrix(m); +} + +void x3d_rotate(int32_t deg, int32_t x, int32_t y, int32_t z) +{ + int32_t xform[] = ID_INIT; + + int32_t angle = x16mul(M_PI_X16, deg) / 180; + int32_t sina = sin_x16(angle); + int32_t cosa = cos_x16(angle); + int32_t one_minus_cosa = 65536 - cosa; + int32_t nxsq = x16sq(x); + int32_t nysq = x16sq(y); + int32_t nzsq = x16sq(z); + + xform[0] = nxsq + x16mul(65536 - nxsq, cosa); + xform[4] = x16mul(x16mul(x, y), one_minus_cosa) - x16mul(z, sina); + xform[8] = x16mul(x16mul(x, z), one_minus_cosa) + x16mul(y, sina); + xform[1] = x16mul(x16mul(x, y), one_minus_cosa) + x16mul(z, sina); + xform[5] = nysq + x16mul(65536 - nysq, cosa); + xform[9] = x16mul(x16mul(y, z), one_minus_cosa) - x16mul(x, sina); + xform[2] = x16mul(x16mul(x, z), one_minus_cosa) - x16mul(y, sina); + xform[6] = x16mul(x16mul(y, z), one_minus_cosa) + x16mul(x, sina); + xform[10] = nzsq + x16mul(65536 - nzsq, cosa); + + x3d_mult_matrix(xform); +} + +void x3d_scale(int32_t x, int32_t y, int32_t z) +{ + int32_t m[] = ID_INIT; + + m[0] = x; + m[5] = y; + m[10] = z; + + x3d_mult_matrix(m); +} + +void x3d_vertex_array(int count, const int32_t *ptr) +{ + vertex_array = ptr; + vertex_count = count; +} + +int x3d_draw(int prim, int vnum) +{ + int i, j, pverts = prim; + const int32_t *vptr = vertex_array; + uint16_t color; + + if(!vertex_array) return -1; + + if(vnum > vertex_count) { + vnum = vertex_count; + } + + for(i=0; ix = tvert[0]; + vout->y = tvert[1]; + vout->z = tvert[2]; +} + +void x3d_color_index(int cidx) +{ + im_color_index = cidx; +} + + +void draw_poly(int num, const pvec3 *verts, int color) +{ + int i; + regis_abspos(verts[0].x, verts[0].y); + regis_begin_vector(REGIS_BOUNDED); + + for(i=0; ix, verts->y); + } + regis_end_vector(); +} + +void draw_point(const pvec3 *v, int color) +{ +}