public MyEdge(float _YMax, float _XMin, float _Coef, MyEdge _Next) { YMax = _YMax; XMin = _XMin; Coefficient = _Coef; Next = _Next; }
public MyEdge() { YMax = 0; XMin = 0; Coefficient = 0; Next = null; }
public MyEdge MergeSort(MyEdge head) { if (head == null || head.Next == null) { return(head); } MyEdge middle = GetMiddle(head); //get the middle of the list MyEdge sHalf = middle.Next; middle.Next = null; //split the list into two halfs return(Merge(MergeSort(head), MergeSort(sHalf))); //recurse on that }
//Finding the middle element of the list for splitting public MyEdge GetMiddle(MyEdge head) { if (head == null) { return(head); } MyEdge slow, fast; slow = fast = head; while (fast.Next != null && fast.Next.Next != null) { slow = slow.Next; fast = fast.Next.Next; } return(slow); }
//Merge subroutine to merge two sorted lists public MyEdge Merge(MyEdge a, MyEdge b) { MyEdge dummyHead = new MyEdge(); MyEdge curr = dummyHead; while (a != null && b != null) { if (a.XMin <= b.XMin) { curr.Next = a; a = a.Next; } else { curr.Next = b; b = b.Next; } curr = curr.Next; } curr.Next = (a == null) ? b : a; return(dummyHead.Next); }
public void FillScanLines() { int y = 0; int R, G, B; float cosNL; float lighVectLen; float normVectLen; float distLen; float refVectLen; float refPointVectLen; float cosVrVp; float[] Vr = new float[3]; float[] Vp = new float[3]; Point RefPos = new Point(WorkspacePictureBox.Image.Width / 2, WorkspacePictureBox.Image.Height / 2); Color objCol; Color objCol2; Color ligCol = LightColorBoxPB.BackColor; Color normVectCol; Color distPix; Color distNX; Color distNY; MyEdge temp = null; UpdateEdges(); Bitmap bitmap = new Bitmap(WorkspacePictureBox.Width, WorkspacePictureBox.Height); while (GET[y] == null && GET2[y] == null) { y++; } AET = null; AET2 = null; while (y < WorkspacePictureBox.Height) { // Add lists from y bucket to AET if (GET[y] != null && AET == null) { AET = GET[y]; } else if (AET != null) { if (GET[y] != null) { temp = AET; while (temp.Next != null) { temp = temp.Next; } temp.Next = GET[y]; } // Sort AET by x AET = MergeSort(AET); // TO_TEST Remove from AET elems for which y = yMax temp = AET; while (temp != null && temp.Next != null) { if (temp.Next.YMax <= y) { temp.Next = temp.Next.Next; } temp = temp.Next; } if (AET.YMax <= y) { AET = AET.Next; } if (AET != null && AET.YMax <= y) { AET = AET.Next; } // Fill pixs between crossings temp = AET; while (temp != null && temp.Next != null) { for (int i = (int)temp.XMin; i < temp.Next.XMin; i++) { if (Tri1ColConstRB.Checked) { objCol = Tri1ColorBoxPB.BackColor; } else // From texture { objCol = tri1ColText.GetPixel(i % (tri1ColText.Width - 1) + 1, y % (tri1ColText.Height - 1) + 1); } Point mouse = PointToClient(MousePosition); // Bąbelek aka "bubble" if (BubbleCB.Checked && (i - PointToClient(MousePosition).X) * (i - PointToClient(MousePosition).X) + (y - PointToClient(MousePosition).Y) * (y - PointToClient(MousePosition).Y) <= r * r) { // Oblicznie wektorów bąbelka N[2] = (float)Math.Sqrt(r * r - Math.Sqrt(i * i + y * y)); N[0] = (i - mouse.X) / N[2]; N[1] = (y - mouse.Y) / N[2]; N[2] /= N[2]; } else if (NormalVectTextRB.Checked) { normVectCol = normVectText.GetPixel(i % (normVectText.Width), y % (normVectText.Height)); N[2] = normVectCol.B; N[0] = (normVectCol.R - 127) / N[2]; N[1] = (normVectCol.G - 127) / N[2]; N[2] /= N[2]; } else { N = new float[] { 0, 0, 1 } }; if (DisturbTextRB.Checked) { distPix = disturbText.GetPixel(i % (disturbText.Width), y % (disturbText.Height)); distNX = disturbText.GetPixel((i + 1) % (disturbText.Width), y % (disturbText.Height)); distNY = disturbText.GetPixel(i % (disturbText.Width), (y + 1) % (disturbText.Height)); D[0] = 1 * ((distNX.R + distNX.G + distNX.B) - (distPix.R + distPix.G + distPix.B)) / 3; D[1] = 1 * ((distNY.R + distNY.G + distNY.B) - (distPix.R + distPix.G + distPix.B)) / 3; D[2] = -N[0] * ((distNX.R + distNX.G + distNX.B) - (distPix.R + distPix.G + distPix.B)) / 3 - N[1] * ((distNY.R + distNY.G + distNY.B) - (distPix.R + distPix.G + distPix.B)) / 3; distLen = (float)Math.Sqrt(D[0] * D[0] + D[1] * D[1] + D[2] * D[2]); if (distLen != 0) { D[0] /= distLen; D[1] /= distLen; D[2] /= distLen; } } Np[0] = N[0] + D[0]; Np[1] = N[1] + D[1]; Np[2] = N[2] + D[2]; normVectLen = (float)Math.Sqrt(Np[0] * Np[0] + Np[1] * Np[1] + Np[2] * Np[2]); Np[0] /= normVectLen; Np[1] /= normVectLen; Np[2] /= normVectLen; if (LighSourVectAnimRB.Checked) { L[0] = lightPos[0] - i; L[1] = lightPos[1] - y; L[2] = 100f; lighVectLen = (float)Math.Sqrt(L[0] * L[0] + L[1] * L[1] + L[2] * L[2]); L[0] /= lighVectLen; L[1] /= lighVectLen; L[2] /= lighVectLen; } cosNL = Math.Max(0, (Np[0] * L[0] + Np[1] * L[1] + Np[2] * L[2])); // Normalized (both divided by 255) and denormalized (result multiplied by 255) R = (int)(objCol.R / 255f * ligCol.R * cosNL); G = (int)(objCol.G / 255f * ligCol.G * cosNL); B = (int)(objCol.B / 255f * ligCol.B * cosNL); if (ReflectorCB.Checked) { Vr[0] = mouse.X - RefPos.X; Vr[1] = mouse.Y - RefPos.Y; Vr[2] = refHeight; refVectLen = (float)Math.Sqrt(Vr[0] * Vr[0] + Vr[1] * Vr[1] + Vr[2] * Vr[2]); Vr[0] /= refVectLen; Vr[1] /= refVectLen; Vr[2] /= refVectLen; Vp[0] = i - RefPos.X; Vp[1] = y - RefPos.Y; Vp[2] = refHeight; refPointVectLen = (float)Math.Sqrt(Vp[0] * Vp[0] + Vp[1] * Vp[1] + Vp[2] * Vp[2]); Vp[0] /= refPointVectLen; Vp[1] /= refPointVectLen; Vp[2] /= refPointVectLen; cosVrVp = Vr[0] * Vp[0] + Vr[1] * Vp[1] + Vr[2] * Vp[2]; cosVrVp = (float)Math.Pow(cosVrVp, K); R = (int)(R * (1 + cosVrVp)); G = (int)(G * (1 + cosVrVp)); B = (int)(B * (1 + cosVrVp)); if (R > 255) { R = 255; } if (G > 255) { G = 255; } if (B > 255) { B = 255; } } bitmap.SetPixel(i, y, Color.FromArgb(R, G, B)); } temp = temp.Next.Next; } // For each edge in AET update x (x+=1/m) temp = AET; while (temp != null) { temp.XMin += temp.Coefficient; temp = temp.Next; } } // TRIANGLE no 2, not DRY temp = null; // Add lists from y bucket to AET if (GET2[y] != null && AET2 == null) { AET2 = GET2[y]; } else if (AET2 != null) { if (GET2[y] != null) { temp = AET2; while (temp.Next != null) { temp = temp.Next; } temp.Next = GET2[y]; } // Sort AET by x AET2 = MergeSort(AET2); // TO_TEST Remove from AET elems for which y = yMax temp = AET2; while (temp != null && temp.Next != null) { if (temp.Next.YMax <= y) { temp.Next = temp.Next.Next; } temp = temp.Next; } if (AET2.YMax <= y) { AET2 = AET2.Next; } if (AET2 != null && AET2.YMax <= y) { AET2 = AET2.Next; } // Fill pixs between crossings temp = AET2; while (temp != null && temp.Next != null) { for (int i = (int)temp.XMin; i < temp.Next.XMin; i++) { if (Tri2ColConstRB.Checked) { objCol2 = Tri2ColorBoxPB.BackColor; } else // From texture { objCol2 = tri2ColText.GetPixel(i % (tri2ColText.Width - 1) + 1, y % (tri2ColText.Height - 1) + 1); } Point mouse = PointToClient(MousePosition); // Bąbelek aka "bubble" if (BubbleCB.Checked && (i - PointToClient(MousePosition).X) * (i - PointToClient(MousePosition).X) + (y - PointToClient(MousePosition).Y) * (y - PointToClient(MousePosition).Y) <= r * r) { N[2] = (float)Math.Sqrt(r * r - Math.Sqrt(i * i + y * y)); N[0] = (i - mouse.X) / N[2]; N[1] = (y - mouse.Y) / N[2]; N[2] /= N[2]; } else if (NormalVectTextRB.Checked) { normVectCol = normVectText.GetPixel(i % (normVectText.Width), y % (normVectText.Height)); N[2] = normVectCol.B; N[0] = (normVectCol.R - 127) / N[2]; N[1] = (normVectCol.G - 127) / N[2]; N[2] /= N[2]; } else { N = new float[] { 0, 0, 1 } }; if (DisturbTextRB.Checked) { distPix = disturbText.GetPixel(i % (disturbText.Width), y % (disturbText.Height)); distNX = disturbText.GetPixel((i + 1) % (disturbText.Width), y % (disturbText.Height)); distNY = disturbText.GetPixel(i % (disturbText.Width), (y + 1) % (disturbText.Height)); D[0] = 1 * ((distNX.R + distNX.G + distNX.B) - (distPix.R + distPix.G + distPix.B)) / 3; D[1] = 1 * ((distNY.R + distNY.G + distNY.B) - (distPix.R + distPix.G + distPix.B)) / 3; D[2] = -N[0] * ((distNX.R + distNX.G + distNX.B) - (distPix.R + distPix.G + distPix.B)) / 3 - N[1] * ((distNY.R + distNY.G + distNY.B) - (distPix.R + distPix.G + distPix.B)) / 3; distLen = (float)Math.Sqrt(D[0] * D[0] + D[1] * D[1] + D[2] * D[2]); if (distLen != 0) { D[0] /= distLen; D[1] /= distLen; D[2] /= distLen; } } Np[0] = N[0] + D[0]; Np[1] = N[1] + D[1]; Np[2] = N[2] + D[2]; normVectLen = (float)Math.Sqrt(Np[0] * Np[0] + Np[1] * Np[1] + Np[2] * Np[2]); Np[0] /= normVectLen; Np[1] /= normVectLen; Np[2] /= normVectLen; if (LighSourVectAnimRB.Checked) { L[0] = lightPos[0] - i; L[1] = lightPos[1] - y; L[2] = 100f; lighVectLen = (float)Math.Sqrt(L[0] * L[0] + L[1] * L[1] + L[2] * L[2]); L[0] /= lighVectLen; L[1] /= lighVectLen; L[2] /= lighVectLen; } cosNL = Math.Max(0, (Np[0] * L[0] + Np[1] * L[1] + Np[2] * L[2])); // Normalized (both divided by 255) and denormalized (result multiplied by 255) R = (int)(objCol2.R / 255f * ligCol.R * cosNL); G = (int)(objCol2.G / 255f * ligCol.G * cosNL); B = (int)(objCol2.B / 255f * ligCol.B * cosNL); if (ReflectorCB.Checked) { Vr[0] = mouse.X - RefPos.X; Vr[1] = mouse.Y - RefPos.Y; Vr[2] = refHeight; refVectLen = (float)Math.Sqrt(Vr[0] * Vr[0] + Vr[1] * Vr[1] + Vr[2] * Vr[2]); Vr[0] /= refVectLen; Vr[1] /= refVectLen; Vr[2] /= refVectLen; Vp[0] = i - RefPos.X; Vp[1] = y - RefPos.Y; Vp[2] = refHeight; refPointVectLen = (float)Math.Sqrt(Vp[0] * Vp[0] + Vp[1] * Vp[1] + Vp[2] * Vp[2]); Vp[0] /= refPointVectLen; Vp[1] /= refPointVectLen; Vp[2] /= refPointVectLen; cosVrVp = Vr[0] * Vp[0] + Vr[1] * Vp[1] + Vr[2] * Vp[2]; cosVrVp = (float)Math.Pow(cosVrVp, K); R = (int)(R * (1 + cosVrVp)); G = (int)(G * (1 + cosVrVp)); B = (int)(B * (1 + cosVrVp)); if (R > 255) { R = 255; } if (G > 255) { G = 255; } if (B > 255) { B = 255; } } bitmap.SetPixel(i, y, Color.FromArgb(R, G, B)); } temp = temp.Next.Next; } // For each edge in AET update x (x+=1/m) temp = AET2; while (temp != null) { temp.XMin += temp.Coefficient; temp = temp.Next; } } y++; } WorkspacePictureBox.Image.Dispose(); WorkspacePictureBox.Image = bitmap; }
public void UpdateEdges() { float x1 = Points[0].X, y1 = Points[0].Y; float x2 = Points[1].X, y2 = Points[1].Y; float coef = (x2 - x1) / (y2 - y1); MyEdge temp = new MyEdge(Math.Max(Points[0].Y, Points[1].Y), Points[Points[0].Y < Points[1].Y ? 0 : 1].X, coef, null); int iNext; float x3 = Points[3].X, y3 = Points[3].Y; float x4 = Points[4].X, y4 = Points[4].Y; float coef2 = (x4 - x3) / (y4 - y3); MyEdge temp2 = new MyEdge(Math.Max(Points[3].Y, Points[4].Y), Points[Points[3].Y < Points[4].Y ? 3 : 4].X, coef2, null); int iNext2; for (int i = 0; i < GET.Length; i++) { GET[i] = null; GET2[i] = null; } GET[(int)Math.Min(Points[0].Y, Points[1].Y)] = temp; GET2[(int)Math.Min(y3, y4)] = temp2; for (int i = 1; i < Points.Length / 2; i++) { if (i == 2) { iNext = 0; iNext2 = 3; } else { iNext = i + 1; iNext2 = iNext + 3; } x1 = Points[i].X; y1 = Points[i].Y; x2 = Points[iNext].X; y2 = Points[iNext].Y; coef = (x2 - x1) / (y2 - y1); x3 = Points[i + 3].X; y3 = Points[i + 3].Y; x4 = Points[iNext2].X; y4 = Points[iNext2].Y; coef2 = (x4 - x3) / (y4 - y3); int ind = (int)Math.Min(Points[i].Y, Points[iNext].Y); if (Points[i].Y != Points[iNext].Y) { if (GET[ind] == null) { GET[ind] = new MyEdge(Math.Max(Points[i].Y, Points[iNext].Y), Points[Points[i].Y < Points[iNext].Y ? i : iNext].X, coef, null); } else { temp = GET[ind]; while (temp.Next != null) { temp = temp.Next; } temp.Next = new MyEdge(Math.Max(Points[i].Y, Points[iNext].Y), Points[Points[i].Y < Points[iNext].Y ? i : iNext].X, coef, null); } } int ind2 = (int)Math.Min(Points[i + 3].Y, Points[iNext2].Y); if (Points[i + 3].Y != Points[iNext2].Y) { if (GET2[ind2] == null) { GET2[ind2] = new MyEdge(Math.Max(Points[i + 3].Y, Points[iNext2].Y), Points[Points[i + 3].Y < Points[iNext2].Y ? i + 3 : iNext2].X, coef2, null); } else { temp = GET2[ind2]; while (temp.Next != null) { temp = temp.Next; } temp.Next = new MyEdge(Math.Max(Points[i + 3].Y, Points[iNext2].Y), Points[Points[i + 3].Y < Points[iNext2].Y ? i + 3 : iNext2].X, coef2, null); } } } }