diff --git a/README.md b/README.md index 6223413..daf36cb 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,8 @@ Tool parameters: --use_gpu_instancing (optional - default false) Use GPU instancing (only for Cesium) +--use_i3dm (optional - default false) Use I3dm format - only first model will be processed (false creates Cmpt) + --boundingvolume_heights (option - default: 0,10) - Tile boundingVolume heights (min, max) in meters. The heights will be added to the z_min and z_max values of the input geometries. ``` # Docker diff --git a/src/ImplicitTiling.cs b/src/ImplicitTiling.cs index e417478..0db9900 100644 --- a/src/ImplicitTiling.cs +++ b/src/ImplicitTiling.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using Wkx; namespace i3dm.export; @@ -29,7 +30,7 @@ public static byte[] GetSubtreeBytes(string tileAvailability, string contentAvai return subtreebytes; } - public static List GenerateTiles(Options o, NpgsqlConnection conn, BoundingBox bbox, Tile tile, List tiles, string contentDirectory, int source_epsg, bool useGpuInstancing = false) + public static List GenerateTiles(Options o, NpgsqlConnection conn, BoundingBox bbox, Tile tile, List tiles, string contentDirectory, int source_epsg, bool useGpuInstancing = false, bool useI3dm = false) { var where = (o.Query != string.Empty ? $" and {o.Query}" : String.Empty); @@ -62,14 +63,18 @@ public static List GenerateTiles(Options o, NpgsqlConnection conn, Boundin var bboxQuad = new BoundingBox(xstart, ystart, xend, yend); var new_tile = new Tile(tile.Z + 1, tile.X * 2 + x, tile.Y * 2 + y); - GenerateTiles(o, conn, bboxQuad, new_tile, tiles, contentDirectory, source_epsg, useGpuInstancing); + GenerateTiles(o, conn, bboxQuad, new_tile, tiles, contentDirectory, source_epsg, useGpuInstancing, useI3dm); } } } else { - var bytes = CreateTile(o, conn, bbox, source_epsg, where, useGpuInstancing); + var bytes = CreateTile(o, conn, bbox, source_epsg, where, useGpuInstancing, useI3dm); var extension = useGpuInstancing? "glb": "cmpt"; + if (useI3dm) + { + extension = "i3dm"; + } var file = $"{contentDirectory}{Path.AltDirectorySeparatorChar}{tile.Z}_{tile.X}_{tile.Y}.{extension}"; Console.Write($"\rCreating tile: {file} "); @@ -83,12 +88,27 @@ public static List GenerateTiles(Options o, NpgsqlConnection conn, Boundin return tiles; } - private static byte[] CreateTile(Options o, NpgsqlConnection conn, BoundingBox tileBounds, int source_epsg, string where, bool useGpuInstancing = false) + private static byte[] CreateTile(Options o, NpgsqlConnection conn, BoundingBox tileBounds, int source_epsg, string where, bool useGpuInstancing = false, bool useI3dm = false) { var instances = InstancesRepository.GetInstances(conn, o.Table, o.GeometryColumn, tileBounds, source_epsg, where, (bool)o.UseScaleNonUniform, useGpuInstancing); - var tile = useGpuInstancing? - GPUTileHandler.GetGPUTile(instances, (bool)o.UseScaleNonUniform): - I3dmTileHandler.GetTile(instances, (bool)o.UseExternalModel, (bool)o.UseScaleNonUniform); + byte[] tile; + + if (useGpuInstancing) + { + + tile = GPUTileHandler.GetGPUTile(instances, (bool)o.UseScaleNonUniform); + } + else if(!useI3dm) + { + // create cmpt + tile = TileHandler.GetCmptTile(instances, (bool)o.UseExternalModel, (bool)o.UseScaleNonUniform); + } + else + { + // take the first model for i3dm + tile = TileHandler.GetI3dmTile(instances, (bool)o.UseExternalModel, (bool)o.UseScaleNonUniform, instances.First().Model); + } + return tile; } } diff --git a/src/Options.cs b/src/Options.cs index a787614..8b8bc7e 100644 --- a/src/Options.cs +++ b/src/Options.cs @@ -34,6 +34,9 @@ public class Options [Option("use_gpu_instancing", Required = false, Default = false, HelpText = "Use EXT_mesh_gpu_instancing instead of I3dm's")] public bool? UseGpuInstancing { get; set; } + [Option("use_i3dm", Required = false, Default = false, HelpText = "Use i3dm instead of cmpt's")] + public bool? UseI3dm { get; set; } + [Option("boundingvolume_heights", Required = false, Default = "0,10", HelpText = "Tile boundingVolume heights (min, max) in meters")] public string BoundingVolumeHeights { get; set; } } diff --git a/src/Program.cs b/src/Program.cs index c7de834..df059d5 100644 --- a/src/Program.cs +++ b/src/Program.cs @@ -6,7 +6,6 @@ using ShellProgressBar; using subtree; using System; -using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -118,7 +117,7 @@ static void Main(string[] args) Console.WriteLine("Start generating tiles..."); var tile = new Tile(0, 0, 0); - var tiles = ImplicitTiling.GenerateTiles(o, conn, bbox_wgs84, tile, new List(), contentDirectory, source_epsg, (bool)o.UseGpuInstancing); + var tiles = ImplicitTiling.GenerateTiles(o, conn, bbox_wgs84, tile, new List(), contentDirectory, source_epsg, (bool)o.UseGpuInstancing, (bool)o.UseI3dm); Console.WriteLine(); Console.WriteLine($"Tiles written: {tiles.Count}"); @@ -134,7 +133,7 @@ static void Main(string[] args) var subtreeLevels = subtreeFiles.Count > 1 ? ((Tile)subtreeFiles.ElementAt(1).Key).Z : 2; var availableLevels = tiles.Max(t => t.Z) + 1; - var tilesetjson = TreeSerializer.ToImplicitTileset(rootBoundingVolumeRegion, o.GeometricError, availableLevels, subtreeLevels, version, (bool)o.UseGpuInstancing); + var tilesetjson = TreeSerializer.ToImplicitTileset(rootBoundingVolumeRegion, o.GeometricError, availableLevels, subtreeLevels, version, (bool)o.UseGpuInstancing, (bool)o.UseI3dm); var file = $"{o.Output}{Path.AltDirectorySeparatorChar}tileset.json"; Console.WriteLine($"Subtree files written: {subtreeFiles.Count}"); Console.WriteLine("SubtreeLevels: " + subtreeLevels); diff --git a/src/I3dmTileHandler.cs b/src/TileHandler.cs similarity index 73% rename from src/I3dmTileHandler.cs rename to src/TileHandler.cs index 6825409..051f77a 100644 --- a/src/I3dmTileHandler.cs +++ b/src/TileHandler.cs @@ -9,9 +9,9 @@ namespace i3dm.export; -public static class I3dmTileHandler +public static class TileHandler { - public static byte[] GetTile(List instances, bool UseExternalModel = false, bool UseScaleNonUniform = false) + public static byte[] GetCmptTile(List instances, bool UseExternalModel = false, bool UseScaleNonUniform = false) { var uniqueModels = instances.Select(s => s.Model).Distinct(); @@ -19,17 +19,7 @@ public static byte[] GetTile(List instances, bool UseExternalModel = f foreach (var model in uniqueModels) { - var positions = new List(); - var scales = new List(); - var scalesNonUniform = new List(); - var normalUps = new List(); - var normalRights = new List(); - var modelInstances = instances.Where(s => s.Model.Equals(model)).ToList(); - - var tags = new List(); - CalculateArrays(modelInstances, UseScaleNonUniform, positions, scales, scalesNonUniform, normalUps, normalRights, tags); - var i3dm = GetI3dm(model, positions, scales, scalesNonUniform, normalUps, normalRights, tags, UseExternalModel, UseScaleNonUniform); - var bytesI3dm = I3dmWriter.Write(i3dm); + var bytesI3dm = GetI3dmTile(instances, UseExternalModel, UseScaleNonUniform, model); tiles.Add(bytesI3dm); } @@ -37,6 +27,22 @@ public static byte[] GetTile(List instances, bool UseExternalModel = f return bytes; } + public static byte[] GetI3dmTile(List instances, bool UseExternalModel, bool UseScaleNonUniform, object model) + { + var positions = new List(); + var scales = new List(); + var scalesNonUniform = new List(); + var normalUps = new List(); + var normalRights = new List(); + var modelInstances = instances.Where(s => s.Model.Equals(model)).ToList(); + + var tags = new List(); + CalculateArrays(modelInstances, UseScaleNonUniform, positions, scales, scalesNonUniform, normalUps, normalRights, tags); + var i3dm = GetI3dm(model, positions, scales, scalesNonUniform, normalUps, normalRights, tags, UseExternalModel, UseScaleNonUniform); + var bytesI3dm = I3dmWriter.Write(i3dm); + return bytesI3dm; + } + internal static void CalculateArrays(List instances, bool UseScaleNonUniform, List positions, List scales, List scalesNonUniform, List normalUps, List normalRights, List tags) { foreach (var instance in instances) diff --git a/src/TreeSerializer.cs b/src/TreeSerializer.cs index 3d33991..b2c6e0b 100644 --- a/src/TreeSerializer.cs +++ b/src/TreeSerializer.cs @@ -6,7 +6,7 @@ namespace i3dm.export; public static class TreeSerializer { - public static string ToImplicitTileset(double[] box, double geometricError, int availableLevels, int subtreeLevels, Version version, bool useGpuInstancing = false) + public static string ToImplicitTileset(double[] box, double geometricError, int availableLevels, int subtreeLevels, Version version, bool useGpuInstancing = false, bool useI3dm = false) { var tileset = new TileSet { @@ -15,6 +15,10 @@ public static string ToImplicitTileset(double[] box, double geometricError, int }; var root = GetRoot(geometricError, box, "ADD"); var extension = useGpuInstancing ? "glb" : "cmpt"; + if(useI3dm) + { + extension = "i3dm"; + } var content = new Content() { uri = "content/{level}_{x}_{y}." + extension }; root.content = content; diff --git a/src/i3dm.export.csproj b/src/i3dm.export.csproj index f510121..1a5c179 100644 --- a/src/i3dm.export.csproj +++ b/src/i3dm.export.csproj @@ -24,7 +24,7 @@ - + diff --git a/tests/TileHandlerTests.cs b/tests/TileHandlerTests.cs index 71a810e..85e8e11 100644 --- a/tests/TileHandlerTests.cs +++ b/tests/TileHandlerTests.cs @@ -60,7 +60,7 @@ public void GetTileTest() instances.Add(instance); // act - var tile = I3dmTileHandler.GetTile(instances); + var tile = TileHandler.GetCmptTile(instances); var cmpt = CmptReader.Read(new MemoryStream(tile)); var i3dmBytes = cmpt.Tiles.First(); var i3dm = I3dmReader.Read(new MemoryStream(i3dmBytes)); @@ -96,7 +96,7 @@ public void GetCompositeTileTest() instances.Add(instance3); // act - var tile = I3dmTileHandler.GetTile(instances, UseExternalModel: true); + var tile = TileHandler.GetCmptTile(instances, UseExternalModel: true); var cmpt = CmptReader.Read(new MemoryStream(tile)); // assert @@ -126,7 +126,7 @@ public void GetTileWithScaleNonUniformTest() instances.Add(instance); // act - var tile = I3dmTileHandler.GetTile(instances, UseScaleNonUniform: true); + var tile = TileHandler.GetCmptTile(instances, UseScaleNonUniform: true); var cmpt = CmptReader.Read(new MemoryStream(tile)); var i3dm = I3dmReader.Read(new MemoryStream(cmpt.Tiles.First())); @@ -148,7 +148,7 @@ public void GetTileWithExternalModelTest() instances.Add(instance); // act - var tile = I3dmTileHandler.GetTile(instances, UseExternalModel: true); + var tile = TileHandler.GetCmptTile(instances, UseExternalModel: true); var cmpt = CmptReader.Read(new MemoryStream(tile)); var i3dm = I3dmReader.Read(new MemoryStream(cmpt.Tiles.First())); @@ -175,7 +175,7 @@ public void GetTileWithRtcCenterTest() instances.Add(instance1); // act - var tile = I3dmTileHandler.GetTile(instances); + var tile = TileHandler.GetCmptTile(instances); var cmpt = CmptReader.Read(new MemoryStream(tile)); var i3dm = I3dmReader.Read(new MemoryStream(cmpt.Tiles.First())); @@ -199,7 +199,7 @@ public void GetTileWithTagsTest() instances.Add(instance); // act - var tile = I3dmTileHandler.GetTile(instances); + var tile = TileHandler.GetCmptTile(instances); var cmpt = CmptReader.Read(new MemoryStream(tile)); var i3dm = I3dmReader.Read(new MemoryStream(cmpt.Tiles.First()));