From: John Tsiombikas Date: Mon, 15 Mar 2021 08:33:33 +0000 (+0200) Subject: grid axes X-Git-Tag: v1.0~8 X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=gba_blender;a=commitdiff_plain;h=c702b53199b0daae33e67b0d398b460995cd374e grid axes --- diff --git a/src/main.c b/src/main.c index d5dc096..a519dc0 100644 --- a/src/main.c +++ b/src/main.c @@ -38,6 +38,31 @@ extern unsigned char bgimg_pixels[]; static int32_t cam_theta = 0x10000, cam_phi = -0x8000; +static int show_obj = 1, show_del; + +#define AXIS0 0x10000 +#define AXIS1 0x80000 + +static struct xvertex gridaxes[] = { + {AXIS0, 0, 0, 0, 0, 0, 92}, + {AXIS1, 0, 0, 0, 0, 0, 92}, + {-AXIS0, 0, 0, 0, 0, 0, 92}, + {-AXIS1, 0, 0, 0, 0, 0, 92}, + {0, 0, AXIS0, 0, 0, 0, 93}, + {0, 0, AXIS1, 0, 0, 0, 93}, + {0, 0, -AXIS0, 0, 0, 0, 93}, + {0, 0, -AXIS1, 0, 0, 0, 93}, + + {0, 0, 0, 0, 0, 0, 92}, + {AXIS1, 0, 0, 0, 0, 0, 92}, + {0, 0, 0, 0, 0, 0, 92}, + {-AXIS1, 0, 0, 0, 0, 0, 92}, + {0, 0, 0, 0, 0, 0, 93}, + {0, 0, AXIS1, 0, 0, 0, 93}, + {0, 0, -0, 0, 0, 0, 93}, + {0, 0, -AXIS1, 0, 0, 0, 93}, +}; + int main(void) { int i; @@ -91,8 +116,38 @@ int main(void) xgl_translate(0, 0, 8 << 16); xgl_rotate_x(cam_phi); xgl_rotate_y(cam_theta); -// xgl_draw(XGL_QUADS, cube, sizeof cube / sizeof *cube); - xgl_draw(XGL_TRIANGLES, suzanne, sizeof suzanne / sizeof *suzanne); + + if(show_obj) { + if(cam_theta < X_PI) { + xgl_draw(XGL_LINES, gridaxes + 2, 2); /* -X */ + } else { + xgl_draw(XGL_LINES, gridaxes, 2); /* +X */ + } + if(cam_theta < X_HPI || cam_theta > (3 * X_HPI)) { + xgl_draw(XGL_LINES, gridaxes + 4, 2); /* +Z */ + } else { + xgl_draw(XGL_LINES, gridaxes + 6, 2); /* -Z */ + } + + if(show_obj == 1) { + xgl_draw(XGL_QUADS, cube, sizeof cube / sizeof *cube); + } else { + xgl_draw(XGL_TRIANGLES, suzanne, sizeof suzanne / sizeof *suzanne); + } + + if(cam_theta < X_PI) { + xgl_draw(XGL_LINES, gridaxes, 2); /* +X */ + } else { + xgl_draw(XGL_LINES, gridaxes + 2, 2); /* -X */ + } + if(cam_theta < X_HPI || cam_theta > (3 * X_HPI)) { + xgl_draw(XGL_LINES, gridaxes + 6, 2); /* -Z */ + } else { + xgl_draw(XGL_LINES, gridaxes + 4, 2); /* +Z */ + } + } else { + xgl_draw(XGL_LINES, gridaxes + 8, 8); + } wait_vblank(); present(backbuf); @@ -115,8 +170,26 @@ static void handle_keys(void) } if(KEYPRESS(KEY_LEFT)) { cam_theta += 0x2000; + if(cam_theta > X_2PI) cam_theta -= X_2PI; } if(KEYPRESS(KEY_RIGHT)) { cam_theta -= 0x2000; + if(cam_theta < 0) cam_theta += X_2PI; + } + if(KEYPRESS(KEY_RT)) { + if(++show_obj > 2) show_obj = 0; + } + if(KEYPRESS(KEY_LT)) { + if(--show_obj < 0) show_obj = 2; + } + + if(KEYPRESS(KEY_A)) { + show_del ^= 1; + } + if(KEYPRESS(KEY_B)) { + if(show_del) { + show_obj = 0; + show_del = 0; + } } } diff --git a/src/polyfill.c b/src/polyfill.c index a068295..11e70fd 100644 --- a/src/polyfill.c +++ b/src/polyfill.c @@ -97,3 +97,148 @@ void polyfill_flat(struct pvertex *varr, int vnum, unsigned char col) fbptr += fbwidth; } } + + +/* ----- line drawing and clipping ------ */ +enum { + IN = 0, + LEFT = 1, + RIGHT = 2, + TOP = 4, + BOTTOM = 8 +}; + +static int outcode(int x, int y, int xmin, int ymin, int xmax, int ymax) +{ + int code = 0; + + if(x < xmin) { + code |= LEFT; + } else if(x > xmax) { + code |= RIGHT; + } + if(y < ymin) { + code |= TOP; + } else if(y > ymax) { + code |= BOTTOM; + } + return code; +} + +#define FIXMUL(a, b) (((a) * (b)) >> 8) +#define FIXDIV(a, b) (((a) << 8) / (b)) + +#define LERP(a, b, t) ((a) + FIXMUL((b) - (a), (t))) + +int clip_line(int *x0, int *y0, int *x1, int *y1, int xmin, int ymin, int xmax, int ymax) +{ + int oc_out; + + int oc0 = outcode(*x0, *y0, xmin, ymin, xmax, ymax); + int oc1 = outcode(*x1, *y1, xmin, ymin, xmax, ymax); + + long fx0, fy0, fx1, fy1, fxmin, fymin, fxmax, fymax; + + if(!(oc0 | oc1)) return 1; /* both points are inside */ + + fx0 = *x0 << 8; + fy0 = *y0 << 8; + fx1 = *x1 << 8; + fy1 = *y1 << 8; + fxmin = xmin << 8; + fymin = ymin << 8; + fxmax = xmax << 8; + fymax = ymax << 8; + + for(;;) { + long x, y, t; + + if(oc0 & oc1) return 0; /* both have points with the same outbit, not visible */ + if(!(oc0 | oc1)) break; /* both points are inside */ + + oc_out = oc0 ? oc0 : oc1; + + if(oc_out & TOP) { + t = FIXDIV(fymin - fy0, fy1 - fy0); + x = LERP(fx0, fx1, t); + y = fymin; + } else if(oc_out & BOTTOM) { + t = FIXDIV(fymax - fy0, fy1 - fy0); + x = LERP(fx0, fx1, t); + y = fymax; + } else if(oc_out & LEFT) { + t = FIXDIV(fxmin - fx0, fx1 - fx0); + x = fxmin; + y = LERP(fy0, fy1, t); + } else {/*if(oc_out & RIGHT) {*/ + t = FIXDIV(fxmax - fx0, fx1 - fx0); + x = fxmax; + y = LERP(fy0, fy1, t); + } + + if(oc_out == oc0) { + fx0 = x; + fy0 = y; + oc0 = outcode(fx0 >> 8, fy0 >> 8, xmin, ymin, xmax, ymax); + } else { + fx1 = x; + fy1 = y; + oc1 = outcode(fx1 >> 8, fy1 >> 8, xmin, ymin, xmax, ymax); + } + } + + *x0 = fx0 >> 8; + *y0 = fy0 >> 8; + *x1 = fx1 >> 8; + *y1 = fy1 >> 8; + return 1; +} + +void draw_line(int x0, int y0, int x1, int y1, unsigned short color) +{ + int i, dx, dy, x_inc, y_inc, error; + unsigned char *fbptr = fb; + + fbptr += y0 * fbwidth + x0; + + dx = x1 - x0; + dy = y1 - y0; + + if(dx >= 0) { + x_inc = 1; + } else { + x_inc = -1; + dx = -dx; + } + if(dy >= 0) { + y_inc = fbwidth; + } else { + y_inc = -fbwidth; + dy = -dy; + } + + if(dx > dy) { + error = dy * 2 - dx; + for(i=0; i<=dx; i++) { + *fbptr = color; + if(error >= 0) { + error -= dx * 2; + fbptr += y_inc; + } + error += dy * 2; + fbptr += x_inc; + } + } else { + error = dx * 2 - dy; + for(i=0; i<=dy; i++) { + *fbptr = color; + if(error >= 0) { + error -= dy * 2; + fbptr += x_inc; + } + error += dx * 2; + fbptr += y_inc; + } + } +} + diff --git a/src/polyfill.h b/src/polyfill.h index d637046..88166cf 100644 --- a/src/polyfill.h +++ b/src/polyfill.h @@ -27,4 +27,7 @@ struct pvertex { void polyfill_framebuffer(unsigned char *fb, int width, int height); void polyfill_flat(struct pvertex *v, int vnum, unsigned char col); +int clip_line(int *x0, int *y0, int *x1, int *y1, int xmin, int ymin, int xmax, int ymax); +void draw_line(int x0, int y0, int x1, int y1, unsigned short color); + #endif /* POLYFILL_H_ */ diff --git a/src/xgl.c b/src/xgl.c index 6277ce5..4880aba 100644 --- a/src/xgl.c +++ b/src/xgl.c @@ -29,6 +29,9 @@ static int mtop; static unsigned int opt; static int32_t ldir[3]; +static void draw_ptlines(int prim, const struct xvertex *varr, int vcount); + + void xgl_init(void) { xgl_viewport(0, 0, 240, 160); @@ -190,6 +193,11 @@ void xgl_draw(int prim, const struct xvertex *varr, int vcount) struct pvertex pv[4]; int32_t ndotl; + if(prim < 3) { + draw_ptlines(prim, varr, vcount); + return; + } + while(vcount >= prim) { cidx = varr->cidx; @@ -234,3 +242,28 @@ void xgl_draw(int prim, const struct xvertex *varr, int vcount) polyfill_flat(pv, prim, cidx); } } + +static void draw_ptlines(int prim, const struct xvertex *varr, int vcount) +{ + int i; + struct xvertex xv[2]; + + while(vcount >= prim) { + for(i=0; i> 8); /* assume aspect: ~2 */ + xv[i].y = (xv[i].y << 2) / (xv[i].z >> 8); /* the shift is * PROJ_D */ + /* projection result is 24.8 */ + /* viewport */ + xv[i].x = ((((xv[i].x + 0x100) >> 1) * vp[2]) >> 8) + vp[0]; + xv[i].y = ((((0x100 - xv[i].y) >> 1) * vp[3]) >> 8) + vp[1]; + varr++; + } + vcount -= prim; + + /* line clipping */ + clip_line((int*)&xv[0].x, (int*)&xv[0].y, (int*)&xv[1].x, (int*)&xv[1].y, vp[0], vp[1], vp[2] - 1, vp[3] - 1); + draw_line(xv[0].x, xv[0].y, xv[1].x, xv[1].y, varr[-2].cidx); + } +}