136
136

Reputation: 1207

C++ 2D Graphics: Flat Bottom Triangle Rasterization

I'm trying to build a simple 2D application on the Windows Console using C++ to display various primitives so I started with the most basic one: a triangle. I can display the triangle's outline and vertices correctly but I'm having problems with filling it. I have come across some rasterization algorithms presented here: http://www.sunshine2k.de/coding/java/TriangleRasterization/TriangleRasterization.html and decided I would go for the first approach. I copied the code for the flat bottom triangle case, however this doesn't appear to work correctly on my application and I have no idea what's the cause of the problem.

My result:

My result

main()

screen.fillFlatBottomTriangle(30,10, 10, 140/4, 256/2, 140/4, block_char, FG_CYAN);
screen.drawTriangle(30,10, 10, 140/4, 256/2, 140/4, block_char, BG_DARK_GREY);

screen.drawPixel(30,10,block_char,FG_RED);
screen.drawPixel(10,140/4,block_char,FG_GREEN);
screen.drawPixel(256/2,140/4,block_char,FG_MAGENTA);

fillFlatBottomTriangle

//http://www.sunshine2k.de/coding/java/TriangleRasterization/TriangleRasterization.html
void Screen::fillFlatBottomTriangle(int x1, int y1, int x2, int y2, int x3, int y3, short character, short color)
{
    float invslope1 = (x2 - x1) / (y2 - y1);
    float invslope2 = (x3 - x1) / (y3 - y1);

    float curx1 = x1;
    float curx2 = x1;

    for (int scanlineY = y1; scanlineY <= y2; scanlineY++)
    {
        this->drawLine((int)curx1, scanlineY, (int)curx2, scanlineY, character, color);
        curx1 += invslope1;
        curx2 += invslope2;
    }
}

drawLine

// https://en.wikipedia.org/wiki/Digital_differential_analyzer_(graphics_algorithm)
void Screen::drawLine(int x1, int y1, int x2, int y2, short character, short color)
{
    float delta_x = x2 - x1;
    float delta_y = y2 - y1;
    float step;

    if (abs(delta_x) >= abs(delta_y))
        step = abs(delta_x);
    else 
        step = abs(delta_y);

    
    delta_x = delta_x / step;
    delta_y = delta_y / step;
    

    float x = x1;
    float y = y1;

    for (int i = 1; i <= step; i++)
    {
        this->drawPixel((int)x, (int)y, character, color);
        x += delta_x;
        y += delta_y;
    }
}

DrawTriangle

void Screen::drawTriangle(int x1, int y1, int x2, int y2, int x3, int y3, short character, short color)
{
    this->drawLine(x1,y1, x2, y2, character, color);
    this->drawLine(x1,y1, x3, y3, character, color);
    this->drawLine(x2,y2, x3, y3, character, color);
}

Upvotes: 2

Views: 630

Answers (1)

Cem
Cem

Reputation: 1296

See this part: (x2 - x1) / (y2 - y1)

Since all variables here are integers, this is integer division. That is, result of the division is being rounded towards 0. Assigning the result to a float doesn't change that.

To make this float division, you should convert at least one of the operands to float: (x2 - x1) / (float) (y2 - y1)

Your current code rounds one of the inverse slopes to 0, resulting in the vertical line at the left side. x values at the other side also don't increase fast enough, since that part was also rounded below.

Upvotes: 5

Related Questions