From d1a2007e191d68b104e436d1817eafcc99ae21dd Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Wed, 7 Sep 2016 01:45:52 +0300 Subject: [PATCH] wrote most of the 3d pipeline stuff --- src/3dgfx.c | 242 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/3dgfx.h | 20 +++-- 2 files changed, 250 insertions(+), 12 deletions(-) diff --git a/src/3dgfx.c b/src/3dgfx.c index e7aabc2..5cf3c42 100644 --- a/src/3dgfx.c +++ b/src/3dgfx.c @@ -1,5 +1,8 @@ +#include +#include #include #include "3dgfx.h" +#include "polyfill.h" #define STACK_SIZE 8 typedef float g3d_matrix[16]; @@ -14,7 +17,17 @@ struct g3d_state { void *pixels; }; +static void xform4_vec3(const float *mat, float *vec); +static void xform3_vec3(const float *mat, float *vec); +static void proc_vertex(struct pvertex *res, const struct g3d_vertex *vert, int space); + static struct g3d_state st; +static const float idmat[] = { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 +}; void g3d_init(void) { @@ -57,6 +70,8 @@ unsigned int g3d_getopt(unsigned int mask) void g3d_set_matrix(int which, const float *m) { int top = st.mtop[which]; + + if(!m) m = idmat; memcpy(st.mat[which][top], m, 16 * sizeof(float)); } @@ -78,4 +93,229 @@ void g3d_mult_matrix(int which, const float *m2) } } } -/* TODO continue ... */ + +void g3d_push_matrix(int which) +{ + int top = st.mtop[which]; + if(top >= G3D_NUM_MATRICES) { + fprintf(stderr, "g3d_push_matrix overflow\n"); + return; + } + memcpy(st.mat[which][top + 1], st.mat[which][top], 16 * sizeof(float)); + st.mtop[which] = top + 1;; +} + +void g3d_pop_matrix(int which) +{ + if(st.mtop[which] <= 0) { + fprintf(stderr, "g3d_pop_matrix underflow\n"); + return; + } + --st.mtop[which]; +} + +void g3d_translate(int which, float x, float y, float z) +{ + float m[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; + m[12] = x; + m[13] = y; + m[14] = z; + g3d_mult_matrix(which, m); +} + +void g3d_rotate(int which, float deg, float x, float y, float z) +{ + float m[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + float angle = M_PI * deg / 180.0f; + float sina = sin(angle); + float cosa = cos(angle); + float one_minus_cosa = 1.0f - cosa; + float nxsq = x * x; + float nysq = y * y; + float nzsq = z * z; + + m[0] = nxsq + (1.0f - nxsq) * cosa; + m[4] = x * y * one_minus_cosa - z * sina; + m[8] = x * z * one_minus_cosa + y * sina; + m[1] = x * y * one_minus_cosa + z * sina; + m[5] = nysq + (1.0 - nysq) * cosa; + m[9] = y * z * one_minus_cosa - x * sina; + m[2] = x * z * one_minus_cosa - y * sina; + m[6] = y * z * one_minus_cosa + x * sina; + m[10] = nzsq + (1.0 - nzsq) * cosa; + + g3d_mult_matrix(which, m); +} + +void g3d_scale(int which, float x, float y, float z) +{ + float m[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + m[0] = x; + m[5] = y; + m[10] = z; + g3d_mult_matrix(which, m); +} + +void g3d_ortho(int which, float left, float right, float bottom, float top, float znear, float zfar) +{ + float m[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + float dx = right - left; + float dy = top - bottom; + float dz = zfar - znear; + + m[0] = 2.0 / dx; + m[5] = 2.0 / dy; + m[10] = -2.0 / dz; + m[12] = -(right + left) / dx; + m[13] = -(top + bottom) / dy; + m[14] = -(zfar + znear) / dz; + + g3d_mult_matrix(which, m); +} + +void g3d_frustum(int which, float left, float right, float bottom, float top, float nr, float fr) +{ + float m[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + float dx = right - left; + float dy = top - bottom; + float dz = fr - nr; + + float a = (right + left) / dx; + float b = (top + bottom) / dy; + float c = -(fr + nr) / dz; + float d = -2.0 * fr * nr / dz; + + m[0] = 2.0 * nr / dx; + m[5] = 2.0 * nr / dy; + m[8] = a; + m[9] = b; + m[10] = c; + m[11] = -1.0f; + m[14] = d; + + g3d_mult_matrix(which, m); +} + +void g3d_perspective(int which, float vfov_deg, float aspect, float znear, float zfar) +{ + float m[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + float vfov = M_PI * vfov_deg / 180.0f; + float s = 1.0f / tan(vfov * 0.5f); + float range = znear - zfar; + + m[0] = s / aspect; + m[5] = s; + m[10] = (znear + zfar) / range; + m[11] = -1.0f; + m[14] = 2.0f * znear * zfar / range; + + g3d_mult_matrix(which, m); +} + +void g3d_draw(int prim, int space, const struct g3d_vertex *varr, int varr_size) +{ + int i; + int vnum = prim; /* primitive vertex counts correspond to the enum values */ + + while(varr_size >= vnum) { + struct pvertex pv[4]; + + for(i=0; ix, vert->y, vert->z, 1.0f); + VEC3(norm, vert->nx, vert->ny, vert->nz); + + switch(space) { + case G3D_LOCAL_SPACE: + memcpy(norm_mat, st.mat[G3D_MODELVIEW][mvtop], 16 * sizeof(float)); + norm_mat[12] = norm_mat[13] = norm_mat[14] = 0.0f; + + xform4_vec3(pos, st.mat[G3D_MODELVIEW][mvtop]); + xform3_vec3(norm, norm_mat); + + case G3D_VIEW_SPACE: + if(st.opt & G3D_LIGHTING) { + /* TODO lighting */ + color[0] = vert->r; + color[1] = vert->g; + color[2] = vert->b; + } + xform4_vec3(pos, st.mat[G3D_PROJECTION][ptop]); + + case G3D_CLIP_SPACE: + /* TODO clipping */ + if(pos[3] != 0.0f) { + pos[0] /= pos[3]; + pos[1] /= pos[3]; + pos[2] /= pos[3]; + } + + case G3D_SCREEN_SPACE: + pos[0] = (pos[0] * 0.5 + 0.5) * (float)st.width; + pos[1] = (0.5 - pos[0] * 0.5) * (float)st.height; + + case G3D_PIXEL_SPACE: + break; + } + + /* convert pos to 24.8 fixed point */ + res->x = (int32_t)(pos[0] * 256.0f); + res->y = (int32_t)(pos[1] * 256.0f); + + /* convert tex coords to 16.16 fixed point */ + res->u = (int32_t)(vert->u * 65536.0f); + res->v = (int32_t)(vert->v * 65536.0f); + + /* pass color through as is */ + res->r = color[0]; + res->g = color[1]; + res->b = color[2]; +} diff --git a/src/3dgfx.h b/src/3dgfx.h index a6b3645..a2fa154 100644 --- a/src/3dgfx.h +++ b/src/3dgfx.h @@ -28,8 +28,7 @@ enum { /* 2nd arg to g3d_draw: which space are input verts in. skips parts of the pipeline */ enum { G3D_LOCAL_SPACE, /* this being 0 makes a nice default arg. */ - G3D_WORLD_SPACE, /* ignore world matrix */ - G3D_VIEW_SPACE, /* ignore view matrix */ + G3D_VIEW_SPACE, /* ignore modelview matrix */ G3D_CLIP_SPACE, /* ignore projection matrix */ G3D_SCREEN_SPACE,/* 2D verts, don't divide by w */ G3D_PIXEL_SPACE /* in pixel units, ignore viewport */ @@ -37,8 +36,7 @@ enum { /* matrix stacks */ enum { - G3D_WORLD, - G3D_VIEW, + G3D_MODELVIEW, G3D_PROJECTION, G3D_NUM_MATRICES @@ -58,13 +56,13 @@ void g3d_mult_matrix(int which, const float *m); void g3d_push_matrix(int which); void g3d_pop_matrix(int which); -void g3d_translate(float x, float y, float z); -void g3d_rotate(float angle, float x, float y, float z); -void g3d_scale(float x, float y, float z); -void g3d_ortho(float left, float right, float bottom, float top, float znear, float zfar); -void g3d_frustum(float left, float right, float bottom, float top, float znear, float zfar); -void g3d_perspective(float vfov, float aspect, float znear, float zfar); +void g3d_translate(int which, float x, float y, float z); +void g3d_rotate(int which, float angle, float x, float y, float z); +void g3d_scale(int which, float x, float y, float z); +void g3d_ortho(int which, float left, float right, float bottom, float top, float znear, float zfar); +void g3d_frustum(int which, float left, float right, float bottom, float top, float znear, float zfar); +void g3d_perspective(int which, float vfov, float aspect, float znear, float zfar); -void g3d_draw(int prim, int space, const struct g3d_vertex *varr, int num); +void g3d_draw(int prim, int space, const struct g3d_vertex *varr, int varr_size); #endif /* THREEDGFX_H_ */ -- 1.7.10.4