3d cube and dirty drawing
[dos_low3d] / src / polyfill.c
index ff62225..ac84ff2 100644 (file)
@@ -10,8 +10,18 @@ void g3d_polyfill(struct g3d_vertex *verts)
 {
        int i, topidx, botidx, mididx;
        int32_t dx, dy, dym;
+       int32_t v01x, v01y, v02x, v02y;
        struct g3d_vertex vtmp;
 
+       /* calculate winding */
+       v01x = verts[1].x - verts[0].x;
+       v01y = verts[1].y - verts[0].y;
+       v02x = verts[2].x - verts[0].x;
+       v02y = verts[2].y - verts[0].y;
+       if(!((v01x * v02y - v02x * v01y) & 0x80000000)) {
+               return;
+       }
+
        topidx = botidx = 0;
        for(i=1; i<3; i++) {
                if(verts[i].y < verts[topidx].y) {
@@ -21,8 +31,10 @@ void g3d_polyfill(struct g3d_vertex *verts)
                        botidx = i;
                }
        }
-       mididx = (topidx + 1) % 3;
-       if(mididx == botidx) mididx = (mididx + 1) % 3;
+       mididx = topidx + 1; if(mididx > 2) mididx = 0;
+       if(mididx == botidx) {
+               if(++mididx > 2) mididx = 0;
+       }
 
        dy = verts[botidx].y - verts[topidx].y;
        if(dy == 0) return;
@@ -43,8 +55,9 @@ void g3d_polyfill(struct g3d_vertex *verts)
 static void filltop(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_vertex *v2)
 {
        struct g3d_vertex *vtmp;
-       int x, xn, y, endy, len;
-       int32_t xl, xr, dxl, dxr, dxldy, dxrdy, dy;
+       int x, xn, line, lasty, len;
+       int32_t xl, xr, dxl, dxr, slopel, sloper, dy;
+       int32_t y0, y1, yoffs;
        unsigned char *fbptr;
 
        if(v1->x > v2->x) {
@@ -53,39 +66,45 @@ static void filltop(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_ver
                v2 = vtmp;
        }
 
-       y = v0->y >> 8;
-       endy = v1->y >> 8;
-       if(endy > YRES) endy = YRES;
-       x = v0->x >> 8;
-
-       fbptr = g3d_fbpixels + y * XRES + x;
-
-       xl = xr = v0->x;
        dy = v1->y - v0->y;
        dxl = v1->x - v0->x;
        dxr = v2->x - v0->x;
-       dxldy = (dxl << 8) / dy;
-       dxrdy = (dxr << 8) / dy;
+       slopel = (dxl << 8) / dy;
+       sloper = (dxr << 8) / dy;
+
+       y0 = (v0->y + 0x100) & 0xffffff00;      /* start from the next scanline */
+       yoffs = y0 - v0->y;                                     /* offset of the next scanline */
+       xl = v0->x + ((yoffs * slopel) >> 8);
+       xr = v0->x + ((yoffs * sloper) >> 8);
+
+       line = y0 >> 8;
+       lasty = v1->y >> 8;
+       if(lasty >= YRES) lasty = YRES - 1;
+       x = xl >> 8;
 
-       while(y++ < endy) {
-               if(y > 0) {
-                       len = (xr - xl) >> 8;
+       fbptr = g3d_fbpixels + line * XRES + x;
+
+       while(line <= lasty) {
+               if(line >= 0) {
+                       len = ((xr + 0x100) >> 8) - (xl >> 8);
                        if(len > 0) memset(fbptr, g3d_curcidx, len);
                }
 
-               xl += dxldy;
-               xr += dxrdy;
+               xl += slopel;
+               xr += sloper;
                xn = xl >> 8;
                fbptr += XRES + (xn - x);
                x = xn;
+               line++;
        }
 }
 
 static void fillbot(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_vertex *v2)
 {
        struct g3d_vertex *vtmp;
-       int x, xn, y, endy, len;
-       int32_t xl, xr, dxl, dxr, dxldy, dxrdy, dy;
+       int x, xn, line, lasty, len;
+       int32_t xl, xr, dxl, dxr, slopel, sloper, dy;
+       int32_t y0, y1, yoffs;
        unsigned char *fbptr;
 
        if(v0->x > v1->x) {
@@ -94,31 +113,35 @@ static void fillbot(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_ver
                v1 = vtmp;
        }
 
-       y = v0->y >> 8;
-       endy = v2->y >> 8;
-       if(endy > YRES) endy = YRES;
-       x = v0->x >> 8;
-
-       fbptr = g3d_fbpixels + y * XRES + x;
-
-       xl = v0->x;
-       xr = v1->x;
        dy = v2->y - v0->y;
        dxl = v2->x - v0->x;
        dxr = v2->x - v1->x;
-       dxldy = (dxl << 8) / dy;
-       dxrdy = (dxr << 8) / dy;
+       slopel = (dxl << 8) / dy;
+       sloper = (dxr << 8) / dy;
+
+       y0 = (v0->y + 0x100) & 0xffffff00;      /* start from the next scanline */
+       yoffs = y0 - v0->y;                                     /* offset of the next scanline */
+       xl = v0->x + ((yoffs * slopel) >> 8);
+       xr = v1->x + ((yoffs * sloper) >> 8);
+
+       line = y0 >> 8;
+       lasty = v2->y >> 8;
+       if(lasty >= YRES) lasty = YRES - 1;
+       x = xl >> 8;
+
+       fbptr = g3d_fbpixels + line * XRES + x;
 
-       while(y++ < endy) {
-               if(y > 0) {
-                       len = (xr - xl) >> 8;
+       while(line <= lasty) {
+               if(line >= 0) {
+                       len = ((xr + 0x100) >> 8) - (xl >> 8);
                        if(len > 0) memset(fbptr, g3d_curcidx, len);
                }
 
-               xl += dxldy;
-               xr += dxrdy;
+               xl += slopel;
+               xr += sloper;
                xn = xl >> 8;
                fbptr += XRES + (xn - x);
                x = xn;
+               line++;
        }
 }