#define MIN( a, b ) ( (a)<(b)?(a):(b) )
#define MAX( a, b ) ( (a)>(b)?(a):(b) )
#define ABS( a ) ( (a)<0?-(a):(a) )
#define FABS( a ) ( (a)<0.0?-(a):(a) )
#define LIMIT( v, min, max ) ( (v)>(max)?(max):((v)<(min)?(min):v) )
#define IN_RANGE( val, MIN, MAX ) ( ( MIN <= val && MAX >= val ) ? 1 : 0 )
#define OUT_OF_RANGE( val, MIN, MAX ) ( ( MIN <= val && MAX >= val ) ? 0 : ( ( MIN > val ) ? -1 : 1 ) )
class IMAGE;
typedef u16 COLOUR;
/*! \class IMAGE
\brief This is the interface used in drawPoly.
*/
class IMAGE
{
public:
void set_pixel (int x, int y, COLOUR colour);
u32 get_width (void) const;
u32 get_height (void) const;
};
class SCANLINE_BOUNDARY
{
public:
SCANLINE_BOUNDARY (u32 *minx, u32 *maxx, u32 height)
: minx_ (minx), maxx_ (maxx), height_ (height) {}
void set_pixel (int x, int y, COLOUR)
{
if (minx_ && maxx_ && (y >= 0) && (y < height_))
{
minx_[y] = MIN (minx_[y], x);
maxx_[y] = MAX (maxx_[y], x);
}
}
private:
u32 height_;
u32 *minx_;
u32 *maxx_;
};
class POINT
{
public:
int get_x() {return 1;}
int get_y() { return 1;}
};
void drawPoly (IMAGE &img, const POINT &p1, const POINT &p2, const POINT &p3, COLOUR colour);
template <class T>
void draw_line(T &image, POINT p1, POINT p2, COLOUR color);
/*!
Draws a texture mapped polygon to img.
\param img Destination image
\param points KPoint*[npoints]
\param npoints Number of points in 'points' parameter.
*/
void drawPoly (IMAGE &img, const POINT &p1, const POINT &p2, const POINT &p3, COLOUR colour)
{
// minx and maxx could be changed to dynamically allocated arrays, but
// I opted for stack allocated arrays.
const int MAX_IMAGE_HEIGHT = 512;
u32 minx [MAX_IMAGE_HEIGHT];
u32 maxx [MAX_IMAGE_HEIGHT];
u32 miny = img.get_height();
u32 maxy = 0;
// >
// Initialize min/max in such a way that nothing will be drawn for each line
// >
for ( int i = 0; i < img.get_height(); i ++ )
{
minx[i] = img.get_width();
maxx[i] = 0;
}
SCANLINE_BOUNDARY boundary (minx, maxx, img.get_height());
draw_line(boundary, p1, p2, colour);
draw_line (boundary, p2, p3, colour);
draw_line (boundary, p3, p1, colour);
// >
// Render shape using min/max values created when drawing the lines.
// >
for ( u32 y = miny; y <= maxy; y ++ )
{
for ( u32 x = minx[y]; x <= maxx[y]; x++ )
{
img.set_pixel((int)x,(int)y, colour);
}
}
}
template <class T>
void draw_line(T &image, POINT p1, POINT p2, COLOUR color) {
int x = p1.get_x();
int y = p1.get_y();
int x2 = p2.get_x();
int y2 = p2.get_y();
int w = x2 - x ;
int h = y2 - y ;
int dx1 = 0, dy1 = 0, dx2 = 0, dy2 = 0 ;
if (w<0) dx1 = -1 ; else if (w>0) dx1 = 1 ;
if (h<0) dy1 = -1 ; else if (h>0) dy1 = 1 ;
if (w<0) dx2 = -1 ; else if (w>0) dx2 = 1 ;
int longest = ABS(w) ;
int shortest = ABS(h) ;
if (!(longest>shortest)) {
longest = ABS(h) ;
shortest = ABS(w) ;
if (h<0) dy2 = -1 ; else if (h>0) dy2 = 1 ;
dx2 = 0 ;
}
int numerator = longest >> 1 ;
for (int i=0;i<=longest;i++) {
image.set_pixel(x,y,color) ;
numerator += shortest ;
if (!(numerator<longest)) {
numerator -= longest ;
x += dx1 ;
y += dy1 ;
} else {
x += dx2 ;
y += dy2 ;
}
}
} |