Example #1
0
        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);
        }
Example #2
0
        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));
        }
Example #3
0
        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);
        }
Example #4
0
        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));
        }
Example #5
0
        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);
        }
Example #6
0
        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);
        }
Example #7
0
        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);
                });