Skip to content

Commit

Permalink
add i3dm export option
Browse files Browse the repository at this point in the history
  • Loading branch information
bertt committed Jul 24, 2024
1 parent 4deffc2 commit 5d8712a
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 31 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
34 changes: 27 additions & 7 deletions src/ImplicitTiling.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Wkx;

namespace i3dm.export;
Expand All @@ -29,7 +30,7 @@ public static byte[] GetSubtreeBytes(string tileAvailability, string contentAvai
return subtreebytes;
}

public static List<Tile> GenerateTiles(Options o, NpgsqlConnection conn, BoundingBox bbox, Tile tile, List<Tile> tiles, string contentDirectory, int source_epsg, bool useGpuInstancing = false)
public static List<Tile> GenerateTiles(Options o, NpgsqlConnection conn, BoundingBox bbox, Tile tile, List<Tile> tiles, string contentDirectory, int source_epsg, bool useGpuInstancing = false, bool useI3dm = false)
{
var where = (o.Query != string.Empty ? $" and {o.Query}" : String.Empty);

Expand Down Expand Up @@ -62,14 +63,18 @@ public static List<Tile> 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} ");

Expand All @@ -83,12 +88,27 @@ public static List<Tile> 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;
}
}
3 changes: 3 additions & 0 deletions src/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
}
Expand Down
5 changes: 2 additions & 3 deletions src/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using ShellProgressBar;
using subtree;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
Expand Down Expand Up @@ -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<Tile>(), contentDirectory, source_epsg, (bool)o.UseGpuInstancing);
var tiles = ImplicitTiling.GenerateTiles(o, conn, bbox_wgs84, tile, new List<Tile>(), contentDirectory, source_epsg, (bool)o.UseGpuInstancing, (bool)o.UseI3dm);

Console.WriteLine();
Console.WriteLine($"Tiles written: {tiles.Count}");
Expand All @@ -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);
Expand Down
32 changes: 19 additions & 13 deletions src/I3dmTileHandler.cs → src/TileHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,40 @@

namespace i3dm.export;

public static class I3dmTileHandler
public static class TileHandler
{
public static byte[] GetTile(List<Instance> instances, bool UseExternalModel = false, bool UseScaleNonUniform = false)
public static byte[] GetCmptTile(List<Instance> instances, bool UseExternalModel = false, bool UseScaleNonUniform = false)
{
var uniqueModels = instances.Select(s => s.Model).Distinct();

var tiles = new List<byte[]>();

foreach (var model in uniqueModels)
{
var positions = new List<Vector3>();
var scales = new List<float>();
var scalesNonUniform = new List<Vector3>();
var normalUps = new List<Vector3>();
var normalRights = new List<Vector3>();
var modelInstances = instances.Where(s => s.Model.Equals(model)).ToList();

var tags = new List<JArray>();
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);
}

var bytes = CmptWriter.Write(tiles);
return bytes;
}

public static byte[] GetI3dmTile(List<Instance> instances, bool UseExternalModel, bool UseScaleNonUniform, object model)
{
var positions = new List<Vector3>();
var scales = new List<float>();
var scalesNonUniform = new List<Vector3>();
var normalUps = new List<Vector3>();
var normalRights = new List<Vector3>();
var modelInstances = instances.Where(s => s.Model.Equals(model)).ToList();

var tags = new List<JArray>();
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<Instance> instances, bool UseScaleNonUniform, List<Vector3> positions, List<float> scales, List<Vector3> scalesNonUniform, List<Vector3> normalUps, List<Vector3> normalRights, List<JArray> tags)
{
foreach (var instance in instances)
Expand Down
6 changes: 5 additions & 1 deletion src/TreeSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/i3dm.export.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<PackageReference Include="cmpt-tile" Version="0.2.4" />
<PackageReference Include="CommandLineParser" Version="2.9.1" />
<PackageReference Include="Dapper" Version="2.1.35" />
<PackageReference Include="i3dm.tile" Version="1.0.0" />
<PackageReference Include="i3dm.tile" Version="1.1.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Npgsql" Version="8.0.3" />
<PackageReference Include="SharpGLTF.Ext.3DTiles" Version="1.0.1" />
Expand Down
12 changes: 6 additions & 6 deletions tests/TileHandlerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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()));

Expand All @@ -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()));

Expand All @@ -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()));

Expand All @@ -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()));

Expand Down

0 comments on commit 5d8712a

Please sign in to comment.