private void DrawFlat(GraphicsDevice graphicsDevice, SectorBounds bounds, ISector rootSector) { RenderTarget2D renderTarget = renderTargets[rootSector]; // Set the render target graphicsDevice.SetRenderTarget(renderTarget); graphicsDevice.DepthStencilState = new DepthStencilState() { DepthBufferEnable = true }; graphicsDevice.Clear(Pallete.OCEAN_BLUE); double relativeCameraZoom = camera.cameraZoom - Math.Log(ZCoords.GetSectorManager().GetTopmostOSMSectors().Count, 4) + (Game1.RECORDING ? 1 : 0); int zoomLevel = Math.Min(Math.Max((int)(relativeCameraZoom - 3), 0), ZCoords.GetSectorManager().GetHighestOSMZoom()); List <ISector> containedSectors = rootSector.GetSectorsInRange(bounds.minX, bounds.maxX, bounds.minY, bounds.maxY, zoomLevel); List <ISector> sorted = containedSectors.Where(x => x.GetRoot().Equals(rootSector)).ToList(); sorted.Sort((x, y) => x.Zoom.CompareTo(y.Zoom)); foreach (var sector in sorted) { IGraphicsBuffer buffer = loadedMaps[sector]; if (!(buffer is ImageTileBuffer)) { continue; } Matrixd projection = Matrixd.CreateOrthographicOffCenter(bounds.minX * (1 << sector.Zoom) - sector.X, bounds.maxX * (1 << sector.Zoom) - sector.X, bounds.maxY * (1 << sector.Zoom) - sector.Y, bounds.minY * (1 << sector.Zoom) - sector.Y, -1, 0.01f); // TODO: why negative? RenderContext context = new RenderContext(graphicsDevice, projection, bounds.minX * (1 << sector.Zoom) - sector.X, bounds.maxX * (1 << sector.Zoom) - sector.X, bounds.minY * (1 << sector.Zoom) - sector.Y, bounds.maxY * (1 << sector.Zoom) - sector.Y, camera.cameraZoom, RenderContext.LayerPass.MAIN_PASS); buffer.Draw(context); } }
public PlanetComponent(Game game, EditorCamera camera) { this.camera = camera; foreach (var rootSector in ZCoords.GetSectorManager().GetTopmostOSMSectors()) { #if WINDOWS RenderTarget2D renderTarget = new RenderTarget2D( game.GraphicsDevice, 2560, 1440, true, GraphicsDevice.PresentationParameters.BackBufferFormat, DepthFormat.Depth24); #else RenderTarget2D renderTarget = new RenderTarget2D( game.GraphicsDevice, 2560, 1440, false, game.GraphicsDevice.PresentationParameters.BackBufferFormat, DepthFormat.Depth24); #endif renderTargets[rootSector] = renderTarget; } }
public HouseBuffer(GraphicsDevice graphicsDevice, List <Matrix> matrices, ISector sector) { this.sector = sector; this.matrices = matrices; double radius = 6356000; // of earth, in meters double scale = 2 / Math.Sqrt(4 * Math.PI * radius * radius / ZCoords.GetSectorManager().GetTopmostOSMSectors().Count / (1 << (2 * ZCoords.GetSectorManager().GetHighestOSMZoom()))); VertexDeclaration instanceVertexDeclaration = GenerateInstanceVertexDeclaration(); instanceBuffer = new VertexBuffer(graphicsDevice, instanceVertexDeclaration, matrices.Count, BufferUsage.WriteOnly); instanceBuffer.SetData(matrices.Select(x => Matrix.CreateScale((float)scale) * x).ToArray()); bindings = new List <VertexBufferBinding[]>(); foreach (ModelMesh mesh in GlobalContent.House.Meshes) { foreach (var meshPart in mesh.MeshParts) { var meshPartBindings = new VertexBufferBinding[2]; meshPartBindings[0] = new VertexBufferBinding(meshPart.VertexBuffer, 0); meshPartBindings[1] = new VertexBufferBinding(instanceBuffer, 0, 1); bindings.Add(meshPartBindings); } } }
// make a lo-rez map showing where there's coast so we can flood-fill it later with land/water public static void SaveCoastLineMap(GraphicsDevice graphicsDevice) { var manager = ZCoords.GetSectorManager(); int imageSize = 1 << manager.GetHighestOSMZoom(); foreach (var sector in manager.GetTopmostOSMSectors()) { RenderTarget2D newTarget = new RenderTarget2D(graphicsDevice, imageSize, imageSize, false, graphicsDevice.PresentationParameters.BackBufferFormat, DepthFormat.Depth24); graphicsDevice.SetRenderTarget(newTarget); List <ISector> sectorsToCheck = new List <ISector>(); sectorsToCheck.AddRange(sector.GetChildrenAtLevel(ZCoords.GetSectorManager().GetHighestOSMZoom())); foreach (var s in sectorsToCheck) { if (File.Exists(OSMPaths.GetSectorPath(s))) { GraphicsBasic.DrawScreenRect(graphicsDevice, s.X, s.Y, 1, 1, ContainsCoast(s) ? Microsoft.Xna.Framework.Color.Gray : Microsoft.Xna.Framework.Color.White); } else { GraphicsBasic.DrawScreenRect(graphicsDevice, s.X, s.Y, 1, 1, Microsoft.Xna.Framework.Color.Red); } } string mapFile = OSMPaths.GetCoastlineImagePath(sector); using (var writer = File.OpenWrite(mapFile)) { newTarget.SaveAsPng(writer, imageSize, imageSize); } } }
// move some of our files to the Android assets folder private static void HelpZenithAndroid() { LongLat longLat = new LongLat(-87.3294527 * Math.PI / 180, 30.4668536 * Math.PI / 180); // Pensacola CubeSector ourRoot = new CubeSector(CubeSector.CubeSectorFace.LEFT, 0, 0, 0); Vector2d relativeCoord = ourRoot.ProjectToLocalCoordinates(longLat.ToSphereVector()); HashSet <ISector> sectorsToLoad = new HashSet <ISector>(); foreach (var r in ZCoords.GetSectorManager().GetTopmostOSMSectors()) { sectorsToLoad.Add(r); for (int z = 1; z <= 3; z++) { foreach (var child in r.GetChildrenAtLevel(z)) { sectorsToLoad.Add(child); } } } for (int z = 4; z <= 8; z++) { ISector sector = ourRoot.GetSectorAt(relativeCoord.X, relativeCoord.Y, z); for (int i = 0; i < 25; i++) { sectorsToLoad.Add(new CubeSector(((CubeSector)sector).sectorFace, sector.X + i / 5 - 2, sector.Y + i % 5 - 2, sector.Zoom)); } } foreach (var sector in sectorsToLoad) { MoveSectorImage(sector); MoveSectorOSM(sector); } }
static void Main(string[] args) { if (args.Length > 0) { Game1.RENDER_SECTOR = ZCoords.GetSectorManager().FromString(args[0]); } using (var game = new Zenith.Game1()) game.Run(); }
private static void LoadAll() { GLOBAL_FINAL = new OSMMetaFinal(); // init GLOBAL_FINAL.gridPoints = new Dictionary <ISector, GridPointInfo[, ]>(); foreach (var root in ZCoords.GetSectorManager().GetTopmostOSMSectors()) { GridPointInfo[,] gp = new GridPointInfo[257, 257]; for (int x = 0; x < 257; x++) { for (int y = 0; y < 257; y++) { gp[x, y] = new GridPointInfo(); } } GLOBAL_FINAL.gridPoints[root] = gp; } for (int r = 0; r < 6; r++) { var frRoot = new CubeSector((CubeSector.CubeSectorFace)r, 0, 0, 0); string filePath = Path.Combine(OSMPaths.GetRenderRoot(), $"Coastline{frRoot.sectorFace.GetFaceAcronym()}.txt"); using (var writer = File.Open(filePath, FileMode.Open)) { using (var br = new BinaryReader(writer)) { int badRelationsCount = br.ReadInt32(); for (int i = 0; i < badRelationsCount; i++) { GLOBAL_FINAL.badRelations.Add(br.ReadInt64()); } for (int i = 0; i < 257; i++) { for (int j = 0; j < 257; j++) { GridPointInfo gridPoint = GLOBAL_FINAL.gridPoints[frRoot][i, j]; int naturalTypesCount = br.ReadInt32(); for (int k = 0; k < naturalTypesCount; k++) { gridPoint.naturalTypes.Add(br.ReadInt32()); } int relationsCount = br.ReadInt32(); for (int k = 0; k < relationsCount; k++) { gridPoint.relations.Add(br.ReadInt64()); } int waysCount = br.ReadInt32(); for (int k = 0; k < waysCount; k++) { gridPoint.ways.Add(br.ReadInt64()); } } } } } } }
public ISector FromString(string s) { String[] split = s.Split(','); CubeSector.CubeSectorFace sectorFace = ZCoords.FromFaceAcronym(split[0]); int x = int.Parse(split[1].Split('=')[1]); int y = int.Parse(split[2].Split('=')[1]); int zoom = int.Parse(split[3].Split('=', '.')[1]); return(new CubeSector(sectorFace, x, y, zoom)); }
public override void Draw(RenderContext renderContext, GameTime gameTime) { if (renderContext.layerPass == RenderContext.LayerPass.MAIN_PASS && !Game1.DEFERRED_RENDERING) { var effect = this.GetDefaultEffect(renderContext.graphicsDevice); camera.ApplyMatrices(effect); float distance = (float)(9 * Math.Pow(0.5, camera.cameraZoom)); // TODO: this is hacky effect.View = CameraMatrixManager.GetWorldRelativeView(distance); effect.TextureEnabled = true; foreach (var rootSector in ZCoords.GetSectorManager().GetTopmostOSMSectors()) { SectorBounds bounds = GetSectorBounds(renderContext.graphicsDevice, rootSector); VertexIndiceBuffer sphere = SphereBuilder.MakeSphereSegExplicit(renderContext.graphicsDevice, rootSector, 2, bounds.minX, bounds.minY, bounds.maxX, bounds.maxY, camera); effect.Texture = renderTargets[rootSector]; foreach (EffectPass pass in effect.CurrentTechnique.Passes) { pass.Apply(); renderContext.graphicsDevice.Indices = sphere.indices; renderContext.graphicsDevice.SetVertexBuffer(sphere.vertices); renderContext.graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, sphere.indices.IndexCount / 3); } sphere.vertices.Dispose(); sphere.indices.Dispose(); } } if (renderContext.layerPass == RenderContext.LayerPass.MAIN_PASS && Game1.DEFERRED_RENDERING) { var effect = GlobalContent.DeferredBasicNormalTextureShader; float distance = (float)(9 * Math.Pow(0.5, camera.cameraZoom)); // TODO: this is hacky Matrix view = CameraMatrixManager.GetWorldRelativeView(distance); effect.Parameters["WVP"].SetValue(camera.world * view * camera.projection); foreach (var rootSector in ZCoords.GetSectorManager().GetTopmostOSMSectors()) { SectorBounds bounds = GetSectorBounds(renderContext.graphicsDevice, rootSector); VertexIndiceBuffer sphere = SphereBuilder.MakeSphereSegExplicit(renderContext.graphicsDevice, rootSector, 2, bounds.minX, bounds.minY, bounds.maxX, bounds.maxY, camera); effect.Parameters["Texture"].SetValue(renderTargets[rootSector]); foreach (EffectPass pass in effect.CurrentTechnique.Passes) { pass.Apply(); renderContext.graphicsDevice.Indices = sphere.indices; renderContext.graphicsDevice.SetVertexBuffer(sphere.vertices); renderContext.graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, sphere.indices.IndexCount / 3); } sphere.vertices.Dispose(); sphere.indices.Dispose(); } } foreach (var rootSector in ZCoords.GetSectorManager().GetTopmostOSMSectors()) { Draw3D(renderContext.graphicsDevice, allBounds[rootSector], rootSector, renderContext.layerPass); } }
private ISector GetContainingSector(LongLat x, int level) { foreach (var root in ZCoords.GetSectorManager().GetTopmostOSMSectors()) { if (root.ContainsLongLat(x)) { Vector2d localAgain = root.ProjectToLocalCoordinates(x.ToSphereVector()); return(root.GetSectorAt(localAgain.X, localAgain.Y, level)); } } throw new NotImplementedException(); }
private void RebuildImage(GraphicsDevice graphicsDevice, ISector sector) { // combination images using (Texture2D rendered = new RenderTarget2D(graphicsDevice, 512, 512, false, graphicsDevice.PresentationParameters.BackBufferFormat, DepthFormat.Depth24)) { int highestZoom = ZCoords.GetSectorManager().GetHighestCacheZoom(); foreach (var parent in sector.GetAllParents().OrderBy(x => - x.Zoom).Where(x => x.Zoom <= highestZoom)) { List <ISector> roadSectors = parent.GetChildrenAtLevel(parent.Zoom == highestZoom - 1 ? ZCoords.GetSectorManager().GetHighestOSMZoom() : parent.Zoom + 1); Texture2D[] textures = new Texture2D[roadSectors.Count]; for (int i = 0; i < roadSectors.Count; i++) { IGraphicsBuffer buffer = null; if (File.Exists(OSMPaths.GetSectorImagePath(roadSectors[i]))) { using (var reader = File.OpenRead(OSMPaths.GetSectorImagePath(roadSectors[i]))) { buffer = new ImageTileBuffer(graphicsDevice, Texture2D.FromStream(graphicsDevice, reader), roadSectors[i]); } } else { throw new NotImplementedException(); } textures[i] = buffer.GetImage(graphicsDevice); } if (textures.Any(x => x != null)) { graphicsDevice.SetRenderTarget((RenderTarget2D)rendered); for (int i = 0; i < roadSectors.Count; i++) { int size, x, y; size = 512 >> (roadSectors[i].Zoom - parent.Zoom); x = parent.GetRelativeXOf(roadSectors[i]) * size; y = parent.GetRelativeYOf(roadSectors[i]) * size; if (textures[i] != null) { GraphicsBasic.DrawSpriteRect(graphicsDevice, x, y, size, size, textures[i], BlendState.AlphaBlend, Microsoft.Xna.Framework.Color.White); } } } for (int i = 0; i < textures.Length; i++) { if (textures[i] != null && textures[i] != GlobalContent.Error) { textures[i].Dispose(); } } SuperSave(rendered, OSMPaths.GetSectorImagePath(parent)); } } }
Dictionary <ISector, SectorBounds> allBounds = new Dictionary <ISector, SectorBounds>(); // TODO: refactor this away from static-ness public override void InitDraw(RenderContext renderContext) { allBounds = new Dictionary <ISector, SectorBounds>(); // precompute this because it depends heavily on the active GraphicsDevice RenderTarget foreach (var rootSector in ZCoords.GetSectorManager().GetTopmostOSMSectors()) { allBounds[rootSector] = GetSectorBounds(renderContext.graphicsDevice, rootSector); } foreach (var rootSector in ZCoords.GetSectorManager().GetTopmostOSMSectors()) { InitDraw(renderContext.graphicsDevice, allBounds[rootSector], rootSector); } foreach (var rootSector in ZCoords.GetSectorManager().GetTopmostOSMSectors()) { DrawFlat(renderContext.graphicsDevice, allBounds[rootSector], rootSector); } }
private ISector GetSector(double mouseX, double mouseY, double cameraZoom) { int zoom = GetRoundedZoom(cameraZoom); LongLat longLat = new LongLat(mouseX, mouseY); foreach (var sector in ZCoords.GetSectorManager().GetTopmostOSMSectors()) { if (sector.ContainsLongLat(longLat)) { var localCoord = sector.ProjectToLocalCoordinates(longLat.ToSphereVector()); var sectorAt = sector.GetSectorAt(localCoord.X, localCoord.Y, zoom); if (sectorAt != null) { return(sectorAt); } } } return(null); }
// took 21.117584 hours to save 4.19 GB // saved to 6 different files in case it crashes public void LoadAllDetailsFromSource() { int i = 0; foreach (CubeSector root in ZCoords.GetSectorManager().GetTopmostOSMSectors()) { for (int x = 0; x < 256; x++) { for (int y = 0; y < 256; y++) { var sector = new CubeSector(root.sectorFace, x, y, 8); LoadDetailsFromSource(sector); } } SaveAll("planet-meta" + i + ".data"); Clear(); i++; } }
static int READ_BREAKUP_STEP = 0; // easy way to allow continuation, should usually equal (#filesThatArenttoplevel)/3 public static void SegmentOSMPlanet() { READ_BREAKUP_STEP = int.Parse(File.ReadAllText(OSMPaths.GetPlanetStepPath()).Split(',')[0]); // file should contain the number of physical breakups that were finished List <ISector> quadrants = ZCoords.GetSectorManager().GetTopmostOSMSectors(); if (READ_BREAKUP_STEP <= CURRENT_BREAKUP_STEP) { foreach (var quadrant in quadrants) { String quadrantPath = OSMPaths.GetSectorPath(quadrant); if (File.Exists(quadrantPath)) { File.Delete(quadrantPath); // we're assuming it's corrupted } if (!Directory.Exists(Path.GetDirectoryName(quadrantPath))) { Directory.CreateDirectory(Path.GetDirectoryName(quadrantPath)); } var fInfo = new FileInfo(OSMPaths.GetPlanetPath()); using (var fileInfoStream = fInfo.OpenRead()) { using (var source = new PBFOsmStreamSource(fileInfoStream)) { var filtered = source.FilterNodes(x => x.Longitude.HasValue && x.Latitude.HasValue && quadrant.ContainsLongLat(new LongLat(x.Longitude.Value * Math.PI / 180, x.Latitude.Value * Math.PI / 180)), true); using (var stream = new FileInfo(quadrantPath).Open(FileMode.Create, FileAccess.ReadWrite)) { var target = new PBFOsmStreamTarget(stream, true); target.RegisterSource(filtered); target.Pull(); target.Close(); } } } } } BreakupStepDone(); foreach (var quadrant in quadrants) { String quadrantPath = OSMPaths.GetSectorPath(quadrant); BreakupFile(quadrantPath, quadrant, ZCoords.GetSectorManager().GetHighestOSMZoom()); } }
private void Draw3D(GraphicsDevice graphicsDevice, SectorBounds bounds, ISector rootSector, RenderContext.LayerPass layerPass) { double relativeCameraZoom = camera.cameraZoom - Math.Log(ZCoords.GetSectorManager().GetTopmostOSMSectors().Count, 4) + (Game1.RECORDING ? 1 : 0); int zoomLevel = Math.Min(Math.Max((int)(relativeCameraZoom - 3), 0), ZCoords.GetSectorManager().GetHighestOSMZoom()); List <ISector> containedSectors = rootSector.GetSectorsInRange(bounds.minX, bounds.maxX, bounds.minY, bounds.maxY, zoomLevel); List <ISector> sorted = containedSectors.Where(x => x.GetRoot().Equals(rootSector)).ToList(); sorted.Sort((x, y) => x.Zoom.CompareTo(y.Zoom)); foreach (var sector in sorted) { IGraphicsBuffer buffer = loadedMaps[sector]; if (buffer is ImageTileBuffer) { continue; } SectorBounds b = new SectorBounds(bounds.minX * (1 << sector.Zoom) - sector.X, bounds.maxX * (1 << sector.Zoom) - sector.X, bounds.minY * (1 << sector.Zoom) - sector.Y, bounds.maxY * (1 << sector.Zoom) - sector.Y); SectorBounds limitedB = new SectorBounds(Math.Max(0, Math.Min(1, b.minX)), Math.Max(0, Math.Min(1, b.maxX)), Math.Max(0, Math.Min(1, b.minY)), Math.Max(0, Math.Min(1, b.maxY))); BasicEffect basicEffect = new BasicEffect(graphicsDevice); camera.ApplyMatrices(basicEffect); // going to make it easy and assume the shape is perfectly parallel (it's not) // the sector plane is constructed by flattening the visible portion of the sphere, basically Vector3d v1 = sector.ProjectToSphereCoordinates(new Vector2d(limitedB.minX, limitedB.minY)); Vector3d v2 = sector.ProjectToSphereCoordinates(new Vector2d(limitedB.maxX, limitedB.minY)); Vector3d v3 = sector.ProjectToSphereCoordinates(new Vector2d(limitedB.minX, limitedB.maxY)); Vector3d xAxis = (v2 - v1) / (limitedB.maxX - limitedB.minX); Vector3d yAxis = (v3 - v1) / (limitedB.maxY - limitedB.minY); Vector3d start = v1 - xAxis * limitedB.minX - yAxis * limitedB.minY; Vector3d zAxis = start * (xAxis.Length() + yAxis.Length()) / start.Length() / 2; // make this roughly the same length // matrixes copied over Matrixd world = Matrixd.CreateRotationZ(-camera.cameraRotX) * Matrixd.CreateRotationX(camera.cameraRotY); // eh.... think hard on this later double distance = 9 * Math.Pow(0.5, camera.cameraZoom); Matrixd view = CameraMatrixManager.GetWorldViewd(distance); Matrixd projection = CameraMatrixManager.GetWorldProjectiond(distance, graphicsDevice.Viewport.AspectRatio); Matrixd transformMatrix = new Matrixd(xAxis.X, xAxis.Y, xAxis.Z, 0, yAxis.X, yAxis.Y, yAxis.Z, 0, zAxis.X, zAxis.Y, zAxis.Z, 0, start.X, start.Y, start.Z, 1); // turns our local coordinates into 3d spherical coordinates, based on the sector Matrixd WVP = Normalize(transformMatrix * world * view * projection); // combine them all to allow for higher precision RenderContext context = new RenderContext(graphicsDevice, WVP, b.minX, b.maxX, b.minY, b.maxY, camera.cameraZoom, layerPass); buffer.Draw(context); } }
private IGraphicsBuffer GetBuffer(GraphicsDevice graphicsDevice, ISector sector, bool cached) { if (sector.Zoom > ZCoords.GetSectorManager().GetHighestOSMZoom()) { throw new NotImplementedException(); } if (ZCoords.GetSectorManager().GetHighestCacheZoom() > ZCoords.GetSectorManager().GetHighestOSMZoom()) { throw new NotImplementedException(); } try { if ((cached || sector.Zoom != ZCoords.GetSectorManager().GetHighestOSMZoom())) { string path = OSMPaths.GetSectorImagePath(sector); #if WINDOWS || LINUX if (File.Exists(path)) { using (var reader = File.OpenRead(path)) { return(new ImageTileBuffer(graphicsDevice, Texture2D.FromStream(graphicsDevice, reader), sector)); } } #else using (var reader = Activity1.ASSETS.Open(path)) { return(new ImageTileBuffer(graphicsDevice, Texture2D.FromStream(graphicsDevice, reader), sector)); } #endif } } catch (Exception ex) { // sometimes the image is corrupt (or zero bytes) } // otherwise, build it if (sector.Zoom == ZCoords.GetSectorManager().GetHighestOSMZoom()) { if (cached) { // TODO: somehow all of this still breaks often and is pretty slow, but at least we only have to run it once if (sector.Zoom <= ZCoords.GetSectorManager().GetHighestCacheZoom()) { SuperSave(GlobalContent.Error, OSMPaths.GetSectorImagePath(sector)); //RebuildImage(graphicsDevice, sector); } return(new ImageTileBuffer(graphicsDevice, GlobalContent.Error, sector)); } else { try { ProceduralTileBuffer buffer = new ProceduralTileBuffer(sector); Stopwatch sw = new Stopwatch(); sw.Start(); buffer.LoadLinesFromFile(); buffer.GenerateVertices(); buffer.GenerateBuffers(graphicsDevice); Console.WriteLine($"Total load time for {sector} is {sw.Elapsed.TotalSeconds} s"); if (sector.Zoom <= ZCoords.GetSectorManager().GetHighestCacheZoom()) { #if WINDOWS || LINUX using (var image = buffer.GetImage(graphicsDevice)) { SuperSave(image, OSMPaths.GetSectorImagePath(sector)); } RebuildImage(graphicsDevice, sector); #endif } return(buffer); } catch (Exception ex) { if (sector.Zoom <= ZCoords.GetSectorManager().GetHighestCacheZoom()) { SuperSave(GlobalContent.Error, OSMPaths.GetSectorImagePath(sector)); RebuildImage(graphicsDevice, sector); } return(new ImageTileBuffer(graphicsDevice, GlobalContent.Error, sector)); } } } else { throw new NotImplementedException(); } }
internal void LoadAll(string fileName) { OSMMetaManager manager = new OSMMetaManager(); if (fileName.Contains("*")) { for (int i = 0; i < 6; i++) { manager.LoadAll(fileName.Replace("*", i + "")); } } else { manager.LoadAll(fileName); } // init gridPoints = new Dictionary <ISector, GridPointInfo[, ]>(); gridTops = new Dictionary <ISector, GridPointInfo[, ]>(); gridLefts = new Dictionary <ISector, GridPointInfo[, ]>(); foreach (var root in ZCoords.GetSectorManager().GetTopmostOSMSectors()) { GridPointInfo[,] gp = new GridPointInfo[257, 257]; GridPointInfo[,] gt = new GridPointInfo[256, 257]; GridPointInfo[,] gl = new GridPointInfo[257, 256]; for (int x = 0; x < 257; x++) { for (int y = 0; y < 257; y++) { gp[x, y] = new GridPointInfo(); if (x < 256) { gt[x, y] = new GridPointInfo(); } if (y < 256) { gl[x, y] = new GridPointInfo(); } } } gridPoints[root] = gp; gridTops[root] = gt; gridLefts[root] = gl; } // find bad relations foreach (var relation in manager.relationInfo) { if (!IsValidRelation(manager, relation.Key)) { badRelations.Add(relation.Key); } } // process all edge info foreach (var edge in manager.edgeInfo) { if (!manager.wayInfo.ContainsKey(edge.wayID)) { continue; // probably doesn't exist because we've removed it to try and save some memory } foreach (var root in ZCoords.GetSectorManager().GetTopmostOSMSectors()) { var local1 = root.ProjectToLocalCoordinates(edge.longLat1.ToSphereVector()); var local2 = root.ProjectToLocalCoordinates(edge.longLat2.ToSphereVector()); if ((local1 - local2).Length() > 0.2) { continue; } // first, order by X if (local1.X > local2.X) { var temp = local2; local2 = local1; local1 = temp; } for (int x = (int)Math.Ceiling(local1.X * 256); x <= local2.X * 256; x++) { if (x == local1.X * 256) { continue; } double t = (x / 256.0 - local1.X) / (local2.X - local1.X); int y = (int)Math.Floor((local1.Y + t * (local2.Y - local1.Y)) * 256); if (x >= 0 && x < 257 && y >= 0 && y < 256) { XORWithEdge(manager, gridLefts[root][x, y], edge); } } // now, order by Y if (local1.Y > local2.Y) { var temp = local2; local2 = local1; local1 = temp; } for (int y = (int)Math.Ceiling(local1.Y * 256); y <= local2.Y * 256; y++) // BUG: can't believe this was required, but we do sometimes have nodes on exactly the edge, apparently { // ignore the edge that bruhes up exactly against the top (assuming it exists at all, since our original load logic can exclude such an edge) // with a point exactly on an edge, the -other- edge that matches exactly on bottom should trigger the flag instead (double-flag would be bad) if (y == local1.Y * 256) { continue; } double t = (y / 256.0 - local1.Y) / (local2.Y - local1.Y); int x = (int)Math.Floor((local1.X + t * (local2.X - local1.X)) * 256); // BUG: (int) is NOT THE SAME AS Math.Floor! if (x >= 0 && x < 256 && y >= 0 && y < 257) { XORWithEdge(manager, gridTops[root][x, y], edge); } } } } // now actually figure out the points // TODO: we're just doing front for now var frRoot = new CubeSector((CubeSector.CubeSectorFace) int.Parse(Regex.Match(fileName, "[0-9]").Value), 0, 0, 0); if (frRoot.sectorFace == CubeSector.CubeSectorFace.RIGHT || frRoot.sectorFace == CubeSector.CubeSectorFace.BACK) { // invert these faces gridPoints[frRoot][0, 0].naturalTypes.Add(0); } for (int y = 0; y < 257; y++) { for (int x = 0; x < 257; x++) { GridPointInfo prev; GridPointInfo next; GridPointInfo edge; if (x == 0) { if (y == 0) { continue; } prev = gridPoints[frRoot][0, y - 1]; next = gridPoints[frRoot][0, y]; edge = gridLefts[frRoot][0, y - 1]; } else { prev = gridPoints[frRoot][x - 1, y]; next = gridPoints[frRoot][x, y]; edge = gridTops[frRoot][x - 1, y]; } foreach (var n in prev.naturalTypes) { next.naturalTypes.Add(n); } foreach (var n in prev.relations) { next.relations.Add(n); } foreach (var n in prev.ways) { next.ways.Add(n); } foreach (var n in edge.naturalTypes) { if (next.naturalTypes.Contains(n)) { next.naturalTypes.Remove(n); } else { next.naturalTypes.Add(n); } } foreach (var n in edge.relations) { if (next.relations.Contains(n)) { next.relations.Remove(n); } else { next.relations.Add(n); } } foreach (var n in edge.ways) { if (next.ways.Contains(n)) { next.ways.Remove(n); } else { next.ways.Add(n); } } } } SaveAsImage(manager, frRoot); SaveAsFile(manager, frRoot); }
private void InitDraw(GraphicsDevice graphicsDevice, SectorBounds bounds, ISector rootSector) { double relativeCameraZoom = camera.cameraZoom - Math.Log(ZCoords.GetSectorManager().GetTopmostOSMSectors().Count, 4) + (Game1.RECORDING ? 1 : 0); // autoload stuff // TODO: move to update step? int zoomLevel = Math.Min(Math.Max((int)(relativeCameraZoom - 3), 0), ZCoords.GetSectorManager().GetHighestOSMZoom()); List <ISector> containedSectors = rootSector.GetSectorsInRange(bounds.minX, bounds.maxX, bounds.minY, bounds.maxY, zoomLevel); foreach (var pair in loadedMaps.Where(x => AllowUnload(x.Key, rootSector, containedSectors)).ToList()) { loadedMaps[pair.Key].Dispose(); loadedMaps.Remove(pair.Key); } // end autoload stuff if (toLoad != null || Constants.TO_LOAD != null) { if (Constants.TO_LOAD != null) { toLoad = ZCoords.GetSectorManager().FromString(Constants.TO_LOAD); } Stopwatch sw = new Stopwatch(); sw.Start(); foreach (var sector in toLoad.GetChildrenAtLevel(ZCoords.GetSectorManager().GetHighestOSMZoom())) { osmSectorLoader.GetGraphicsBuffer(graphicsDevice, sector).Dispose(); } Console.WriteLine($"Total load time for {toLoad} is {sw.Elapsed.TotalHours} h"); toLoad = null; if (Constants.TO_LOAD != null) { Constants.TERMINATE = true; Constants.TO_LOAD = null; } } bool loadCache = !(relativeCameraZoom - 4 > ZCoords.GetSectorManager().GetHighestOSMZoom()); foreach (var l in containedSectors) { if (loadCache) { if (!loadedMaps.ContainsKey(l)) { loadedMaps[l] = osmSectorLoader.GetCacheBuffer(graphicsDevice, l); } } else { if (!loadedMaps.ContainsKey(l) || loadedMaps[l] is ImageTileBuffer) { if (loadedMaps.ContainsKey(l)) { loadedMaps[l].Dispose(); } loadedMaps[l] = osmSectorLoader.GetGraphicsBuffer(graphicsDevice, l); } } } List <ISector> sorted = containedSectors.Where(x => x.GetRoot().Equals(rootSector)).ToList(); sorted.Sort((x, y) => x.Zoom.CompareTo(y.Zoom)); foreach (var sector in sorted) { IGraphicsBuffer buffer = loadedMaps[sector]; Matrixd projection = Matrixd.CreateOrthographicOffCenter(bounds.minX * (1 << sector.Zoom) - sector.X, bounds.maxX * (1 << sector.Zoom) - sector.X, bounds.maxY * (1 << sector.Zoom) - sector.Y, bounds.minY * (1 << sector.Zoom) - sector.Y, -1, 0.01f); // TODO: why negative? RenderContext context = new RenderContext(graphicsDevice, projection, bounds.minX * (1 << sector.Zoom) - sector.X, bounds.maxX * (1 << sector.Zoom) - sector.X, bounds.minY * (1 << sector.Zoom) - sector.Y, bounds.maxY * (1 << sector.Zoom) - sector.Y, camera.cameraZoom, RenderContext.LayerPass.MAIN_PASS); buffer.InitDraw(context); } }