0

I'm trying to rasterize three triangles in 3D using scanline method. But after i process all polygons, the quality of edge between adjacent polygons is very poor. Rendered picture:

img

For rasterizing i use scanline method with active edges table. Each scanline intersects only two edges. I store intersection (x,y,z) points and then draw line. For computing intersections i use this class and call update() method for active edges for every new scanline:

public class Edge {
private Point3D start, end;
public double dx = 0, dy = 0, dzX = 0, dzY = 0, currX = 0, currY = 0, currZx = 0, currZy = 0;
private double calcCurrX = 0, calcCurrY = 0, calcCurrZx = 0, calcCurrZy = 0;
private double lx = 0, ly = 0,lz = 0;

public Edge(Point3D start, Point3D end) {
    this.start = new Point3D(start);
    this.end = new Point3D(end);
    reset();
}

public void update(){
    calcCurrX += dx;
    calcCurrZx += dzX;//for drawing scanline slices
    calcCurrZy += dzY;//for use with scanline
    calcCurrY += dy;
    currX = calcCurrX + 0.5;
    currY = calcCurrY + 0.5;
    currZx = calcCurrZx + 0.5;
    currZy = calcCurrZy + 0.5;
}

public Point3D getStart() {
    return start;
}

public void setStart(Point3D start) {
    this.start = start;
    reset();
}

public Point3D getEnd() {
    return end;
}

public void setEnd(Point3D end) {
    this.end = end;
    reset();
}

public void reset(){
    lx = this.end.x - this.start.x;
    ly = this.end.y - this.start.y;
    lz = this.end.z - this.start.z;
    dx = lx / ly;
    dy = ly / ly;
    dzX = lz / lx;
    dzY = lz / ly;

    calcCurrX = this.start.x;// + 0.5 * Math.signum(dx);
    calcCurrZx = this.start.z;// + 0.5 * Math.signum(dzX);
    calcCurrZy = this.start.z;// + 0.5 * Math.signum(dzY);
    calcCurrY = this.start.y;// + 0.5 * Math.signum(dy);
    currX = calcCurrX + 0.5;
    currY = calcCurrY + 0.5;
    currZx = calcCurrZx + 0.5;
    currZy = calcCurrZy + 0.5;
}}

Here is code that loops through all scanlines, computes intersections and draws lines:

int scanlineEnd = (int) edges[0].getEnd().y;
    for (Edge edge : edges) {
        if (scanlineEnd < (int) edge.getEnd().y)
            scanlineEnd = (int) edge.getEnd().y;
    }

    scanlineEnd = Math.min(scanlineEnd, zBuffer[0].length);

    int scanline = (int) edges[0].getStart().y;

    ArrayList<Edge> activeEdges = computeActiveEdges(edges, scanline);

    while (scanline < scanlineEnd){
        if(activeEdges.isEmpty()) break;

        if(scanline == (int) activeEdges.get(0).getEnd().y || scanline == (int) activeEdges.get(1).getEnd().y){
            activeEdges = computeActiveEdges(edges, scanline);
        }

        if (scanline < 0){
            activeEdges.get(0).update();
            activeEdges.get(1).update();
            scanline++;
            continue;
        }

        Point3D start = new Point3D((int) activeEdges.get(0).currX, (int) activeEdges.get(0).currY, (int) activeEdges.get(0).currZy);
        Point3D end = new Point3D((int) activeEdges.get(1).currX, (int) activeEdges.get(1).currY, (int) activeEdges.get(1).currZy);

        if (end.x < start.x) {
            Point3D temp = start;
            start = end;
            end = temp;
        }

        double dzX = 0;
        if ((int) start.x != (int) end.x) {
            dzX = (end.z - start.z) / (end.x - start.x);
        }

        int y = (int) start.y;
        double currZx = start.z;
        //int zMin = findMinZ(coordinatesT), zMax = findMaxZ(coordinatesT);
        for (int x = (int) start.x; x <= (int) end.x; x++) {
            if (x >= 0 && x < zBuffer.length) {
                if (zBuffer[x][y] < (int) currZx) {
                    image.setRGB(x, y, color.getRGB());
                    zBuffer[x][y] = (int) (currZx);
                }
            }
            currZx += dzX; //here i compute z for line that connects two intersection points. I think i'm doing it incorrect
        }
        activeEdges.get(0).update();
        activeEdges.get(1).update();

        scanline++;
    }

How can i get better quality of edges between polygons?

Spektre
  • 49,595
  • 11
  • 110
  • 380
mobimore
  • 21
  • 1
  • 4
  • There may be more reasons (too lazy to analyze your almost uncommented code) 1. wrong interpolation of scanline start/end that is my bet as you are offsetting values by `0.5` but I see nowhere the `-1` in divisors. 2. Inconsistent Z-buffer conditions (but this would imply use of parallelism or heavy optimization which I doubt is the case here) 3. round off errors (as you are on ints you could missed some precision loss easily). – Spektre Nov 14 '16 at 16:05
  • @Spektre 1.Sorry for uncommented code... How can i correct wrong interpolation? Or maybe how can i interpolate correct? 3. I use double and round only before putting pixel on screen. – mobimore Nov 14 '16 at 16:12
  • try to use DDA the interpolation of yours is suspicious but Your code is really hard to read for me (I use very different formating) so I may overlooked something. – Spektre Nov 14 '16 at 20:11
  • see [Algorithm to fill triangle](http://stackoverflow.com/a/39062479/2521214) see functions `troj` and `_troj_line` which renders filled triangle. Have a look at the sublinks there too – Spektre Nov 14 '16 at 20:18
  • @Spektre Thank you for links. As temporary solution, i made this changed this line: for (int x = (int) start.x; x <= (int) end.x; x++) to this: for (int x = (int) start.x; x < (int) end.x; x++) – mobimore Nov 15 '16 at 12:36

0 Answers0