gba-x3dtest

annotate src/polyfill.c @ 6:73b5f2e5d18a

first triangle on screen
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 18 Jun 2014 04:13:02 +0300
parents 850be43b3135
children fb0a0d6a8b52
rev   line source
nuclear@5 1 #include "config.h"
nuclear@5 2 #include <string.h>
nuclear@6 3 #include <assert.h>
nuclear@5 4 #include "polyfill.h"
nuclear@5 5 #include "fixed.h"
nuclear@5 6 #include "gbasys.h"
nuclear@5 7
nuclear@5 8 static void fill_scanline(int y, int x0, int x1, uint16_t color);
nuclear@5 9
nuclear@5 10 void draw_poly(int num, const pvec3 *verts, uint16_t color)
nuclear@5 11 {
nuclear@5 12 int i, topidx = 0, botidx = 0;
nuclear@5 13 int lidx[2], ridx[2];
nuclear@5 14 int32_t y, topy, boty;
nuclear@5 15 int32_t ldy, rdy, ldxdy, rdxdy;
nuclear@5 16 int32_t lx, rx;
nuclear@5 17 int start, end;
nuclear@5 18
nuclear@5 19 topy = boty = verts[0].y;
nuclear@5 20 for(i=1; i<num; i++) {
nuclear@5 21 int32_t y = verts[i].y;
nuclear@5 22 if(y < topy) {
nuclear@5 23 topy = y;
nuclear@5 24 topidx = i;
nuclear@5 25 }
nuclear@5 26 if(y > boty) {
nuclear@5 27 boty = y;
nuclear@5 28 botidx = i;
nuclear@5 29 }
nuclear@5 30 }
nuclear@5 31
nuclear@5 32 lidx[0] = ridx[0] = topidx;
nuclear@5 33 lidx[1] = topidx ? topidx - 1 : num - 1;
nuclear@5 34 ridx[1] = (topidx + 1) % num;
nuclear@5 35
nuclear@6 36 if(verts[ridx[1]].x < verts[lidx[1]].x) {
nuclear@5 37 return; /* backface (CCW) */
nuclear@5 38 }
nuclear@5 39
nuclear@5 40 lx = rx = verts[lidx[0]].x;
nuclear@5 41
nuclear@6 42 /* TODO handle ldy == 0 or rdy == 0 */
nuclear@5 43 ldy = verts[lidx[1]].y - verts[lidx[0]].y;
nuclear@5 44 ldxdy = x16div(verts[lidx[1]].x - lx, ldy);
nuclear@5 45
nuclear@6 46 rdy = verts[ridx[1]].y - verts[ridx[0]].y;
nuclear@5 47 rdxdy = x16div(verts[ridx[1]].x - rx, rdy);
nuclear@5 48
nuclear@5 49 start = topy >> 16;
nuclear@5 50 end = boty >> 16;
nuclear@5 51
nuclear@6 52 if(end >= HEIGHT) end = HEIGHT - 1;
nuclear@6 53
nuclear@5 54 y = topy;
nuclear@5 55 for(i=start; i<end; i++) {
nuclear@5 56 unsigned short x0, x1;
nuclear@5 57
nuclear@5 58 x0 = lx < 0 ? 0 : (lx >> 16);
nuclear@6 59 x1 = (rx >> 16) >= WIDTH ? WIDTH - 1 : (rx >> 16);
nuclear@5 60
nuclear@6 61 if(i >= 0 && x1 > x0) {
nuclear@6 62 fill_scanline(i, x0, x1, color);
nuclear@6 63 }
nuclear@5 64
nuclear@5 65 if(y >= verts[lidx[1]].y) {
nuclear@5 66 lidx[0] = lidx[1];
nuclear@5 67 lidx[1] = lidx[1] ? lidx[1] - 1 : num - 1;
nuclear@5 68 ldy = verts[lidx[1]].y - verts[lidx[0]].y;
nuclear@5 69 if(ldy < 0) {
nuclear@5 70 break;
nuclear@5 71 }
nuclear@5 72 ldxdy = x16div(verts[lidx[1]].x - lx, ldy);
nuclear@5 73 }
nuclear@5 74 if(y >= verts[ridx[1]].y) {
nuclear@5 75 ridx[0] = ridx[1];
nuclear@5 76 ridx[1] = (ridx[1] + 1) % num;
nuclear@5 77 rdy = verts[ridx[1]].y - verts[ridx[0]].y;
nuclear@5 78 if(rdy < 0) {
nuclear@5 79 break;
nuclear@5 80 }
nuclear@5 81 rdxdy = x16div(verts[ridx[1]].x - rx, rdy);
nuclear@5 82 }
nuclear@5 83
nuclear@5 84 lx += ldxdy;
nuclear@5 85 rx += rdxdy;
nuclear@6 86 y += 65536;
nuclear@5 87 }
nuclear@5 88 }
nuclear@5 89
nuclear@5 90 static void fill_scanline(int y, int x0, int x1, uint16_t color)
nuclear@5 91 {
nuclear@5 92 int i;
nuclear@5 93 uint16_t *pixels = (uint16_t*)back_buffer->pixels + y * WIDTH + x0;
nuclear@5 94
nuclear@5 95 for(i=x0; i<x1; i++) {
nuclear@5 96 *pixels++ = color;
nuclear@5 97 }
nuclear@5 98 }