Code: Select all
/**************************************************************************/
/*!
@brief Draw a triangle with face-shading
@param x0 Vertex #0 x coordinate
@param y0 Vertex #0 y coordinate
@param x1 Vertex #1 x coordinate
@param y1 Vertex #1 y coordinate
@param x2 Vertex #2 x coordinate
@param y2 Vertex #2 y coordinate
@param color0 16-bit 5-6-5 vertex 0
@param color1 16-bit 5-6-5 vertex 1
@param color2 16-bit 5-6-5 vertex 2
*/
/**************************************************************************/
void Adafruit_GFX::shadeTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
int16_t x2, int16_t y2, uint16_t color0, uint16_t color1, uint16_t color2) {
int16_t a, b, y, last;
// Sort coordinates by Y order (y2 >= y1 >= y0)
if (y0 > y1) {
_swap_int16_t(y0, y1);
_swap_int16_t(x0, x1);
_swap_int16_t(color0, color1);
}
if (y1 > y2) {
_swap_int16_t(y2, y1);
_swap_int16_t(x2, x1);
_swap_int16_t(color2, color1);
}
if (y0 > y1) {
_swap_int16_t(y0, y1);
_swap_int16_t(x0, x1);
_swap_int16_t(color0, color1);
}
startWrite();
if (y0 == y2) { // Handle awkward all-on-same-line case as its own thing
a = b = x0;
if (x1 < a)
a = x1;
else if (x1 > b)
b = x1;
if (x2 < a)
a = x2;
else if (x2 > b)
b = x2;
interpolateFastHLine(a, y0, b - a + 1, color);
endWrite();
return;
}
int16_t dx01 = x1 - x0, dy01 = y1 - y0, dx02 = x2 - x0, dy02 = y2 - y0,
dx12 = x2 - x1, dy12 = y2 - y1;
int32_t sa = 0, sb = 0;
// For upper part of triangle, find scanline crossings for segments
// 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1
// is included here (and second loop will be skipped, avoiding a /0
// error there), otherwise scanline y1 is skipped here and handled
// in the second loop...which also avoids a /0 error here if y0=y1
// (flat-topped triangle).
if (y1 == y2)
last = y1; // Include y1 scanline
else
last = y1 - 1; // Skip it
uint16_t midpoint = interpolate(color2,color0,(y1-y0)*32./(y2-y0));
uint16_t colorX = midpoint;
uint16_t colorY = color1;
uint16_t colorZ = color0;
sa += dx01;
sb += dx02;
for (y = y0; y <= last; y++) {
a = x0 + sa / dy01;
b = x0 + sb / dy02;
sa += dx01;
sb += dx02;
/* longhand:
a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
*/
if (a > b) {
_swap_int16_t(a, b);
_swap_int16(colorA, colorB);
}
interpolateFastHLine(a, y, b-a, colorA, colorB);
}
uint16_t colorU = midpoint;
uint16_t colorV = color1;
uint16_t colorW = color2;
// For lower part of triangle, find scanline crossings for segments
// 0-2 and 1-2. This loop is skipped if y1=y2.
sa = (int32_t)dx12 * (y - y1);
sb = (int32_t)dx02 * (y - y0);
for (; y <= y2; y++) {
a = x1 + sa / dy12;
b = x0 + sb / dy02;
sa += dx12;
sb += dx02;
float weight = ((y-y0)*32.)/len2;
uint16_t colorA = interpolate(colorX,colorZ,weight);
uint16_t colorB = interpolate(colorY,colorZ,weight);
/* longhand:
a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
*/
if (a > b) {
_swap_int16_t(a, b);
_swap_int16(colorA, colorB);
}
interpolateFastHLine(a, y, b-a, colorA, colorB);
}
endWrite();
}