Skip to content

Commit

Permalink
add gpu instancing metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
bertt committed Mar 28, 2024
1 parent 39b2a34 commit b252cc1
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 17 deletions.
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,11 @@ There is an experimental option to create 3D Tiles 1.1 using GPU instancing: --u

This option is currently in development.

The following features should work: Positioning, Rotation (roll, pitch, yaw) and Scaling of instances.
The following features should work:

- Attribute information from tags using EXT_structural_metadata, EXT_mesh_gpu_instancing and EXT_instance_features.

- Positioning, Rotation (roll, pitch, yaw) and Scaling of instances.

To use this option, the input table should contain columns 'roll', 'pitch' and 'yaw' (column 'rotation' is not used).

Expand All @@ -217,9 +221,9 @@ alter table instances drop column rotation

The columns should be filled with radian angles (0 - 2PI).

The following features are not yet supported when using use_gpu_instancing:
Known limits:

- batch information (EXT_Mesh_Features/EXT_Structural_Metadata)
- When using GPU instancing, the column type 'string' is used (so no support for other types yet).

- composite tiles (formerly known as cmpt). When there are multiple models in the input table only the first one is used.

Expand Down Expand Up @@ -253,6 +257,8 @@ To Visualize in CesiumJS, add references to:

## History

2023-03-28: release 2.7.0: add support for EXT_structural_metadata

2023-11-08: release 2.6.0: Add support for GPU instancing (experimental), removed option -r RTC_CENTER

2023-10-18: release 2.5.0: Improved root bounding volume calculation, improved batch table handling
Expand Down
2 changes: 2 additions & 0 deletions src/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using i3dm.export.Cesium;
using i3dm.export.extensions;
using Npgsql;
using SharpGLTF.Schema2;
using ShellProgressBar;
using subtree;
using System;
Expand Down Expand Up @@ -97,6 +98,7 @@ static void Main(string[] args)
if ((bool)o.UseGpuInstancing)
{
translate = new Vector3((float)center_wgs84.X, (float)center_wgs84.Y, (float)center_wgs84.Z);
Tiles3DExtensions.RegisterExtensions();
}

var options = new ProgressBarOptions
Expand Down
57 changes: 50 additions & 7 deletions src/TileHandler.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
using Cmpt.Tile;
using i3dm.export.Cesium;
using I3dm.Tile;
using Newtonsoft.Json.Linq;
using SharpGLTF.Geometry.VertexTypes;
using SharpGLTF.Geometry;
using SharpGLTF.Scenes;
using SharpGLTF.Schema2;
using SharpGLTF.Transforms;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Numerics;
using Wkx;
using System.Text.Json.Nodes;
using SharpGLTF.Schema2.Tiles3D;

namespace i3dm.export;

Expand Down Expand Up @@ -46,7 +44,12 @@ public static byte[] GetTile(List<Instance> instances, Format format, Vector3 tr

if (useGpuInstancing)
{
var bytesGlb = GetGpuGlb(model, modelInstances, translate, UseScaleNonUniform);
foreach (var instance in instances)
{
tags.Add(instance.Tags);
}

var bytesGlb = GetGpuGlb(model, modelInstances, translate, UseScaleNonUniform, tags);
tiles.Add(bytesGlb);
}
else
Expand Down Expand Up @@ -94,13 +97,15 @@ private static Vector3 GetPosition(Point p, Vector3 translate)
return vec;
}

