+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "3dgfx.h"
+#include "util.h"
static int32_t mvmat[16];
static int32_t pmat[16];
+static int vp[4];
+
+unsigned char *g3d_fbpixels;
+int g3d_width, g3d_height;
+int g3d_curcidx;
+
int g3d_init(void)
{
memset(mvmat, 0, sizeof mvmat);
memset(pmat, 0, sizeof pmat);
- mvmat[0] = mvmat[5] = mvmat[10] = mvmat[15] = 0;
- pmat[0] = pmat[5] = pmat[10] = pmat[15] = 0;
+ mvmat[0] = mvmat[5] = mvmat[10] = mvmat[15] = 0x10000;
+ pmat[0] = pmat[5] = pmat[10] = pmat[15] = 0x10000;
+ g3d_curcidx = 0xff;
return 0;
}
{
}
-void g3d_framebuf(int width, int height, void *fb)
+void g3d_framebuffer(int width, int height, void *fb)
{
+ g3d_fbpixels = fb;
+ g3d_width = width;
+ g3d_height = height;
+
+ vp[0] = vp[1] = 0;
+ vp[2] = width;
+ vp[3] = height;
}
void g3d_modelview(const int32_t *m)
memcpy(pmat, m, sizeof pmat);
}
+void g3d_color(int cidx)
+{
+ g3d_curcidx = cidx;
+}
+
+static const int primverts[] = {1, 2, 3, 4};
+
void g3d_draw(int prim, struct g3d_vertex *varr, int vcount)
{
+ int i, prim_vnum;
+
+ prim_vnum = primverts[prim];
+
+ for(i=0; i<vcount; i+=prim_vnum) {
+ g3d_draw_prim(prim, varr);
+ varr += prim_vnum;
+ }
+}
+
+int32_t vpscale(int32_t x, int32_t s, int32_t shift);
+#pragma aux vpscale = \
+ "add eax, 0x100" \
+ "mul ebx" \
+ "shrd eax, edx, cl" \
+ parm [eax] [ebx] [ecx] \
+ value [eax];
+
+void g3d_draw_prim(int prim, struct g3d_vertex *varr)
+{
+ int i, vcount, x, y, x1, y1;
+ struct g3d_vertex v[4];
+
+ vcount = primverts[prim];
+
+ for(i=0; i<vcount; i++) {
+ v[i] = varr[i];
+
+ /* transform to view space */
+ g3d_xform(v + i, mvmat);
+
+ /* transform to homogeneous clip space */
+ g3d_xform(v + i, pmat);
+
+ /* TODO clip */
+
+ /* perspective division */
+ if(v[i].w != 0) {
+ v[i].x = (v[i].x << 4) / (v[i].w >> 4);
+ v[i].y = (v[i].y << 4) / (v[i].w >> 4);
+ }
+
+ /* viewport transform */
+ v[i].x = vpscale(v[i].x, vp[2], 1) + (vp[0] << 8);
+ v[i].y = vpscale(-v[i].y, vp[3], 1) + (vp[1] << 8);
+ }
+
+ switch(prim) {
+ case G3D_POINTS:
+ x = v[0].x >> 8;
+ y = v[0].y >> 8;
+ if(x >= 0 && y >= 0 && x < XRES && y < YRES) {
+ g3d_fbpixels[y * XRES + x] = g3d_curcidx;
+ }
+ break;
+
+ case G3D_LINES:
+ break; /* TODO */
+
+ case G3D_TRIANGLES:
+ g3d_polyfill(v);
+ break;
+
+ case G3D_QUADS:
+ g3d_polyfill(v);
+ v[1] = v[0];
+ g3d_polyfill(v + 1);
+ break;
+ }
}
--- /dev/null
+ bits 32\r
+ section .rodata\r
+\r
+ global _sintab\r
+_sintab:\r
+ dw 0, 100, 201, 301, 401, 502, 602, 702, 802, 902, 1002, 1102, 1202\r
+ dw 1301, 1400, 1499, 1598, 1696, 1794, 1892, 1990, 2087, 2184, 2281\r
+ dw 2378, 2474, 2569, 2664, 2759, 2854, 2948, 3041, 3134, 3227, 3319\r
+ dw 3411, 3502, 3593, 3683, 3772, 3861, 3950, 4037, 4124, 4211, 4297\r
+ dw 4382, 4467, 4551, 4634, 4717, 4798, 4879, 4960, 5039, 5118, 5196\r
+ dw 5274, 5350, 5426, 5501, 5575, 5648, 5721, 5792, 5863, 5933, 6001\r
+ dw 6069, 6136, 6203, 6268, 6332, 6395, 6458, 6519, 6579, 6639, 6697\r
+ dw 6755, 6811, 6866, 6921, 6974, 7026, 7077, 7127, 7176, 7224, 7271\r
+ dw 7317, 7361, 7405, 7447, 7489, 7529, 7568, 7606, 7643, 7678, 7713\r
+ dw 7746, 7778, 7809, 7839, 7867, 7895, 7921, 7946, 7970, 7992, 8014\r
+ dw 8034, 8053, 8071, 8087, 8103, 8117, 8130, 8142, 8152, 8161, 8169\r
+ dw 8176, 8182, 8186, 8189, 8191, 8192, 8191, 8189, 8186, 8182, 8176\r
+ dw 8169, 8161, 8152, 8142, 8130, 8117, 8103, 8087, 8071, 8053, 8034\r
+ dw 8014, 7992, 7970, 7946, 7921, 7895, 7867, 7839, 7809, 7778, 7746\r
+ dw 7713, 7678, 7643, 7606, 7568, 7529, 7489, 7447, 7405, 7361, 7317\r
+ dw 7271, 7224, 7176, 7127, 7077, 7026, 6974, 6921, 6866, 6811, 6755\r
+ dw 6697, 6639, 6579, 6519, 6458, 6395, 6332, 6268, 6203, 6136, 6069\r
+ dw 6001, 5933, 5863, 5792, 5721, 5648, 5575, 5501, 5426, 5350, 5274\r
+ dw 5196, 5118, 5039, 4960, 4879, 4798, 4717, 4634, 4551, 4467, 4382\r
+ dw 4297, 4211, 4124, 4037, 3950, 3861, 3772, 3683, 3593, 3502, 3411\r
+ dw 3319, 3227, 3134, 3041, 2948, 2854, 2759, 2664, 2569, 2474, 2378\r
+ dw 2281, 2184, 2087, 1990, 1892, 1794, 1696, 1598, 1499, 1400, 1301\r
+ dw 1202, 1102, 1002, 902, 802, 702, 602, 502, 401, 301, 201, 100\r
+ dw 0, -100, -201, -301, -401, -502, -602, -702, -802, -902, -1002\r
+ dw -1102, -1202, -1301, -1400, -1499, -1598, -1696, -1794, -1892\r
+ dw -1990, -2087, -2184, -2281, -2378, -2474, -2569, -2664, -2759\r
+ dw -2854, -2948, -3041, -3134, -3227, -3319, -3411, -3502, -3593\r
+ dw -3683, -3772, -3861, -3950, -4037, -4124, -4211, -4297, -4382\r
+ dw -4467, -4551, -4634, -4717, -4798, -4879, -4960, -5039, -5118\r
+ dw -5196, -5274, -5350, -5426, -5501, -5575, -5648, -5721, -5792\r
+ dw -5863, -5933, -6001, -6069, -6136, -6203, -6268, -6332, -6395\r
+ dw -6458, -6519, -6579, -6639, -6697, -6755, -6811, -6866, -6921\r
+ dw -6974, -7026, -7077, -7127, -7176, -7224, -7271, -7317, -7361\r
+ dw -7405, -7447, -7489, -7529, -7568, -7606, -7643, -7678, -7713\r
+ dw -7746, -7778, -7809, -7839, -7867, -7895, -7921, -7946, -7970\r
+ dw -7992, -8014, -8034, -8053, -8071, -8087, -8103, -8117, -8130\r
+ dw -8142, -8152, -8161, -8169, -8176, -8182, -8186, -8189, -8191\r
+ dw -8192, -8191, -8189, -8186, -8182, -8176, -8169, -8161, -8152\r
+ dw -8142, -8130, -8117, -8103, -8087, -8071, -8053, -8034, -8014\r
+ dw -7992, -7970, -7946, -7921, -7895, -7867, -7839, -7809, -7778\r
+ dw -7746, -7713, -7678, -7643, -7606, -7568, -7529, -7489, -7447\r
+ dw -7405, -7361, -7317, -7271, -7224, -7176, -7127, -7077, -7026\r
+ dw -6974, -6921, -6866, -6811, -6755, -6697, -6639, -6579, -6519\r
+ dw -6458, -6395, -6332, -6268, -6203, -6136, -6069, -6001, -5933\r
+ dw -5863, -5792, -5721, -5648, -5575, -5501, -5426, -5350, -5274\r
+ dw -5196, -5118, -5039, -4960, -4879, -4798, -4717, -4634, -4551\r
+ dw -4467, -4382, -4297, -4211, -4124, -4037, -3950, -3861, -3772\r
+ dw -3683, -3593, -3502, -3411, -3319, -3227, -3134, -3041, -2948\r
+ dw -2854, -2759, -2664, -2569, -2474, -2378, -2281, -2184, -2087\r
+ dw -1990, -1892, -1794, -1696, -1598, -1499, -1400, -1301, -1202\r
+ dw -1102, -1002, -902, -802, -702, -602, -502, -401, -301, -201, -100\r
+\r
+\r
+; vi:ft=nasm ts=8 sts=8 sw=8:\r
--- /dev/null
+#include <stdio.h>\r
+#include <string.h>\r
+#include "3dgfx.h"\r
+#include "util.h"\r
+\r
+static void filltop(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_vertex *v2);\r
+static void fillbot(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_vertex *v2);\r
+\r
+void g3d_polyfill(struct g3d_vertex *verts)\r
+{\r
+ int i, topidx, botidx, mididx;\r
+ int32_t dx, dy, dym;\r
+ struct g3d_vertex vtmp;\r
+\r
+ topidx = botidx = 0;\r
+ for(i=1; i<3; i++) {\r
+ if(verts[i].y < verts[topidx].y) {\r
+ topidx = i;\r
+ }\r
+ if(verts[i].y > verts[botidx].y) {\r
+ botidx = i;\r
+ }\r
+ }\r
+ mididx = (topidx + 1) % 3;\r
+ if(mididx == botidx) mididx = (mididx + 1) % 3;\r
+\r
+ dy = verts[botidx].y - verts[topidx].y;\r
+ if(dy == 0) return;\r
+\r
+ dx = verts[botidx].x - verts[topidx].x;\r
+ dym = verts[mididx].y - verts[topidx].y;\r
+ vtmp.x = muldiv(dx, dym, dy) + verts[topidx].x; /* dx * dym / dy + vtop.x */\r
+ vtmp.y = verts[mididx].y;\r
+\r
+ if(verts[topidx].y != verts[mididx].y) {\r
+ filltop(verts + topidx, verts + mididx, &vtmp);\r
+ }\r
+ if(verts[mididx].y != verts[botidx].y) {\r
+ fillbot(verts + mididx, &vtmp, verts + botidx);\r
+ }\r
+}\r
+\r
+static void filltop(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_vertex *v2)\r
+{\r
+ struct g3d_vertex *vtmp;\r
+ int x, xn, y, endy, len;\r
+ int32_t xl, xr, dxl, dxr, dxldy, dxrdy, dy;\r
+ unsigned char *fbptr;\r
+\r
+ if(v1->x > v2->x) {\r
+ vtmp = v1;\r
+ v1 = v2;\r
+ v2 = vtmp;\r
+ }\r
+\r
+ y = v0->y >> 8;\r
+ endy = v1->y >> 8;\r
+ x = v0->x >> 8;\r
+\r
+ fbptr = g3d_fbpixels + y * XRES + x;\r
+\r
+ xl = xr = v0->x;\r
+ dy = v1->y - v0->y;\r
+ dxl = v1->x - v0->x;\r
+ dxr = v2->x - v0->x;\r
+ dxldy = (dxl << 8) / dy;\r
+ dxrdy = (dxr << 8) / dy;\r
+\r
+ while(y++ < endy) {\r
+ len = (xr - xl) >> 8;\r
+ if(len > 0) memset(fbptr, g3d_curcidx, len);\r
+\r
+ xl += dxldy;\r
+ xr += dxrdy;\r
+ xn = xl >> 8;\r
+ fbptr += XRES + (xn - x);\r
+ x = xn;\r
+ }\r
+}\r
+\r
+static void fillbot(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_vertex *v2)\r
+{\r
+ struct g3d_vertex *vtmp;\r
+ int x, xn, y, endy, len;\r
+ int32_t xl, xr, dxl, dxr, dxldy, dxrdy, dy;\r
+ unsigned char *fbptr;\r
+\r
+ if(v0->x > v1->x) {\r
+ vtmp = v0;\r
+ v0 = v1;\r
+ v1 = vtmp;\r
+ }\r
+\r
+ y = v0->y >> 8;\r
+ endy = v2->y >> 8;\r
+ x = v0->x >> 8;\r
+\r
+ fbptr = g3d_fbpixels + y * XRES + x;\r
+\r
+ xl = v0->x;\r
+ xr = v1->x;\r
+ dy = v2->y - v0->y;\r
+ dxl = v2->x - v0->x;\r
+ dxr = v2->x - v1->x;\r
+ dxldy = (dxl << 8) / dy;\r
+ dxrdy = (dxr << 8) / dy;\r
+\r
+ while(y++ < endy) {\r
+ len = (xr - xl) >> 8;\r
+ if(len > 0) memset(fbptr, g3d_curcidx, len);\r
+\r
+ xl += dxldy;\r
+ xr += dxrdy;\r
+ xn = xl >> 8;\r
+ fbptr += XRES + (xn - x);\r
+ x = xn;\r
+ }\r
+}\r