/* PrimitiveRender.cpp Written by Matthew Fisher Rendering functions for lines and polygons in software. Not very efficent. DrawLine uses integer arithmetic but DrawPolygon doesn't. I decide not to comment these because I intend to rewrite them, but they work good enough under most conditions. */ void PrimitiveRender::DrawSquare(Bitmap &Bmp, const Vec2i &Coords, int Radius, RGBColor InteriorColor, RGBColor BorderColor) { DrawRect(Bmp, Rectangle2i::ConstructFromCenterVariance(Coords, Vec2i(Radius, Radius)), InteriorColor, BorderColor); } void AliasRender::DrawRect(Bitmap &Bmp, const Rectangle2i &Rect, RGBColor InteriorColor, RGBColor BorderColor) { const int Height = Bmp.Height(); const int Width = Bmp.Width(); for(int y = Rect.Min.y; y <= Rect.Max.y; y++) { if(y >= 0 && y < Height) { for(int x = Rect.Min.x; x <= Rect.Max.x; x++) { if(x >= 0 && x < Width) { if(x == Rect.Min.x || x == Rect.Max.x || y == Rect.Min.y || y == Rect.Max.y) { Bmp[y][x] = BorderColor; } else { Bmp[y][x] = InteriorColor; } } } } } } void AliasRender::DrawTransparentRect(Bitmap &Bmp, const Rectangle2i &Rect, RGBColor InteriorColor, RGBColor BorderColor) { const int Height = Bmp.Height(); const int Width = Bmp.Width(); for(int y = Rect.Min.y; y <= Rect.Max.y; y++) { if(y >= 0 && y < Height) { for(int x = Rect.Min.x; x <= Rect.Max.x; x++) { if(x >= 0 && x < Width) { if(x == Rect.Min.x || x == Rect.Max.x || y == Rect.Min.y || y == Rect.Max.y) { Bmp[y][x] = BorderColor; } else { RGBColor &C = Bmp[y][x]; C = RGBColor(int(C.r) * InteriorColor.r / 255, int(C.g) * InteriorColor.g / 255, int(C.b) * InteriorColor.b / 255); } } } } } } void AliasRender::DrawCircle(Bitmap &Bmp, const Vec2i &Coords, int Radius, RGBColor Color) { const int Height = Bmp.Height(); const int Width = Bmp.Width(); const int RadiusSq = Radius * Radius; for(int y = -Radius; y <= Radius; y++) { int BmpY = y + Coords.y; if(BmpY >= 0 && BmpY < Height) { int ySq = y * y; for(int x = -Radius; x <= Radius; x++) { int BmpX = x + Coords.x; if(BmpX >= 0 && BmpX < Width && ySq + x * x < RadiusSq) { Bmp[BmpY][BmpX] = Color; } } } } } void AliasRender::DrawLine(Bitmap &B, int x1, int y1, int x2, int y2, const RGBColor &Color) { int YSign = 1; if(x2 < x1) { Utility::Swap(x1, x2); Utility::Swap(y1, y2); } if(y2 < y1) { YSign = -1; if(x2 - x1 + y2 - y1 < 0) DrawLineR2(B, x1, y1, x2, y2, Color, YSign); else DrawLineR1(B, x1, y1, x2, y2, Color, YSign); } else { if(x2 - x1 + y1 - y2 < 0) DrawLineR2(B, x1, y1, x2, y2, Color, YSign); else DrawLineR1(B, x1, y1, x2, y2, Color, YSign); } } void AliasRender::DrawLineR1(Bitmap &B, int x1, int y1, int x2, int y2, const RGBColor &Color, int YSign) { int y = y1; int dy = (y2 - y1) * YSign; int dxdy = (y2 - y1) * YSign + x1 - x2; int F = dxdy; int x; for(x = x1;x <= x2;x++) { if(x >= 0 && x < int(B.Width()) && y >= 0 && y < int(B.Height())) B[y][x] = Color; if( F < 0 ) F += dy; else { y += YSign; F += dxdy; } } } void AliasRender::DrawLineR2(Bitmap &B, int x1, int y1, int x2, int y2, const RGBColor &Color, int YSign) { int x = x1; int dx = x2-x1; int dxdy = x2-x1+(y1-y2)*YSign; int F = x2-x1+(y1-y2)*YSign; int y; if(YSign == 1) { for(y = y1;y <= y2;y++) { if(x >= 0 && x < int(B.Width()) && y >= 0 && y < int(B.Height())) B[y][x] = Color; if( F < 0 ) F += dx; else { x++; F += dxdy; } } } else { for(y = y1;y >= y2;y--) { if(x >= 0 && x < int(B.Width()) && y >= 0 && y < int(B.Height())) B[y][x] = Color; if( F < 0 ) F += dx; else { x++; F += dxdy; } } } }