/// <summary> /// 平底,p1为上顶点,p2,p3 /// </summary> /// <param name="p1"></param> /// <param name="p2"></param> /// <param name="p3"></param> private void DrawTriangleBottom(Vertex p1, Vertex p2, Vertex p3) { for (float y = p1.point.y; y <= p2.point.y; y += 0.5f) { int yIndex = (int)(System.Math.Round(y, MidpointRounding.AwayFromZero)); if (yIndex >= 0 && yIndex < this.MaximumSize.Height) { float xl = (y - p1.point.y) * (p2.point.x - p1.point.x) / (p2.point.y - p1.point.y) + p1.point.x; float xr = (y - p1.point.y) * (p3.point.x - p1.point.x) / (p3.point.y - p1.point.y) + p1.point.x; float dy = y - p1.point.y; float t = dy / (p2.point.y - p1.point.y); //插值生成左右顶点 Vertex new1 = new Vertex(); new1.point.x = xl; new1.point.y = y; MathUntil.ScreenSpaceLerpVertex(ref new1, p1, p2, t); // Vertex new2 = new Vertex(); new2.point.x = xr; new2.point.y = y; MathUntil.ScreenSpaceLerpVertex(ref new2, p1, p3, t); //扫描线填充 if (new1.point.x < new2.point.x) { ScanlineFill(new1, new2, yIndex); } else { ScanlineFill(new2, new1, yIndex); } } } }
/// <summary> /// 光栅化三角形 /// </summary> private void TriangleRasterization(Vertex p1, Vertex p2, Vertex p3) { if (p1.point.y == p2.point.y) { if (p1.point.y < p3.point.y) {//平顶 DrawTriangleTop(p1, p2, p3); } else {//平底 DrawTriangleBottom(p3, p1, p2); } } else if (p1.point.y == p3.point.y) { if (p1.point.y < p2.point.y) {//平顶 DrawTriangleTop(p1, p3, p2); } else {//平底 DrawTriangleBottom(p2, p1, p3); } } else if (p2.point.y == p3.point.y) { if (p2.point.y < p1.point.y) {//平顶 DrawTriangleTop(p2, p3, p1); } else {//平底 DrawTriangleBottom(p1, p2, p3); } } else {//分割三角形 Vertex top; Vertex bottom; Vertex middle; if (p1.point.y > p2.point.y && p2.point.y > p3.point.y) { top = p3; middle = p2; bottom = p1; } else if (p3.point.y > p2.point.y && p2.point.y > p1.point.y) { top = p1; middle = p2; bottom = p3; } else if (p2.point.y > p1.point.y && p1.point.y > p3.point.y) { top = p3; middle = p1; bottom = p2; } else if (p3.point.y > p1.point.y && p1.point.y > p2.point.y) { top = p2; middle = p1; bottom = p3; } else if (p1.point.y > p3.point.y && p3.point.y > p2.point.y) { top = p2; middle = p3; bottom = p1; } else if (p2.point.y > p3.point.y && p3.point.y > p1.point.y) { top = p1; middle = p3; bottom = p2; } else { //三点共线 return; } //插值求中间点x float middlex = (middle.point.y - top.point.y) * (bottom.point.x - top.point.x) / (bottom.point.y - top.point.y) + top.point.x; float dy = middle.point.y - top.point.y; float t = dy / (bottom.point.y - top.point.y); //插值生成左右顶点 Vertex newMiddle = new Vertex(); newMiddle.point.x = middlex; newMiddle.point.y = middle.point.y; MathUntil.ScreenSpaceLerpVertex(ref newMiddle, top, bottom, t); //平底 DrawTriangleBottom(top, newMiddle, middle); //平顶 DrawTriangleTop(newMiddle, middle, bottom); } }