nuclear@1: #include nuclear@5: #include nuclear@5: #include nuclear@1: #include "min3d.h" nuclear@1: #include "m3dimpl.h" nuclear@1: nuclear@1: #ifndef M_PI nuclear@1: #define M_PI 3.141592653 nuclear@1: #endif nuclear@1: nuclear@3: struct min3d_context *m3dctx; nuclear@3: nuclear@1: int m3d_init(void) nuclear@1: { nuclear@1: if(!(m3dctx = malloc(sizeof *m3dctx))) { nuclear@1: return -1; nuclear@1: } nuclear@1: memset(m3dctx, 0, sizeof *m3dctx); nuclear@1: nuclear@1: m3d_matrix_mode(M3D_PROJECTION); nuclear@1: m3d_load_identity(); nuclear@1: m3d_matrix_mode(M3D_MODELVIEW); nuclear@1: m3d_load_identity(); nuclear@1: return 0; nuclear@1: } nuclear@1: nuclear@1: void m3d_shutdown(void) nuclear@1: { nuclear@1: free(m3dctx); nuclear@1: } nuclear@1: nuclear@1: void m3d_set_buffers(struct m3d_image *cbuf, uint16_t *zbuf) nuclear@1: { nuclear@1: m3dctx->cbuf = cbuf; nuclear@1: m3dctx->zbuf = zbuf; nuclear@1: } nuclear@1: nuclear@1: void m3d_clear(unsigned int bmask) nuclear@1: { nuclear@1: int num_pixels = m3dctx->cbuf->xsz * m3dctx->cbuf->ysz; nuclear@1: if(bmask & M3D_COLOR_BUFFER_BIT) { nuclear@1: memset(m3dctx->cbuf->pixels, 0, num_pixels * 3); nuclear@1: } nuclear@1: if(bmask & M3D_DEPTH_BUFFER_BIT) { nuclear@1: memset(m3dctx->zbuf, 0xff, num_pixels * sizeof *m3dctx->zbuf); nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: nuclear@1: void m3d_enable(int bit) nuclear@1: { nuclear@1: m3dctx->state |= (1 << bit); nuclear@1: } nuclear@1: nuclear@1: void m3d_disable(int bit) nuclear@1: { nuclear@1: m3dctx->state &= ~(1 << bit); nuclear@1: } nuclear@1: nuclear@1: nuclear@1: /* matrix stack */ nuclear@1: void m3d_matrix_mode(int mode) nuclear@1: { nuclear@1: m3dctx->mmode = mode; nuclear@1: } nuclear@1: nuclear@1: void m3d_load_identity(void) nuclear@1: { nuclear@1: static const float mid[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; nuclear@1: m3d_load_matrix(mid); nuclear@1: } nuclear@1: nuclear@1: void m3d_load_matrix(const float *m) nuclear@1: { nuclear@1: int top = m3dctx->mstack[m3dctx->mmode].top; nuclear@1: memcpy(m3dctx->mstack[m3dctx->mmode].m[top], m, 16 * sizeof *m); nuclear@1: } nuclear@1: nuclear@1: #define M(i,j) (((i) << 2) + (j)) nuclear@1: void m3d_mult_matrix(const float *m2) nuclear@1: { nuclear@1: int i, j, top = m3dctx->mstack[m3dctx->mmode].top; nuclear@1: float m1[16]; nuclear@1: float *dest = m3dctx->mstack[m3dctx->mmode].m[top]; nuclear@1: nuclear@1: memcpy(m1, dest, sizeof m1); nuclear@1: nuclear@1: for(i=0; i<4; i++) { nuclear@1: for(j=0; j<4; j++) { nuclear@1: dest[M(i,j)] = m1[M(0,j)] * m2[M(i,0)] + nuclear@1: m1[M(1,j)] * m2[M(i,1)] + nuclear@1: m1[M(2,j)] * m2[M(i,2)] + nuclear@1: m1[M(3,j)] * m2[M(i,3)]; nuclear@1: } nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: void m3d_translate(float x, float y, float z) nuclear@1: { nuclear@1: float m[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; nuclear@1: m[12] = x; nuclear@1: m[13] = y; nuclear@1: m[14] = z; nuclear@1: m3d_mult_matrix(m); nuclear@1: } nuclear@1: nuclear@1: void m3d_rotate(float deg, float x, float y, float z) nuclear@1: { nuclear@1: float xform[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; nuclear@1: nuclear@1: float angle = M_PI * deg / 180.0f; nuclear@1: float sina = sin(angle); nuclear@1: float cosa = cos(angle); nuclear@1: float one_minus_cosa = 1.0f - cosa; nuclear@1: float nxsq = x * x; nuclear@1: float nysq = y * y; nuclear@1: float nzsq = z * z; nuclear@1: nuclear@1: xform[0] = nxsq + (1.0f - nxsq) * cosa; nuclear@1: xform[4] = x * y * one_minus_cosa - z * sina; nuclear@1: xform[8] = x * z * one_minus_cosa + y * sina; nuclear@1: xform[1] = x * y * one_minus_cosa + z * sina; nuclear@1: xform[5] = nysq + (1.0 - nysq) * cosa; nuclear@1: xform[9] = y * z * one_minus_cosa - x * sina; nuclear@1: xform[2] = x * z * one_minus_cosa - y * sina; nuclear@1: xform[6] = y * z * one_minus_cosa + x * sina; nuclear@1: xform[10] = nzsq + (1.0 - nzsq) * cosa; nuclear@1: nuclear@1: m3d_mult_matrix(xform); nuclear@1: } nuclear@1: nuclear@1: void m3d_scale(float x, float y, float z) nuclear@1: { nuclear@1: static float m[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; nuclear@1: m[0] = x; nuclear@1: m[5] = y; nuclear@1: m[10] = z; nuclear@1: m3d_mult_matrix(m); nuclear@1: } nuclear@1: nuclear@1: void m3d_frustum(float left, float right, float bottom, float top, float nr, float fr) nuclear@1: { nuclear@1: float xform[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; nuclear@1: nuclear@1: float dx = right - left; nuclear@1: float dy = top - bottom; nuclear@1: float dz = fr - nr; nuclear@1: nuclear@1: float a = (right + left) / dx; nuclear@1: float b = (top + bottom) / dy; nuclear@1: float c = -(fr + nr) / dz; nuclear@1: float d = -2.0 * fr * nr / dz; nuclear@1: nuclear@1: xform[0] = 2.0 * nr / dx; nuclear@1: xform[5] = 2.0 * nr / dy; nuclear@1: xform[8] = a; nuclear@1: xform[9] = b; nuclear@1: xform[10] = c; nuclear@1: xform[11] = -1.0f; nuclear@1: xform[14] = d; nuclear@1: nuclear@1: m3d_mult_matrix(xform); nuclear@1: } nuclear@1: nuclear@1: void m3d_perspective(float vfov, float aspect, float nr, float fr) nuclear@1: { nuclear@1: float vfov_rad = M_PI * vfov / 180.0; nuclear@1: float x = nr * tan(vfov_rad / 2.0); nuclear@1: m3d_frustum(-aspect * x, aspect * x, -x, x, nr, fr); nuclear@1: } nuclear@1: nuclear@2: static void xform4(float *mat, float *vec) nuclear@2: { nuclear@2: float x = mat[0] * vec[0] + mat[1] * vec[1] + mat[2] * vec[2] + mat[3]; nuclear@2: float y = mat[4] * vec[0] + mat[5] * vec[1] + mat[6] * vec[2] + mat[7]; nuclear@2: float z = mat[8] * vec[0] + mat[9] * vec[1] + mat[10] * vec[2] + mat[11]; nuclear@2: float w = mat[12] * vec[0] + mat[13] * vec[1] + mat[14] * vec[2] + mat[15]; nuclear@2: nuclear@2: vec[0] = x; nuclear@2: vec[1] = y; nuclear@2: vec[2] = z; nuclear@2: vec[3] = w; nuclear@2: } nuclear@2: nuclear@3: static int proc_prim(int prim, struct min3d_vertex *res, struct min3d_vertex *v) nuclear@2: { nuclear@3: int i; nuclear@3: int vcount = prim; nuclear@3: int mvtop, ptop; nuclear@3: float *mvmat, *pmat; nuclear@3: nuclear@3: mvtop = m3dctx->mstack[M3D_MODELVIEW].top; nuclear@3: mvmat = m3dctx->mstack[M3D_MODELVIEW].m[mvtop]; nuclear@3: ptop = m3dctx->mstack[M3D_PROJECTION].top; nuclear@3: pmat = m3dctx->mstack[M3D_PROJECTION].m[ptop]; nuclear@3: nuclear@3: /* transform to view space */ nuclear@3: for(i=0; i= w || nuclear@3: res[0].pos[0] / w < -1 || res[0].pos[0] / w >= 1 || nuclear@3: res[0].pos[1] / w < -1 || res[0].pos[1] / w >= 1) { nuclear@3: vcount = 0; nuclear@3: } nuclear@3: } nuclear@3: break; nuclear@3: nuclear@3: default: nuclear@3: break; /* TODO */ nuclear@3: } nuclear@3: nuclear@3: /* perspective division */ nuclear@3: for(i=0; ivert_array = varr; nuclear@5: } nuclear@5: nuclear@5: void m3d_normal_array(const float *narr) nuclear@5: { nuclear@5: m3dctx->norm_array = narr; nuclear@5: } nuclear@5: nuclear@5: void m3d_color_array(const float *carr) nuclear@5: { nuclear@5: m3dctx->col_array = carr; nuclear@5: } nuclear@5: nuclear@5: void m3d_texcoord_array(const float *tcarr) nuclear@5: { nuclear@5: m3dctx->tc_array = tcarr; nuclear@5: } nuclear@5: nuclear@5: nuclear@5: void m3d_draw(int prim, int vcount) nuclear@1: { nuclear@3: int i; nuclear@3: struct min3d_vertex v[4]; nuclear@3: struct min3d_vertex resv[16]; nuclear@5: const float *varr = m3dctx->vert_array; nuclear@5: const float *carr = m3dctx->col_array; nuclear@5: nuclear@5: if(!varr) return; nuclear@3: nuclear@3: for(i=0; icur_color[0]; nuclear@5: v[idx].color[1] = carr ? *carr++ : m3dctx->cur_color[1]; nuclear@5: v[idx].color[2] = carr ? *carr++ : m3dctx->cur_color[2]; nuclear@3: nuclear@3: if(idx == prim - 1) { nuclear@3: int resnum = proc_prim(prim, resv, v); nuclear@3: switch(resnum) { nuclear@3: case 1: nuclear@3: draw_point(resv); nuclear@3: break; nuclear@3: nuclear@3: case '2': nuclear@3: draw_line(resv); nuclear@3: break; nuclear@3: nuclear@3: default: nuclear@3: draw_poly(resv, resnum); nuclear@3: } nuclear@3: } nuclear@3: } nuclear@1: } nuclear@1: nuclear@5: void m3d_draw_indexed(int prim, const int *idxarr, int icount) nuclear@1: { nuclear@1: /* TODO */ nuclear@1: } nuclear@1: