nuclear@0: /* nuclear@0: 256-color 3D graphics hack for real-mode DOS. nuclear@0: Copyright (C) 2011 John Tsiombikas nuclear@0: nuclear@0: This program is free software: you can redistribute it and/or modify nuclear@0: it under the terms of the GNU General Public License as published by nuclear@0: the Free Software Foundation, either version 3 of the License, or nuclear@0: (at your option) any later version. nuclear@0: nuclear@0: This program is distributed in the hope that it will be useful, nuclear@0: but WITHOUT ANY WARRANTY; without even the implied warranty of nuclear@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nuclear@0: GNU General Public License for more details. nuclear@0: nuclear@0: You should have received a copy of the GNU General Public License nuclear@0: along with this program. If not, see . nuclear@0: */ nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@9: #include nuclear@0: #include nuclear@0: #include "mingl.h" nuclear@0: #include "mglimpl.h" nuclear@0: nuclear@0: nuclear@0: static struct vertex *vleft, *vright; nuclear@0: static struct framebuffer *fb; nuclear@0: static struct state *st; nuclear@0: nuclear@0: nuclear@0: #define SCAN_EDGE scan_edge_flat nuclear@0: #define SCAN_LINE scan_line_flat nuclear@0: #undef INTERP_DEPTH nuclear@0: #undef INTERP_ENERGY nuclear@3: #undef INTERP_TEX nuclear@0: #include "scantmpl.h" nuclear@0: #undef SCAN_EDGE nuclear@0: #undef SCAN_LINE nuclear@0: nuclear@0: #define SCAN_EDGE scan_edge_z nuclear@0: #define SCAN_LINE scan_line_z nuclear@0: #define INTERP_DEPTH nuclear@0: #undef INTERP_ENERGY nuclear@3: #undef INTERP_TEX nuclear@0: #include "scantmpl.h" nuclear@0: #undef SCAN_EDGE nuclear@0: #undef SCAN_LINE nuclear@0: nuclear@0: #define SCAN_EDGE scan_edge_e nuclear@0: #define SCAN_LINE scan_line_e nuclear@0: #undef INTERP_DEPTH nuclear@0: #define INTERP_ENERGY nuclear@3: #undef INTERP_TEX nuclear@0: #include "scantmpl.h" nuclear@0: #undef SCAN_EDGE nuclear@0: #undef SCAN_LINE nuclear@0: nuclear@0: #define SCAN_EDGE scan_edge_ze nuclear@0: #define SCAN_LINE scan_line_ze nuclear@0: #define INTERP_DEPTH nuclear@0: #define INTERP_ENERGY nuclear@3: #undef INTERP_TEX nuclear@0: #include "scantmpl.h" nuclear@0: #undef SCAN_EDGE nuclear@0: #undef SCAN_LINE nuclear@0: nuclear@3: #define SCAN_EDGE scan_edge_t nuclear@3: #define SCAN_LINE scan_line_t nuclear@3: #undef INTERP_DEPTH nuclear@3: #undef INTERP_ENERGY nuclear@3: #define INTERP_TEX nuclear@3: #include "scantmpl.h" nuclear@3: #undef SCAN_EDGE nuclear@3: #undef SCAN_LINE nuclear@3: nuclear@3: #define SCAN_EDGE scan_edge_zt nuclear@3: #define SCAN_LINE scan_line_zt nuclear@3: #define INTERP_DEPTH nuclear@3: #undef INTERP_ENERGY nuclear@3: #define INTERP_TEX nuclear@3: #include "scantmpl.h" nuclear@3: #undef SCAN_EDGE nuclear@3: #undef SCAN_LINE nuclear@3: nuclear@3: #define SCAN_EDGE scan_edge_et nuclear@3: #define SCAN_LINE scan_line_et nuclear@3: #undef INTERP_DEPTH nuclear@3: #define INTERP_ENERGY nuclear@3: #define INTERP_TEX nuclear@3: #include "scantmpl.h" nuclear@3: #undef SCAN_EDGE nuclear@3: #undef SCAN_LINE nuclear@3: nuclear@3: #define SCAN_EDGE scan_edge_zet nuclear@3: #define SCAN_LINE scan_line_zet nuclear@3: #define INTERP_DEPTH nuclear@3: #define INTERP_ENERGY nuclear@3: #define INTERP_TEX nuclear@3: #include "scantmpl.h" nuclear@3: #undef SCAN_EDGE nuclear@3: #undef SCAN_LINE nuclear@3: nuclear@3: nuclear@0: static void (*scan_edge)(struct vertex*, struct vertex*); nuclear@0: static void (*scan_line)(int, unsigned char*); nuclear@0: nuclear@0: int mgl_rast_init(struct state *state, struct framebuffer *fbuf) nuclear@0: { nuclear@0: fb = fbuf; nuclear@0: st = state; nuclear@0: nuclear@0: if(!(vleft = malloc(fb->height * sizeof *vleft))) { nuclear@0: return -1; nuclear@0: } nuclear@0: if(!(vright = malloc(fb->height * sizeof *vright))) { nuclear@0: free(vleft); nuclear@0: return -1; nuclear@0: } nuclear@0: nuclear@0: scan_edge = scan_edge_flat; nuclear@0: scan_line = scan_line_flat; nuclear@0: nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: void mgl_rast_cleanup(void) nuclear@0: { nuclear@0: free(vleft); nuclear@0: free(vright); nuclear@0: } nuclear@0: nuclear@0: void mgl_rast_prepare(void) nuclear@0: { nuclear@0: static void (*sedge[])(struct vertex*, struct vertex*) = { nuclear@3: /* tez */ nuclear@3: scan_edge_flat, /* 000 */ nuclear@3: scan_edge_z, /* 001 */ nuclear@3: scan_edge_e, /* 010 */ nuclear@3: scan_edge_ze, /* 011 */ nuclear@3: scan_edge_t, /* 100 */ nuclear@3: scan_edge_zt, /* 101 */ nuclear@3: scan_edge_et, /* 110 */ nuclear@3: scan_edge_zet /* 111 */ nuclear@0: }; nuclear@0: static void (*sline[])(int, unsigned char*) = { nuclear@3: /* tez */ nuclear@3: scan_line_flat, /* 000 */ nuclear@3: scan_line_z, /* 001 */ nuclear@3: scan_line_e, /* 010 */ nuclear@3: scan_line_ze, /* 011 */ nuclear@3: scan_line_t, /* 100 */ nuclear@3: scan_line_zt, /* 101 */ nuclear@3: scan_line_et, /* 110 */ nuclear@3: scan_line_zet /* 111 */ nuclear@0: }; nuclear@0: int bits = 0; nuclear@0: nuclear@3: if((st->flags & MGL_TEXTURE_2D) && st->tex.pixels) { nuclear@3: bits |= 4; nuclear@3: } nuclear@0: if(st->flags & MGL_SMOOTH) { nuclear@0: bits |= 2; nuclear@0: } nuclear@0: if((st->flags & MGL_DEPTH_TEST) && fb->zbuf) { nuclear@0: bits |= 1; nuclear@0: } nuclear@0: nuclear@0: scan_edge = sedge[bits]; nuclear@0: scan_line = sline[bits]; nuclear@0: } nuclear@0: nuclear@0: void mgl_draw_point(struct vertex *v) nuclear@0: { nuclear@0: int x = (int)ROUND(v->pos.x); nuclear@0: int y = (int)ROUND(v->pos.y); nuclear@0: nuclear@0: if(x >= 0 && x < fb->width && y >= 0 && y < fb->height) { nuclear@0: int cidx = v->cidx + v->energy * st->col_range; nuclear@0: fb->pixels[y * fb->width + x] = cidx; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: void mgl_draw_line(struct vertex *v0, struct vertex *v1) nuclear@0: { nuclear@0: /* TODO */ nuclear@0: fprintf(stderr, "draw_line unimplemented\n"); nuclear@0: abort(); nuclear@0: } nuclear@0: nuclear@0: void mgl_draw_poly(struct vertex *v, int numv) nuclear@0: { nuclear@0: int ybeg, yend, i; nuclear@0: unsigned char *sline; nuclear@0: nuclear@0: ybeg = fb->height; nuclear@0: yend = 0; nuclear@0: nuclear@0: for(i=0; ipos.y); nuclear@0: nuclear@0: scan_edge(v0, v1); nuclear@0: nuclear@0: if(y > yend) yend = y; nuclear@0: if(y < ybeg) ybeg = y; nuclear@0: } nuclear@0: nuclear@0: if(ybeg < 0) ybeg = 0; nuclear@0: if(yend >= fb->height) yend = fb->height - 1; nuclear@0: nuclear@0: sline = fb->pixels + ybeg * fb->width; nuclear@0: for(i=ybeg; iwidth; nuclear@0: } nuclear@0: }