private Vector4 CalculateColor(Vector3 barycentricCoords, FilledTriangle triangle) { Vector4 point = new Vector4(); point.X = barycentricCoords.X * triangle.Vertices[0].Color.X + barycentricCoords.Y * triangle.Vertices[1].Color.X + barycentricCoords.Z * triangle.Vertices[2].Color.X; point.Y = barycentricCoords.X * triangle.Vertices[0].Color.Y + barycentricCoords.Y * triangle.Vertices[1].Color.Y + barycentricCoords.Z * triangle.Vertices[2].Color.Y; point.Z = barycentricCoords.X * triangle.Vertices[0].Color.Z + barycentricCoords.Y * triangle.Vertices[1].Color.Z + barycentricCoords.Z * triangle.Vertices[2].Color.Z; return(point); }
private Vector4 CalculateNormal(Vector3 barycentricCoords, FilledTriangle triangle) { Vector4 normal = new Vector4(); normal.X = barycentricCoords.X * triangle.Mv1.Normal.X + barycentricCoords.Y * triangle.Mv2.Normal.X + barycentricCoords.Z * triangle.Mv3.Normal.X; normal.Y = barycentricCoords.X * triangle.Mv1.Normal.Y + barycentricCoords.Y * triangle.Mv2.Normal.Y + barycentricCoords.Z * triangle.Mv3.Normal.Y; normal.Z = barycentricCoords.X * triangle.Mv1.Normal.Z + barycentricCoords.Y * triangle.Mv3.Normal.Z + barycentricCoords.Z * triangle.Mv3.Normal.Z; return(Vector4.Normalize(normal)); }
private Vector4 CalculatePoint(Vector3 barycentricCoords, FilledTriangle triangle) { Vector4 point = new Vector4(); point.X = barycentricCoords.X * triangle.Mv1.Point.X + barycentricCoords.Y * triangle.Mv2.Point.X + barycentricCoords.Z * triangle.Mv3.Point.X; point.Y = barycentricCoords.X * triangle.Mv1.Point.Y + barycentricCoords.Y * triangle.Mv2.Point.Y + barycentricCoords.Z * triangle.Mv3.Point.Y; point.Z = barycentricCoords.X * triangle.Mv1.Point.Z + barycentricCoords.Y * triangle.Mv2.Point.Z + barycentricCoords.Z * triangle.Mv3.Point.Z; return(point); }
private Vector3 CalculateBarycentric(int x, int y, FilledTriangle triangle) { var d = new Vector3(x, y, 1); var w = triangle.A.Determinant; var wx = Matrix3x3.CreateFromColumns(d, triangle.VB, triangle.VC).Determinant; var wy = Matrix3x3.CreateFromColumns(triangle.VA, d, triangle.VC).Determinant; var wz = Matrix3x3.CreateFromColumns(triangle.VA, triangle.VB, d).Determinant; var xA = wx / w; var xB = wy / w; var xC = wz / w; return(new Vector3(xA, xB, xC)); }
private FilledTriangle PrepareForFilling(FilledTriangle triangle, Camera camera, int j, int y, int y1, Vector3 barycentricCoords, float zp) { Vector4 normal = Vector4.Zero; Vector4 point = Vector4.Zero; ; Vector4 IO = Vector4.One; if (Shader.Settings.IsPhong == true) { normal = CalculateNormal(barycentricCoords, triangle); point = CalculatePoint(barycentricCoords, triangle); IO = triangle.Vertices[0].Color; } else { IO = CalculateColor(barycentricCoords, triangle); } arguments[j, y - 1] = new ShadingArguments(camera, point, normal, IO); _zBuffer[j, y1 - 1] = zp; if (j <= minX) { minX = j; } if (j >= maxX) { maxX = j; } if (y - 1 <= minY) { minY = y - 1; } if (y - 1 >= maxY) { maxY = y - 1; } return(triangle); }
private float CountZCoord(Vector3 barycentricCoords, FilledTriangle triangle) { float z = barycentricCoords.X * triangle.Vertices[0].Z + barycentricCoords.Y * triangle.Vertices[1].Z + barycentricCoords.Z * triangle.Vertices[2].Z; return(z); }
public void FillPolygon(FilledTriangle triangle, Camera camera) { List <Vertex> vertices = triangle.Vertices; int[] ind = Enumerable.Range(0, triangle.Vertices.Count).OrderBy(x => triangle.Vertices[x].Y).ToArray(); int ymin = vertices[ind[0]].Y; int ymax = vertices[ind[vertices.Count - 1]].Y; int k = 0; List <Node> AET = new List <Node>(); for (int y = ymin; y <= ymax; y++) { while (vertices[ind[k]].Y == y - 1) { int i = ind[k]; int iPrev = (ind[k] - 1) % vertices.Count; if (iPrev < 0) { iPrev += vertices.Count; } Vertex Pi = vertices[i]; Vertex PiPrev = vertices[iPrev]; CheckNeighbour(AET, iPrev, Pi, i, PiPrev); int iNext = (ind[k] + 1) % vertices.Count; if (iNext < 0) { iNext += vertices.Count; } Vertex PiNext = vertices[iNext]; CheckNeighbour(AET, i, Pi, iNext, PiNext); k++; } // AET update AET = AET.OrderBy(node => node.X).ToList(); var aet = AET; Parallel.For(0, AET.Count - 1, i => { i *= 2; var y1 = y; Parallel.For((int)Math.Round(aet[i].X), (int)Math.Round(aet[i + 1].X), j => { Vector3 barycentricCoords = CalculateBarycentric(j, y1 - 1, triangle); float zp = CountZCoord(barycentricCoords, triangle); if (zp <= _zBuffer[j, y1 - 1]) { triangle = PrepareForFilling(triangle, camera, j, y, y1, barycentricCoords, zp); } }); }); foreach (var t in AET) { t.X += t.iM; } } }
private void RepaintScene() { _myGraphics.Clear(); foreach (WorldObject worldObject in _scene.WorldObjects) { Parallel.ForEach(worldObject.LocalObject.Mesh.Triangles, triangle => { FilledTriangle filledtriangle = new FilledTriangle(); // Vertex shading Vector4 vshader1 = VectorShader(worldObject.LocalObject.Mesh.Vertices[triangle.A], worldObject.ModelMatrix, out Vector4 p1M, out Vector4 n1M); Vector4 vshader2 = VectorShader(worldObject.LocalObject.Mesh.Vertices[triangle.B], worldObject.ModelMatrix, out Vector4 p2M, out Vector4 n2M); Vector4 vshader3 = VectorShader(worldObject.LocalObject.Mesh.Vertices[triangle.C], worldObject.ModelMatrix, out Vector4 p3M, out Vector4 n3M); // Back face culling float cosNView = CalculateBackFaceCulling(p1M, n1M, n2M, n3M); if (cosNView >= 0) { return; } // Normalized vertices in Projection Vector4 pV1 = CaclulateNormalizedProjectionVertex(vshader1); Vector4 pV2 = CaclulateNormalizedProjectionVertex(vshader2); Vector4 pV3 = CaclulateNormalizedProjectionVertex(vshader3); // Cutting to cube if (!isInCube(pV1) || !isInCube(pV2) || !isInCube(pV3)) { return; } // Vertices in World Space used to calculate colors filledtriangle.Mv1 = new NVertex(p1M, n1M); filledtriangle.Mv2 = new NVertex(p2M, n2M); filledtriangle.Mv3 = new NVertex(p3M, n3M); Vector4 color1, color2, color3; GetVerticesColors(triangle, p1M, n1M, out color1, out color2, out color3); // Certices ready to be drawn Vertex viewV1 = CaclulateVieportVertex(pV1, color1); Vertex viewV2 = CaclulateVieportVertex(pV2, color2); Vertex viewV3 = CaclulateVieportVertex(pV3, color3); filledtriangle.Vertices = new List <Vertex> { viewV1, viewV2, viewV3 }; filledtriangle = PrepareBarycentricMatrix(filledtriangle, viewV1, viewV2, viewV3); _myGraphics.FillPolygon(filledtriangle, _scene.Camera); });