Exemple #1
0
        public void Render(Scene scene)
        {
            // Order of transformation:
            // 1. Object space: In this space there are models at the beginning, they have no position or rotation.
            // 2. World space: A common space in which the camera and all models are located, after giving them coordiantes and rotation.
            // 3. View space: Coordinate space with respect to the camera, which is located at (0, 0, 0)
            // 4. Projection space: After this transformation, the objects seen by the camera gain perspective.

            // Matrix transformation from 2. to 3.
            var viewMatrix = scene.Camera.LookAtLH();

            // Matrix transformation from 3. to 4.
            var projectionMatrix = Matrix.PrespectiveFovLH(
                scene.Camera.FieldOfViewRadians,
                Bitmap.AspectRatio,
                scene.Camera.ZNear,
                scene.Camera.ZFar);

            foreach (var mesh in scene.Meshes)
            {
                // Transformation matrix from 1. to 2.
                // First we apply the rotation and then the transformation
                var worldMatrix = Matrix.Scaling(mesh.Scaling) * Matrix.RotationQuaternion(mesh.Rotation) * Matrix.Translation(mesh.Position);

                // Matrix multiplication combining all transformations in the correct order.
                var transformMatrix = worldMatrix * viewMatrix * projectionMatrix;

                // 3D coordinantes to 2D coordinantes on a bitmap.
                var pixels = mesh.Vertices.Select(vertex => Project(vertex, transformMatrix)).ToArray();

                var vertices = mesh.Vertices.Select(vertex => Vector3.TransformCoordinate(vertex, worldMatrix * viewMatrix)).ToArray();

                var color32 = mesh.Color.ToColor32();

                // Iterate over the triangles.
                foreach (var face in mesh.Faces)
                {
                    if (vertices[face.A].Z < scene.Camera.ZNear ||
                        vertices[face.B].Z < scene.Camera.ZNear ||
                        vertices[face.C].Z < scene.Camera.ZNear)
                    {
                        continue;
                    }

                    face.Edges((a, b) =>
                    {
                        var p1 = pixels[a];
                        var p2 = pixels[b];

                        if (ClippingAlgorithm.ClipLine(ref p1, ref p2))
                        {
                            // Draw the grid lines.
                            LineDrawingAlgorithm.DrawLine(p1, p2, (x, y) => Bitmap.DrawPoint(x, y, color32));
                        }
                    });
                }
            }
        }
Exemple #2
0
        /// <summary>
        ///     Renderuje obiekty na bitmapie używając danej kamery.
        /// </summary>
        public void Render(Scene scene)
        {
            // Kolejność przekształceń.
            // [1. Object Space]. W tej przestrzeni znajdują się modele na początku, nie mają swojego położenia, ani rotacji.
            // [2. World Space]. Wspólna przestrzeń, w której znajduje się kamera i wszystkie modele już po nadaniu im współrzędnych oraz rotacji.
            // [3. View Space]. Przestrzeń ze współrzędnymi względem kamery, która znajduje się w (0, 0, 0).
            // [4. Projection Space]. Po nadaniu tego przekształcenia obiekty widziane przez kamerę zyskują perspektywę.

            // Macierz przekształcenia z [2. World space] do [3. View space].
            var viewMatrix = scene.Camera.LookAtLH();

            // Macierz przekształcenia z [3. View space] do [4. Projection space].
            var projectionMatrix = Matrix.PerspectiveFovLH(
                scene.Camera.FieldOfViewRadians,
                Bitmap.AspectRatio,
                scene.Camera.ZNear,
                scene.Camera.ZFar);

            // Iterujemy wszystkie siatki modelów które mają zostać wyrenderowane.
            foreach (var mesh in scene.Meshes)
            {
                // Przygotowujemy macierz przekształcenia z [1. Object Space] do [2. World Space].
                // W tym celu zastosujemy najpierw rotację, a potem translację obiektu tak, aby znalazł się
                // w pożądanych współrzędnych w przestrzeni świata (World Space).
                var worldMatrix = Matrix.Scaling(mesh.Scaling) * Matrix.RotationQuaternion(mesh.Rotation) *
                                  Matrix.Translation(mesh.Position);

                // Poniższa macierz łączy wszystkie przekształcenia od 1. do 4. w odpowiedniej kolejności.
                var transformMatrix = worldMatrix * viewMatrix * projectionMatrix;

                // Przekształcamy współrzędne 3D do współrzędnych 2D na bitmapie.
                var pixels = mesh.Vertices.Select(vertex => Project(vertex, transformMatrix)).ToArray();


                var vertices =
                    mesh.Vertices.Select(vertex => Vector3.TransformCoordinate(vertex, worldMatrix * viewMatrix))
                    .ToArray();

                var color32 = mesh.Color.ToColor32();
                // Iterujemy wszystkie "trójkąty" bieżącej siatki.
                foreach (var face in mesh.Faces)
                {
                    // Każdy trójkąt ma trzy wierzchołki.
                    if (vertices[face.A].Z < scene.Camera.ZNear ||
                        vertices[face.B].Z < scene.Camera.ZNear ||
                        vertices[face.C].Z < scene.Camera.ZNear
                        )
                    {
                        continue;
                    }

                    face.Edges((a, b) =>
                    {
                        var p1 = pixels[a];
                        var p2 = pixels[b];

                        // Obcina linie siatki wychodzące poza ekran.
                        if (ClippingAlgorithm.ClipLine(ref p1, ref p2))
                        {
                            // Rysuje linie siatki między wierzchołkami trójkątów.
                            LineDrawingAlgorithm.DrawLine(p1, p2, (x, y) => Bitmap.DrawPoint(x, y, color32));
                        }
                    });
                }
            }
        }