// The main method of the engine that re-compute each vertex projection // during each frame public static void RenderInto(RenderState state, params Mesh[] meshes) { Vector3f buffv = new Vector3f(); GeoPolar3d polarA = new GeoPolar3d(); GeoPolar3d polarB = new GeoPolar3d(); GeoPolar3d polarC = new GeoPolar3d(); Vector3f midAB = new Vector3f(); Vector3f midAC = new Vector3f(); Vector3f midBC = new Vector3f(); GeoPolar3d polarMidAB = new GeoPolar3d(); GeoPolar3d polarMidAC = new GeoPolar3d(); GeoPolar3d polarMidBC = new GeoPolar3d(); foreach (Mesh mesh in meshes) { for (int faceIndex = 0; faceIndex < mesh.Faces.Length; faceIndex++) { var face = mesh.Faces[faceIndex]; state.TransformToPolar(ref mesh.Vertices[face.A].Coordinates, ref polarA); state.TransformToPolar(ref mesh.Vertices[face.B].Coordinates, ref polarB); state.TransformToPolar(ref mesh.Vertices[face.C].Coordinates, ref polarC); // TODO: Skip this triangle if it contains the point we are at? // Also need to maintain the triangle topology that can be distrupted by // discontinuities in arctan. Vector3f.Avg(ref mesh.Vertices[face.A].Coordinates, ref mesh.Vertices[face.B].Coordinates, ref midAB); Vector3f.Avg(ref mesh.Vertices[face.A].Coordinates, ref mesh.Vertices[face.C].Coordinates, ref midAC); Vector3f.Avg(ref mesh.Vertices[face.B].Coordinates, ref mesh.Vertices[face.C].Coordinates, ref midBC); state.TransformToPolar(ref midAB, ref polarMidAB); state.TransformToPolar(ref midAC, ref polarMidAC); state.TransformToPolar(ref midBC, ref polarMidBC); bool abOK = CheckBetween(polarA.Lat, polarMidAB.Lat, polarB.Lat); bool acOK = CheckBetween(polarA.Lat, polarMidAC.Lat, polarC.Lat); bool bcOK = CheckBetween(polarB.Lat, polarMidBC.Lat, polarC.Lat); if (!(abOK && acOK && bcOK)) { if (abOK) { polarC.Lat += (polarC.Lat < polarA.Lat ? 1 : -1) * 2 * Math.PI; } if (acOK) { polarB.Lat += (polarB.Lat < polarA.Lat ? 1 : -1) * 2 * Math.PI; } if (bcOK) { polarA.Lat += (polarA.Lat < polarC.Lat ? 1 : -1) * 2 * Math.PI; } } // Now check if any triangles need to be shifted by multiple of 2Pi to move into view // First, shift neg while ( polarA.Lat - 2 * Math.PI >= state.Camera.MinAngleRad || polarB.Lat - 2 * Math.PI >= state.Camera.MinAngleRad || polarC.Lat - 2 * Math.PI >= state.Camera.MinAngleRad) { polarC.Lat -= 2 * Math.PI; polarB.Lat -= 2 * Math.PI; polarA.Lat -= 2 * Math.PI; } while ( polarA.Lat <= state.Camera.MaxAngleRad || polarB.Lat <= state.Camera.MaxAngleRad || polarC.Lat <= state.Camera.MaxAngleRad) { var pixelA = state.Project(ref mesh.Vertices[face.A], ref polarA); var pixelB = state.Project(ref mesh.Vertices[face.B], ref polarB); var pixelC = state.Project(ref mesh.Vertices[face.C], ref polarC); DrawTriangle(state, ref pixelA, ref pixelB, ref pixelC, mesh.Texture, ref buffv); polarC.Lat += 2 * Math.PI; polarB.Lat += 2 * Math.PI; polarA.Lat += 2 * Math.PI; } } } }