private void UpdateImagery(ClipmapLevel level, ClipmapLevel coarserLevel, Context context, SceneState sceneState) { int deltaX = level.NextImageryExtent.West - level.CurrentImageryExtent.West; int deltaY = level.NextImageryExtent.South - level.CurrentImageryExtent.South; if (deltaX == 0 && deltaY == 0) { return; } int minLongitude = deltaX > 0 ? level.CurrentImageryExtent.East + 1 : level.NextImageryExtent.West; int maxLongitude = deltaX > 0 ? level.NextImageryExtent.East : level.CurrentImageryExtent.West - 1; int minLatitude = deltaY > 0 ? level.CurrentImageryExtent.North + 1 : level.NextImageryExtent.South; int maxLatitude = deltaY > 0 ? level.NextImageryExtent.North : level.CurrentImageryExtent.South - 1; int width = maxLongitude - minLongitude + 1; int height = maxLatitude - minLatitude + 1; if (level.CurrentImageryExtent.West > level.CurrentImageryExtent.East || // initial update width >= level.ImageryWidth || height >= level.ImageryHeight) // complete update { // Initial or complete update. width = level.ImageryWidth; height = level.ImageryHeight; deltaX = level.ImageryWidth; deltaY = level.ImageryHeight; minLongitude = level.NextImageryExtent.West; maxLongitude = level.NextImageryExtent.East; minLatitude = level.NextImageryExtent.South; maxLatitude = level.NextImageryExtent.North; } if (height > 0) { ClipmapUpdate horizontalUpdate = new ClipmapUpdate( level, level.NextImageryExtent.West, minLatitude, level.NextImageryExtent.East, maxLatitude); _updater.UpdateImagery(context, horizontalUpdate); } if (width > 0) { ClipmapUpdate verticalUpdate = new ClipmapUpdate( level, minLongitude, level.NextImageryExtent.South, maxLongitude, level.NextImageryExtent.North); _updater.UpdateImagery(context, verticalUpdate); } level.CurrentImageryExtent.West = level.NextImageryExtent.West; level.CurrentImageryExtent.South = level.NextImageryExtent.South; level.CurrentImageryExtent.East = level.NextImageryExtent.East; level.CurrentImageryExtent.North = level.NextImageryExtent.North; }
private void UpdateNormals(Context context, ClipmapUpdate update) { ClipmapLevel level = update.Level; context.TextureUnits[0].Texture = update.Level.HeightTexture; context.TextureUnits[0].TextureSampler = Device.TextureSamplers.NearestRepeat; _framebuffer.ColorAttachments[_normalOutput] = level.NormalTexture; int clipmapSize = level.NextExtent.East - level.NextExtent.West + 1; int west = (level.OriginInTextures.X + (update.West - level.NextExtent.West)) % clipmapSize; int south = (level.OriginInTextures.Y + (update.South - level.NextExtent.South)) % clipmapSize; _computeNormalsUpdateSize.Value = new Vector2F(update.Width, update.Height); _computeNormalsOrigin.Value = new Vector2F(west, south); _computeNormalsOneOverHeightMapSize.Value = new Vector2F(1.0f / update.Level.HeightTexture.Description.Width, 1.0f / update.Level.HeightTexture.Description.Height); _postDelta.Value = (float)update.Level.Terrain.PostDeltaLongitude; // Save the current state of the context Rectangle oldViewport = context.Viewport; Framebuffer oldFramebuffer = context.Framebuffer; // Update the context and draw context.Viewport = new Rectangle(0, 0, level.NormalTexture.Description.Width, level.NormalTexture.Description.Height); context.Framebuffer = _framebuffer; context.Draw(_unitQuadPrimitiveType, _computeNormalsDrawState, _sceneState); // Restore the context to its original state context.Framebuffer = oldFramebuffer; context.Viewport = oldViewport; }
private void Update(Context context, ClipmapUpdate update, ClipmapLevel level, RasterDataDetails details, RasterLevel rasterLevel) { ClipmapUpdate[] updates = SplitUpdateToAvoidWrapping(update, details); foreach (ClipmapUpdate nonWrappingUpdate in updates) { RasterTileRegion[] tileRegions = rasterLevel.GetTilesInExtent(nonWrappingUpdate.West, nonWrappingUpdate.South, nonWrappingUpdate.East, nonWrappingUpdate.North); foreach (RasterTileRegion region in tileRegions) { Texture2D tileTexture; bool loaded = details.LoadedTiles.TryGetValue(region.Tile.Identifier, out tileTexture); if (loaded) { RenderTileToLevelTexture(context, level, details, region, tileTexture); } else { UpsampleTileData(context, level, details, region); } } } if (details.Type == RasterType.Terrain) { // Normals at edges are incorrect, so include a one-post buffer around the update region // when updating normals in order to update normals that were previously at the edge. ClipmapUpdate updateWithBuffer = update.AddBufferWithinLevelNextExtent(); ClipmapUpdate[] normalUpdates = SplitUpdateToAvoidWrapping(updateWithBuffer, details); foreach (ClipmapUpdate normalUpdate in normalUpdates) { UpdateNormals(context, normalUpdate); } } }
private ClipmapUpdate IntersectUpdates(ClipmapUpdate first, ClipmapUpdate second) { int west = Math.Max(first.West, second.West); int south = Math.Max(first.South, second.South); int east = Math.Min(first.East, second.East); int north = Math.Min(first.North, second.North); return(new ClipmapUpdate(first.Level, west, south, east, north)); }
private void ApplyNewTile(Context context, RasterDataDetails details, ClipmapLevel level, RasterTile tile) { ClipmapLevel.Extent nextExtent = details.Type == RasterType.Terrain ? level.NextExtent : level.NextImageryExtent; RasterLevel rasterLevel = details.Type == RasterType.Terrain ? level.Terrain : level.Imagery; ClipmapUpdate entireLevel = new ClipmapUpdate( level, nextExtent.West, nextExtent.South, nextExtent.East, nextExtent.North); ClipmapUpdate thisTile = new ClipmapUpdate( level, tile.West - 1, tile.South - 1, tile.East + 1, tile.North + 1); ClipmapUpdate intersection = IntersectUpdates(entireLevel, thisTile); if (intersection.Width > 0 && intersection.Height > 0) { Update(context, intersection, level, details, rasterLevel); // Recurse on child tiles if they're NOT loaded. Unloaded children will use data from this tile. ClipmapLevel finer = level.FinerLevel; if (finer != null) { ApplyIfNotLoaded(context, details, finer, tile.SouthwestChild); ApplyIfNotLoaded(context, details, finer, tile.SoutheastChild); ApplyIfNotLoaded(context, details, finer, tile.NorthwestChild); ApplyIfNotLoaded(context, details, finer, tile.NortheastChild); } } }
private void UpdateImagery(ClipmapLevel level, ClipmapLevel coarserLevel, Context context, SceneState sceneState) { int deltaX = level.NextImageryExtent.West - level.CurrentImageryExtent.West; int deltaY = level.NextImageryExtent.South - level.CurrentImageryExtent.South; if (deltaX == 0 && deltaY == 0) return; int minLongitude = deltaX > 0 ? level.CurrentImageryExtent.East + 1 : level.NextImageryExtent.West; int maxLongitude = deltaX > 0 ? level.NextImageryExtent.East : level.CurrentImageryExtent.West - 1; int minLatitude = deltaY > 0 ? level.CurrentImageryExtent.North + 1 : level.NextImageryExtent.South; int maxLatitude = deltaY > 0 ? level.NextImageryExtent.North : level.CurrentImageryExtent.South - 1; int width = maxLongitude - minLongitude + 1; int height = maxLatitude - minLatitude + 1; if (level.CurrentImageryExtent.West > level.CurrentImageryExtent.East || // initial update width >= level.ImageryWidth || height >= level.ImageryHeight) // complete update { // Initial or complete update. width = level.ImageryWidth; height = level.ImageryHeight; deltaX = level.ImageryWidth; deltaY = level.ImageryHeight; minLongitude = level.NextImageryExtent.West; maxLongitude = level.NextImageryExtent.East; minLatitude = level.NextImageryExtent.South; maxLatitude = level.NextImageryExtent.North; } if (height > 0) { ClipmapUpdate horizontalUpdate = new ClipmapUpdate( level, level.NextImageryExtent.West, minLatitude, level.NextImageryExtent.East, maxLatitude); _updater.UpdateImagery(context, horizontalUpdate); } if (width > 0) { ClipmapUpdate verticalUpdate = new ClipmapUpdate( level, minLongitude, level.NextImageryExtent.South, maxLongitude, level.NextImageryExtent.North); _updater.UpdateImagery(context, verticalUpdate); } level.CurrentImageryExtent.West = level.NextImageryExtent.West; level.CurrentImageryExtent.South = level.NextImageryExtent.South; level.CurrentImageryExtent.East = level.NextImageryExtent.East; level.CurrentImageryExtent.North = level.NextImageryExtent.North; }
private ClipmapUpdate[] SplitUpdateToAvoidWrapping(ClipmapUpdate update, RasterDataDetails details) { ClipmapLevel level = update.Level; Vector2I origin = details.Type == RasterType.Terrain ? level.OriginInTextures : level.OriginInImagery; ClipmapLevel.Extent extent = details.Type == RasterType.Terrain ? level.NextExtent : level.NextImageryExtent; int clipmapSizeX = extent.East - extent.West + 1; int clipmapSizeY = extent.North - extent.South + 1; int west = (origin.X + (update.West - extent.West)) % clipmapSizeX; int east = (origin.X + (update.East - extent.West)) % clipmapSizeX; int south = (origin.Y + (update.South - extent.South)) % clipmapSizeY; int north = (origin.Y + (update.North - extent.South)) % clipmapSizeY; if (east < west && north < south) { // Horizontal AND vertical wrap ClipmapUpdate bottomLeftUpdate = new ClipmapUpdate( level, update.West, update.South, extent.West + (clipmapSizeX - origin.X - 1), extent.South + (clipmapSizeY - origin.Y - 1)); ClipmapUpdate bottomRightUpdate = new ClipmapUpdate( level, extent.West + clipmapSizeX - origin.X, update.South, update.East, extent.South + (clipmapSizeY - origin.Y - 1)); ClipmapUpdate topLeftUpdate = new ClipmapUpdate( level, update.West, extent.South + clipmapSizeY - origin.Y, extent.West + (clipmapSizeX - origin.X - 1), update.North); ClipmapUpdate topRightUpdate = new ClipmapUpdate( level, extent.West + clipmapSizeX - origin.X, extent.South + clipmapSizeY - origin.Y, update.East, update.North); ClipmapUpdate[] result = new ClipmapUpdate[4]; result[0] = bottomLeftUpdate; result[1] = bottomRightUpdate; result[2] = topLeftUpdate; result[3] = topRightUpdate; return(result); } else if (east < west) { // Horizontal wrap ClipmapUpdate leftUpdate = new ClipmapUpdate( level, update.West, update.South, extent.West + (clipmapSizeX - origin.X - 1), update.North); ClipmapUpdate rightUpdate = new ClipmapUpdate( level, extent.West + clipmapSizeX - origin.X, update.South, update.East, update.North); ClipmapUpdate[] result = new ClipmapUpdate[2]; result[0] = leftUpdate; result[1] = rightUpdate; return(result); } else if (north < south) { // Vertical wrap ClipmapUpdate bottomUpdate = new ClipmapUpdate( level, update.West, update.South, update.East, extent.South + (clipmapSizeY - origin.Y - 1)); ClipmapUpdate topUpdate = new ClipmapUpdate( level, update.West, extent.South + clipmapSizeY - origin.Y, update.East, update.North); ClipmapUpdate[] result = new ClipmapUpdate[2]; result[0] = bottomUpdate; result[1] = topUpdate; return(result); } else { // No wrap ClipmapUpdate[] result = new ClipmapUpdate[1]; result[0] = update; return(result); } }
public void UpdateImagery(Context context, ClipmapUpdate update) { ClipmapLevel level = update.Level; Update(context, update, level, _imagery, level.Imagery); }
public void UpdateTerrain(Context context, ClipmapUpdate update) { ClipmapLevel level = update.Level; Update(context, update, level, _terrain, level.Terrain); }
private ClipmapUpdate[] SplitUpdateToAvoidWrapping(ClipmapUpdate update, RasterDataDetails details) { ClipmapLevel level = update.Level; Vector2I origin = details.Type == RasterType.Terrain ? level.OriginInTextures : level.OriginInImagery; ClipmapLevel.Extent extent = details.Type == RasterType.Terrain ? level.NextExtent : level.NextImageryExtent; int clipmapSizeX = extent.East - extent.West + 1; int clipmapSizeY = extent.North - extent.South + 1; int west = (origin.X + (update.West - extent.West)) % clipmapSizeX; int east = (origin.X + (update.East - extent.West)) % clipmapSizeX; int south = (origin.Y + (update.South - extent.South)) % clipmapSizeY; int north = (origin.Y + (update.North - extent.South)) % clipmapSizeY; if (east < west && north < south) { // Horizontal AND vertical wrap ClipmapUpdate bottomLeftUpdate = new ClipmapUpdate( level, update.West, update.South, extent.West + (clipmapSizeX - origin.X - 1), extent.South + (clipmapSizeY - origin.Y - 1)); ClipmapUpdate bottomRightUpdate = new ClipmapUpdate( level, extent.West + clipmapSizeX - origin.X, update.South, update.East, extent.South + (clipmapSizeY - origin.Y - 1)); ClipmapUpdate topLeftUpdate = new ClipmapUpdate( level, update.West, extent.South + clipmapSizeY - origin.Y, extent.West + (clipmapSizeX - origin.X - 1), update.North); ClipmapUpdate topRightUpdate = new ClipmapUpdate( level, extent.West + clipmapSizeX - origin.X, extent.South + clipmapSizeY - origin.Y, update.East, update.North); ClipmapUpdate[] result = new ClipmapUpdate[4]; result[0] = bottomLeftUpdate; result[1] = bottomRightUpdate; result[2] = topLeftUpdate; result[3] = topRightUpdate; return result; } else if (east < west) { // Horizontal wrap ClipmapUpdate leftUpdate = new ClipmapUpdate( level, update.West, update.South, extent.West + (clipmapSizeX - origin.X - 1), update.North); ClipmapUpdate rightUpdate = new ClipmapUpdate( level, extent.West + clipmapSizeX - origin.X, update.South, update.East, update.North); ClipmapUpdate[] result = new ClipmapUpdate[2]; result[0] = leftUpdate; result[1] = rightUpdate; return result; } else if (north < south) { // Vertical wrap ClipmapUpdate bottomUpdate = new ClipmapUpdate( level, update.West, update.South, update.East, extent.South + (clipmapSizeY - origin.Y - 1)); ClipmapUpdate topUpdate = new ClipmapUpdate( level, update.West, extent.South + clipmapSizeY - origin.Y, update.East, update.North); ClipmapUpdate[] result = new ClipmapUpdate[2]; result[0] = bottomUpdate; result[1] = topUpdate; return result; } else { // No wrap ClipmapUpdate[] result = new ClipmapUpdate[1]; result[0] = update; return result; } }
private ClipmapUpdate IntersectUpdates(ClipmapUpdate first, ClipmapUpdate second) { int west = Math.Max(first.West, second.West); int south = Math.Max(first.South, second.South); int east = Math.Min(first.East, second.East); int north = Math.Min(first.North, second.North); return new ClipmapUpdate(first.Level, west, south, east, north); }