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)); } }); } } }
/// <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)); } }); } } }
private void CarveCornerTunnel(IMap map, MapCoordinate coordinate, MapCoordinate corner) { var points = _lineDrawing.DrawLine(coordinate, corner); CarveTunnel(map, points); }