/// <summary> /// The main method of the engine that re-compute each vertex projection /// during each frame /// </summary> /// <param name="camera"></param> /// <param name="meshes"></param> public void Render(Camera camera, params Mesh[] meshes) { // To understand this part, please read the prerequisites resources var viewMatrix = Matrix.LookAtLH(camera.Position, camera.Target, Vector3.Up); var projectionMatrix = Matrix.PerspectiveFovRH(0.78f, (float)bmp.PixelWidth / bmp.PixelHeight, 0.01f, 1.0f); for (var i = 0; i < meshes.Length; i++) { // Beware to apply rotation before translation var worldMatrix = Matrix.RotationYawPitchRoll(meshes[i].Rotation.Y, meshes[i].Rotation.X, meshes[i].Rotation.Z) * Matrix.Translation(meshes[i].Position); var transformMatrix = worldMatrix * viewMatrix * projectionMatrix; //Iterate over the faces, get the vertices of each face and draw the lines between them Parallel.For(0, meshes[i].Faces.Length, j => { var pixelA = Project(meshes[i].Vertices[meshes[i].Faces[j].A], transformMatrix, worldMatrix); var pixelB = Project(meshes[i].Vertices[meshes[i].Faces[j].B], transformMatrix, worldMatrix); var pixelC = Project(meshes[i].Vertices[meshes[i].Faces[j].C], transformMatrix, worldMatrix); var color = 0.25f + j % meshes[i].Faces.Length * 0.75f / meshes[i].Faces.Length; DrawTriangle(pixelA, pixelB, pixelC, new Color { ScB = color, ScG = color, ScR = color, ScA = 1f }, meshes[i].Texture); }); } }
/// <summary> /// Project takes some 3D coordinates and transform them /// in 2D coordinates using the transformation matrix /// </summary> Vertex Project(Vertex vertex, Matrix transMat, Matrix world) { // transforming the coordinates var point2D = Vector3.TransformCoordinates(vertex.Coordinates, transMat); var point3D = Vector3.TransformCoordinates(vertex.Coordinates, world); var normal3DWorld = Vector3.TransformCoordinates(vertex.Normal, world); // The transformed coordinates will be based on coordinate system // starting on the center of the screen. But drawing on screen normally starts // from top left. We then need to transform them again to have x:0, y:0 on top left. var x = point2D.X * renderWidth + renderWidth / 2.0f; var y = -point2D.Y * renderHeight + renderHeight / 2.0f; return(new Vertex { Coordinates = new Vector3(x, y, point3D.Z), Normal = normal3DWorld, WorldCoordinates = point3D, TexCoord = vertex.TexCoord }); }