diff --git a/source/core/include/math/dvc_fix_point.h b/source/core/include/math/dvc_fix_point.h index 2b26028..fa3ca3a 100644 --- a/source/core/include/math/dvc_fix_point.h +++ b/source/core/include/math/dvc_fix_point.h @@ -415,6 +415,7 @@ struct iFloat2 iFloat2() : x(0), y(0) {} iFloat2(const iFloat2& other) : x(other.x), y(other.y) {} iFloat2(float32_t _x, float32_t _y) : x(_x), y(_y) {} + iFloat2(iFloat _x, iFloat _y) : x(_x), y(_y) {} }; struct iFloat3 diff --git a/source/core/include/pipe/dvc_rasterizer.h b/source/core/include/pipe/dvc_rasterizer.h index b399ff3..208810e 100644 --- a/source/core/include/pipe/dvc_rasterizer.h +++ b/source/core/include/pipe/dvc_rasterizer.h @@ -42,8 +42,8 @@ public: //Scaleline algorithm static void drawTriangleScanline(int32_t canvasWidth, int32_t canvasHeight, - const fVector3& v0, const fVector3& v1, const fVector3& v2, - DrawTriangleCallback callback); + const fVector2& v0, const fVector2& v1, const fVector2& v2, + DrawTriangleCallback callback, bool ccw = true); }; DV_CORE_END_NAMESPACE diff --git a/source/core/source/pipe/dvc_rasterizer_triangle.cpp b/source/core/source/pipe/dvc_rasterizer_triangle.cpp index 1ce8d2d..878ca0c 100644 --- a/source/core/source/pipe/dvc_rasterizer_triangle.cpp +++ b/source/core/source/pipe/dvc_rasterizer_triangle.cpp @@ -544,58 +544,80 @@ void Rasterizer::drawTriangleLarrabee(int32_t canvasWidth, int32_t canvasHeight, } //------------------------------------------------------------------------------------- -void Rasterizer::drawTriangleScanline(int32_t canvasWidth, int32_t canvasHeight, const fVector3& v0, const fVector3& v1, const fVector3& v2, DrawTriangleCallback callback) +void Rasterizer::drawTriangleScanline(int32_t canvasWidth, int32_t canvasHeight, + const fVector2& _v0, const fVector2& _v1, const fVector2& _v2, + DrawTriangleCallback callback, bool ccw) { -#if 0 - //back cull - fVector3 edge0 = v2 - v1; - fVector3 edge1 = v0 - v2; - fVector3 vnormal = edge0.crossProduct(edge1); - if (vnormal.z > 0) return; + //Whether the three input vertices are in the agreed clockwise order or not, + // it indicates that the triangle is invisible + bool isCCW = (_v1 - _v0).crossProduct(_v2 - _v1) > 0; + if (isCCW != ccw) return; - fVector3 edge2 = v1 - v0; + fVector2 v[3]; + v[0] = _v0; + v[1] = ccw ? _v1 : _v2; + v[2] = ccw ? _v2 : _v1; - float xmin = MathUtil::min3(v0.x, v1.x, v2.x); - float ymin = MathUtil::min3(v0.y, v1.y, v2.y); - float xmax = MathUtil::max3(v0.x, v1.x, v2.x); - float ymax = MathUtil::max3(v0.y, v1.y, v2.y); - - float area = _edge(v0, v1, v2); + float32_t xmin = MathUtil::min3(v[0].x, v[1].x, v[2].x); + float32_t ymin = MathUtil::min3(v[0].y, v[1].y, v[2].y); + float32_t xmax = MathUtil::max3(v[0].x, v[1].x, v[2].x); + float32_t ymax = MathUtil::max3(v[0].y, v[1].y, v[2].y); int32_t x0 = MathUtil::max2(0, (int32_t)std::floor(xmin)); int32_t x1 = MathUtil::min2(canvasWidth - 1, (int32_t)std::floor(xmax)); int32_t y0 = MathUtil::max2(0, (int32_t)std::floor(ymin)); int32_t y1 = MathUtil::min2(canvasHeight - 1, (int32_t)std::floor(ymax)); + float32_t area = (v[1] - v[0]).crossProduct(v[2] - v[1]); + + //edge function + // e(x,y)=(x1-x0)(y-y0)-(y1-y0))(x-x0)=ax+by+c + // a=y0-y1, b=x1-x0, c=(y1-y0)x0-(x1-x0)y0 + + iFloat edge_a[3], edge_b[3], edge_c[3]; + bool edge_tl[3]; //is top-left edge? + + for (int32_t i = 0; i < 3; i++) { + int32_t next = (i + 1) % 3; + iFloat2 v0 = iFloat2(v[i].x, v[i].y); + iFloat2 v1 = iFloat2(v[next].x, v[next].y); + + edge_a[i] = v0.y - v1.y; + edge_b[i] = v1.x - v0.x; + edge_c[i] = (v1.y - v0.y) * v0.x - (v1.x - v0.x) * v0.y; + edge_tl[i] = (edge_a[i] != 0) ? (edge_a[i] > 0) : (edge_b[i] < 0); + } + for (int32_t y = y0; y <= y1; y++) { for (int32_t x = x0; x <= x1; x++) { - fVector3 pixel(x + 0.5f, y + 0.5f, 0.f); + iFloat2 iPixel(iFloat(x) + iFloat::kHalf, iFloat(y) + iFloat::kHalf); - bool overlaps = true; + bool outsideTriangle = false; + for (int32_t i = 0; i < 3; i++) + { + iFloat edge = edge_a[i] * iPixel.x + edge_b[i] * iPixel.y + edge_c[i]; + bool insideEdge = edge.s3132 > 0 || (edge.s3132 == 0 && edge_tl[i]); - float w0 = _edge(v1, v2, pixel); - overlaps &= (w0 == 0 ? ((edge0.y == 0 && edge0.x > 0) || edge0.y > 0) : (w0 > 0)); - if (!overlaps) continue; + if (!insideEdge) { + outsideTriangle = true; + break; + } + } + if (outsideTriangle) { + continue; + } - float w1 = _edge(v2, v0, pixel); - overlaps &= (w1 == 0 ? ((edge1.y == 0 && edge1.x > 0) || edge1.y > 0) : (w1 > 0)); - if (!overlaps) continue; + fVector2 pixel(x + 0.5f, y + 0.5f); + float32_t w0 = (v[2] - v[1]).crossProduct(pixel - v[2]); + float32_t w1 = (v[0] - v[2]).crossProduct(pixel - v[0]); + float32_t w2 = (v[1] - v[0]).crossProduct(pixel - v[1]); - float w2 = _edge(v0, v1, pixel); - overlaps &= (w2 == 0 ? ((edge2.y == 0 && edge2.x > 0) || edge2.y > 0) : (w2 > 0)); - if (!overlaps) continue; - - - fVector3 t = fVector3(w0 / area, w1 / area, w2 / area); - - float invZ = MathUtil::lerp3(v0.z, v1.z, v2.z, t); - t *= fVector3(v0.z / invZ, v1.z / invZ, v2.z / invZ); + fVector3 t = fVector3(w0 / area, (ccw ? w1 : w2) / area, (ccw ? w2 : w1) / area); callback(std::make_pair(x, y), t); } } -#endif } DV_CORE_END_NAMESPACE