private void FillPolygonNormal(List <Edge> edges, double kd, double ks, double m) { List <Edge>[] ET = EdgeBucketSort(edges); int edgesCounter = edges.Count; int y = 0; while (ET[y] == null) { y++; } List <(double yMax, double xMin, double m)> AET = new List <(double, double, double)>(); while (edgesCounter != 0 || AET.Any()) { AET.RemoveAll(x => x.yMax == y); if (ET[y] != null) { foreach (Edge edge in ET[y]) { double mx = ((double)edge.p2.X - (double)edge.p1.X) / ((double)edge.p2.Y - (double)edge.p1.Y); if (edge.p1.Y != edge.p2.Y) { AET.Add((edge.p2.Y, edge.p1.X, mx)); } edgesCounter--; } } AET.Sort((a, b) => a.xMin.CompareTo(b.xMin)); for (int i = 0; i < AET.Count; i += 2) { for (int j = (int)(AET[i].xMin); j < (int)(AET[i + 1].xMin); j++) { Color objectColor = constColor; if (isColorFromTexture) { objectColor = photo[j, y]; } Vector3D normalVector = new Vector3D(0, 0, 1); if (isNormalVectorFromMap) { normalVector = FromNormalMapToVector(normalMap[j, y]); } else if (isNormalVectorFromBubble) { normalVector = GetNormalVectorFromBubble(j, y); } Vector3D newL = CalculateLVector(new Vector3D(j, y, 0)); int R = (int)GetLambertColor(((double)lightColor.R / (double)255), objectColor.R, newL, normalVector, ks, kd, m); int G = (int)GetLambertColor(((double)lightColor.G / (double)255), objectColor.G, newL, normalVector, ks, kd, m); int B = (int)GetLambertColor(((double)lightColor.B / (double)255), objectColor.B, newL, normalVector, ks, kd, m); FixRGB(ref R, ref G, ref B); Color newColor = Color.FromArgb(R, G, B); newPhoto[j, y] = newColor; } } y++; for (int i = 0; i < AET.Count; i++) { AET[i] = (AET[i].yMax, AET[i].xMin + AET[i].m, AET[i].m); } } }
private void FillPolygonHybrid(Triangle triangle, double kd, double ks, double m) { List <Edge> edges = triangle.GetEdges(); List <Edge>[] ET = EdgeBucketSort(edges); int edgesCounter = edges.Count; int y = 0; while (ET[y] == null) { y++; } List <(double yMax, double xMin, double m)> AET = new List <(double, double, double)>(); List <(Point, Color, Vector3D)> triangle_vertex = new List <(Point, Color, Vector3D)>(); for (int i = 0; i < 3; i++) { Point p; if (i == 0) { p = triangle.p1; } else if (i == 1) { p = triangle.p2; } else { p = triangle.p3; } Color objectColor = constColor; if (isColorFromTexture) { objectColor = photo[p.X, p.Y]; } Vector3D normalVector = new Vector3D(0, 0, 1); if (isNormalVectorFromMap) { normalVector = FromNormalMapToVector(normalMap[p.X, p.Y]); } else if (isNormalVectorFromBubble) { normalVector = GetNormalVectorFromBubble(p.X, p.Y); } Vector3D newL = CalculateLVector(new Vector3D(p.X, p.Y, 0)); int R = (int)GetLambertColor(((double)lightColor.R / (double)255), objectColor.R, newL, normalVector, ks, kd, m); int G = (int)GetLambertColor(((double)lightColor.G / (double)255), objectColor.G, newL, normalVector, ks, kd, m); int B = (int)GetLambertColor(((double)lightColor.B / (double)255), objectColor.B, newL, normalVector, ks, kd, m); FixRGB(ref R, ref G, ref B); Color newColor = Color.FromArgb(R, G, B); triangle_vertex.Add((p, newColor, normalVector)); } double area = CalculateTriangleArea(triangle.p1, triangle.p2, triangle.p3); while (edgesCounter != 0 || AET.Any()) { AET.RemoveAll(x => x.yMax == y); if (ET[y] != null) { foreach (Edge edge in ET[y]) { double mx = ((double)edge.p2.X - (double)edge.p1.X) / ((double)edge.p2.Y - (double)edge.p1.Y); if (edge.p1.Y != edge.p2.Y) { AET.Add((edge.p2.Y, edge.p1.X, mx)); } edgesCounter--; } } AET.Sort((a, b) => a.xMin.CompareTo(b.xMin)); for (int i = 0; i < AET.Count; i += 2) { for (int j = (int)(AET[i].xMin); j < (int)(AET[i + 1].xMin); j++) { (Color color, Vector3D vector)interpolate_values = CalculateInterpolateColorAndVertex(area, triangle_vertex, j, y); Vector3D newL = CalculateLVector(new Vector3D(j, y, 0)); int R = (int)GetLambertColor(((double)lightColor.R / (double)255), interpolate_values.color.R, newL, interpolate_values.vector, ks, kd, m); int G = (int)GetLambertColor(((double)lightColor.G / (double)255), interpolate_values.color.G, newL, interpolate_values.vector, ks, kd, m); int B = (int)GetLambertColor(((double)lightColor.B / (double)255), interpolate_values.color.B, newL, interpolate_values.vector, ks, kd, m); FixRGB(ref R, ref G, ref B); Color newColor = Color.FromArgb(R, G, B); newPhoto[j, y] = newColor; } } y++; for (int i = 0; i < AET.Count; i++) { AET[i] = (AET[i].yMax, AET[i].xMin + AET[i].m, AET[i].m); } } }
//paint polygon public static void PaintPolygon(List <SimplePoint> points, TriangleFillingMode fillingMode, ref double KdFactor, ref double KsFactor, ref int MFactor) { IntPoint[] pointsArray = new IntPoint[points.Count]; int[] indexes = new int[points.Count]; int i = 0; //fast (byte R, byte G, byte B)p0Fast = (0, 0, 0); (byte R, byte G, byte B)p1Fast = (0, 0, 0); (byte R, byte G, byte B)p2Fast = (0, 0, 0); int triangleField = 0; //hybrid SimpleColor c0Hybrid = new SimpleColor(); SimpleColor c1Hybrid = new SimpleColor(); SimpleColor c2Hybrid = new SimpleColor(); Vector3 v0Hybrid = new Vector3(); Vector3 v1Hybrid = new Vector3(); Vector3 v2Hybrid = new Vector3(); foreach (var item in points) { pointsArray[i] = new IntPoint(item.X, item.Y); if (pointsArray[i].X >= fillingMode.PictureBitmapColor.GetLength(1)) { pointsArray[i].X = fillingMode.PictureBitmapColor.GetLength(1) - 1; } if (pointsArray[i].Y >= fillingMode.PictureBitmapColor.GetLength(0)) { pointsArray[i].Y = fillingMode.PictureBitmapColor.GetLength(0) - 1; } indexes[i] = i; i++; } if (fillingMode.fillingMode == FillingMode.Fast) { p0Fast = CalculateResultColorInPoint(pointsArray[0].X, pointsArray[0].Y, fillingMode, ref KdFactor, ref KsFactor, ref MFactor); p1Fast = CalculateResultColorInPoint(pointsArray[1].X, pointsArray[1].Y, fillingMode, ref KdFactor, ref KsFactor, ref MFactor); p2Fast = CalculateResultColorInPoint(pointsArray[2].X, pointsArray[2].Y, fillingMode, ref KdFactor, ref KsFactor, ref MFactor); triangleField = IntPoint.CalculateTriangleField(pointsArray); } else if (fillingMode.fillingMode == FillingMode.Hybrid) { c0Hybrid = fillingMode.PictureBitmapColor[pointsArray[0].Y, pointsArray[0].X]; c1Hybrid = fillingMode.PictureBitmapColor[pointsArray[1].Y, pointsArray[1].X]; c2Hybrid = fillingMode.PictureBitmapColor[pointsArray[2].Y, pointsArray[2].X]; v0Hybrid = fillingMode.NormalBitmapVector[pointsArray[0].Y, pointsArray[0].X]; v1Hybrid = fillingMode.NormalBitmapVector[pointsArray[1].Y, pointsArray[1].X]; v2Hybrid = fillingMode.NormalBitmapVector[pointsArray[2].Y, pointsArray[2].X]; triangleField = IntPoint.CalculateTriangleField(pointsArray); } Array.Sort(indexes, (p1, p2) => { if (pointsArray[p1].Y > pointsArray[p2].Y) { return(1); } else if (pointsArray[p1].Y < pointsArray[p2].Y) { return(-1); } else if (pointsArray[p1].X > pointsArray[p2].X) { return(1); } else if (pointsArray[p1].X < pointsArray[p2].X) { return(-1); } return(0); }); List <(int ymax, double x, double m)> AET = new List <(int, double, double)>(); int ymin = pointsArray[indexes[0]].Y; int ymax = pointsArray[indexes[indexes.Length - 1]].Y; int startingIndex = 0; bool removeEdgesFromAET = false; for (int scanLineY = ymin; scanLineY <= ymax; scanLineY++) { for (int j = startingIndex; j < indexes.Length; j++) { if (pointsArray[indexes[j]].Y > scanLineY - 1) { break; } if (pointsArray[indexes[j]].Y == scanLineY - 1) { startingIndex++; int index = indexes[j]; int previousIndex = (indexes[j] - 1 + pointsArray.Length) % pointsArray.Length; int nextIndex = (indexes[j] + 1) % pointsArray.Length; if (pointsArray[previousIndex].Y >= pointsArray[indexes[j]].Y) { //dodaj krawedz Pi-1 Pi do AET int x = pointsArray[index].X; if (pointsArray[index].Y != pointsArray[previousIndex].Y) { double m = (double)(pointsArray[index].X - pointsArray[previousIndex].X) / (double)(pointsArray[index].Y - pointsArray[previousIndex].Y); AET.Add((pointsArray[previousIndex].Y, x, m)); } } else { //usun krawedz Pi-1 Pi z AET removeEdgesFromAET = true; } if (pointsArray[nextIndex].Y >= pointsArray[indexes[j]].Y) { //dodaj krawedz Pi+1 Pi do AET int x = pointsArray[index].X; if (pointsArray[nextIndex].Y != pointsArray[index].Y) { double m = (double)(pointsArray[nextIndex].X - pointsArray[index].X) / (double)(pointsArray[nextIndex].Y - pointsArray[index].Y); AET.Add((pointsArray[nextIndex].Y, x, m)); } } else { //usun krawedz Pi+1 Pi z AET removeEdgesFromAET = true; } if (removeEdgesFromAET == true) { AET.RemoveAll((aet) => { return(aet.ymax == scanLineY - 1); }); removeEdgesFromAET = false; } } } //uaktualnij AET //posortuj AET.Sort((p1, p2) => { if (p1.x > p2.x) { return(1); } else if (p1.x < p2.x) { return(-1); } else { return(0); } }); //wypelnij if (fillingMode.fillingMode == FillingMode.Direct) { FillScanLineDirect(scanLineY, AET, fillingMode, ref KdFactor, ref KsFactor, ref MFactor); } else if (fillingMode.fillingMode == FillingMode.Fast) { //policz kolory w wierzcholkach trojkat FillScanLineFast(scanLineY, AET, fillingMode, ref triangleField, pointsArray, ref p0Fast, ref p1Fast, ref p2Fast); } else//hybrid mode { FillScanLineHybrid(scanLineY, AET, fillingMode, ref triangleField, pointsArray, ref v0Hybrid, ref c0Hybrid, ref v1Hybrid, ref c1Hybrid, ref v2Hybrid, ref c2Hybrid, ref KdFactor, ref KsFactor, ref MFactor); } //uaktualnij x for (int k = 0; k < AET.Count; k++) { var aet = AET[k]; AET[k] = (aet.ymax, aet.x += aet.m, aet.m); } } }