private void SetPixel(Triangle triangle, int x, int y, Color color) { if (0 <= x && x < canvas.Width && 0 <= y && y < canvas.Height) { double w0, w1, w2; (w0, w1, w2) = triangle.GetWeights(x, y); double z = triangle.Z(w0, w1, w2); if (z >= zBuffor[x, y]) { zBuffor[x, y] = z; canvas.SetPixel(x, y, color); } } }
public void Fill(IModel model, Triangle triangle) { var indexes = triangle.GetSortedIndexes(); var AET = new List <AETNode>(); int k = 0; Vector <double> N = null; Color constantColor = Color.Empty; Color[] gouraudColors = null; if (model is Cuboid) { N = (model as Cuboid).N(triangle); } switch (shaderType) { case ShaderType.Constant: { var coordinates = Vector <double> .Build.Dense(new double[3] { (triangle.points[0].worldX + triangle.points[1].worldX + triangle.points[2].worldX) / 3.0, (triangle.points[0].worldY + triangle.points[1].worldY + triangle.points[2].worldY) / 3.0, (triangle.points[0].worldZ + triangle.points[1].worldZ + triangle.points[2].worldZ) / 3.0 }); N = triangle.InterpolateN(0.333, 0.333, 0.333); constantColor = ColorCalculation.Phong(coordinates, N, model.Color); break; } case ShaderType.Gouraud: { gouraudColors = new Color[3] { ColorCalculation.Phong(triangle.points[0], model.Color), ColorCalculation.Phong(triangle.points[1], model.Color), ColorCalculation.Phong(triangle.points[2], model.Color) }; break; } } int lowerBound = triangle.points[indexes[0]].projectionY; int upperBound = triangle.points[indexes[2]].projectionY >= canvas.Height ? canvas.Height - 1 : triangle.points[indexes[2]].projectionY; if (lowerBound < 0) { if (upperBound < 0) { return; } lowerBound = 0; AET.Add(new AETNode(triangle.points[indexes[2]], triangle.points[indexes[0]])); if (triangle.points[indexes[1]].projectionY < 0) { AET.Add(new AETNode(triangle.points[indexes[1]], triangle.points[indexes[2]])); k = 2; } else { AET.Add(new AETNode(triangle.points[indexes[0]], triangle.points[indexes[1]])); k = 1; } foreach (var aetNode in AET) { aetNode.x += aetNode.xd * -aetNode.p1.projectionY; } AET.Sort((p1, p2) => (int)(p1.x - p2.x)); } for (int y = lowerBound; y <= upperBound; y++) { while (triangle.points[indexes[k]].projectionY == y - 1) { var prev = triangle.points[Triangle.Prev(indexes[k])]; var current = triangle.points[indexes[k]]; var next = triangle.points[Triangle.Next(indexes[k])]; if (prev.projectionY > current.projectionY) { AET.Add(new AETNode(prev, current)); } else { AET.RemoveAll(aetn => aetn.p2.projectionY == current.projectionY); } if (next.projectionY > current.projectionY) { AET.Add(new AETNode(current, next)); } else { AET.RemoveAll(aetn => aetn.p2.projectionY == current.projectionY); } k++; } if (AET.Count > 0 && AET[1].x < AET[0].x) { AET.Add(AET[0]); AET.RemoveAt(0); } for (int i = 0; i < AET.Count; i += 2) { int xLowerBound = (int)AET[i].x >= 0 ? (int)AET[i].x : 0; int xUpperBound = (int)Math.Round(AET[i + 1].x) < canvas.Width ? (int)Math.Round(AET[i + 1].x) : canvas.Width; for (int x = xLowerBound; x < xUpperBound; x++) { double w0, w1, w2; (w0, w1, w2) = triangle.GetWeights(x, y); double z = triangle.Z(w0, w1, w2); if (z >= zBuffor[x, y]) { zBuffor[x, y] = z; switch (shaderType) { case ShaderType.Constant: canvas.SetPixel(x, y, constantColor); break; case ShaderType.Gouraud: Color gouraudColor = ColorCalculation.Gouraud(gouraudColors, w0, w1, w2); canvas.SetPixel(x, y, gouraudColor); break; case ShaderType.Phong: N = triangle.InterpolateN(w0, w1, w2); Color phongColor = ColorCalculation.Phong(triangle.InterpolateXYZ(w0, w1, w2), N, model.Color); canvas.SetPixel(x, y, phongColor); break; } } } } foreach (var aetn in AET) { aetn.x += aetn.xd; } } if (drawTriangleEdges) { DrawLine(triangle, triangle.points[0], triangle.points[1]); DrawLine(triangle, triangle.points[0], triangle.points[2]); DrawLine(triangle, triangle.points[1], triangle.points[2]); } }