private static byte[] GetGpuGlb(object model, List<Instance> positions, Vector3 translate, bool UseScaleNonUniform)
private static byte[] GetGpuGlb(object model, List<Instance> positions, Vector3 translate, bool UseScaleNonUniform, List<JArray> tags)
{
var modelRoot = ModelRoot.Load((string)model);
var meshBuilder = modelRoot.LogicalMeshes.First().ToMeshBuilder();

var sceneBuilder = new SceneBuilder();

var pointId = 0;

foreach (var p in positions)
{
var point = (Point)p.Position;
Expand All @@ -124,12 +129,50 @@ private static byte[] GetGpuGlb(object model, List<Instance> positions, Vector3
scale,
quaternion,
translation);
sceneBuilder.AddRigidMesh(meshBuilder, transformation);
var json = "{\"_FEATURE_ID_0\":" + pointId + "}";
sceneBuilder.AddRigidMesh(meshBuilder, transformation).WithExtras(JsonNode.Parse(json));
pointId++;
}

var settings = SceneBuilderSchema2Settings.WithGpuInstancing;
settings.GpuMeshInstancingMinCount = 0;
var gltf = sceneBuilder.ToGltf2(settings);

var rootMetadata = gltf.UseStructuralMetadata();
var schema = rootMetadata.UseEmbeddedSchema("schema");
var schemaClass = schema.UseClassMetadata("propertyTable");

if(tags.Count > 0)
{
var propertyTable = schemaClass.AddPropertyTable(positions.Count);

if (tags[0] != null)
{
var properties = TinyJson.GetProperties(tags[0]);
foreach(var property in properties)
{
var values = TinyJson.GetValues(tags, property);

var nameProperty = schemaClass
.UseProperty(property)
.WithStringType();

// todo: use other types than string
var strings = values.Select(s => s.ToString()).ToArray();

propertyTable
.UseProperty(nameProperty)
.SetValues(strings);
}
}


var featureId0 = new FeatureIDBuilder(positions.Count, 0, propertyTable);
gltf.LogicalNodes[0].AddInstanceFeatureIds(featureId0);

}


var bytes = gltf.WriteGLB().Array;
return bytes;
}
Expand Down
2 changes: 1 addition & 1 deletion src/TinyJson.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public static string ToJson(List<JArray> tags, List<string> properties)
return resres;
}

private static List<object> GetValues(List<JArray> tags, string prop)
public static List<object> GetValues(List<JArray> tags, string prop)
{
var res = new List<Object>();
foreach (var tag in tags)
Expand Down
23 changes: 17 additions & 6 deletions tests/TileHandlerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using I3dm.Tile;
using Newtonsoft.Json.Linq;
using NUnit.Framework;
using SharpGLTF.Schema2;
using SharpGLTF.Schema2.Tiles3D;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Expand All @@ -14,29 +16,38 @@ public class TileHandlerTests
[Test]
public void GetGpuTileTest()
{
Tiles3DExtensions.RegisterExtensions();

// arrange
var instances = new List<Instance>();
var instance = new Instance();
instance.Position = new Wkx.Point(1, 2, 0);
instance.Scale = 1;
instance.Model = "Box.glb";
instance.Tags = JArray.Parse("[{'id':123},{'name': 'test'}]");
instances.Add(instance);

// act
var tile = TileHandler.GetTile(instances, Format.Cesium, Vector3.Zero,useGpuInstancing:true);
var tile = TileHandler.GetTile(instances, Format.Cesium, Vector3.Zero, useGpuInstancing: true);

var fileName = Path.Combine(TestContext.CurrentContext.WorkDirectory, "ams_building_multiple_colors.glb");
File.WriteAllBytes(fileName, tile);

var model = SharpGLTF.Schema2.ModelRoot.Load(fileName);

var model = ModelRoot.Load(fileName);
var extInstanceFeaturesExtension = model.LogicalNodes[0].GetExtension<MeshExtInstanceFeatures>();

var extStructuralMetadataExtension = model.GetExtension<EXTStructuralMetadataRoot>();
Assert.That(extStructuralMetadataExtension != null);

var fid0 = extInstanceFeaturesExtension.FeatureIds[0];
Assert.That(fid0.FeatureCount == 1);


// assert
// todo: can we read the instance positions from the glb?
Assert.That(tile.Length > 0);
}



[Test]
public void GetTileTest()
{
Expand Down Expand Up @@ -164,7 +175,7 @@ public void GetTileWithRtcCenterTest()
instances.Add(instance1);

// act
var tile = TileHandler.GetTile(instances, Format.Mapbox,translate: new Vector3(5, 5, 0));
var tile = TileHandler.GetTile(instances, Format.Mapbox, translate: new Vector3(5, 5, 0));
var cmpt = CmptReader.Read(new MemoryStream(tile));
var i3dm = I3dmReader.Read(new MemoryStream(cmpt.Tiles.First()));

Expand Down

0 comments on commit b252cc1

Please sign in to comment.