From 9fc08a32d127383478cd64fc014552a1ef9eaf0d Mon Sep 17 00:00:00 2001 From: Bert Temme Date: Sat, 8 Jun 2024 09:24:41 +0200 Subject: [PATCH] improve gpu instancing --- src/Cesium/Transforms.cs | 36 ----------------------------------- src/InstancesRepository.cs | 1 - src/Program.cs | 15 +++------------ src/TileHandler.cs | 39 +++++++++++++++++++++++++++----------- src/TreeSerializer.cs | 6 +----- 5 files changed, 32 insertions(+), 65 deletions(-) diff --git a/src/Cesium/Transforms.cs b/src/Cesium/Transforms.cs index bb30d42..3df2f5f 100644 --- a/src/Cesium/Transforms.cs +++ b/src/Cesium/Transforms.cs @@ -4,42 +4,6 @@ namespace i3dm.export.Cesium; public static class Transforms { - public static Matrix4x4 FromRotationZ(double angle) - { - var cosAngle = (float)Math.Cos(angle); - var sinAngle = (float)Math.Sin(angle); - return new Matrix4x4( - cosAngle, sinAngle, 0, 0, - -sinAngle, cosAngle, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1); - } - - public static Quaternion GetQuaterion(Matrix4x4 enu, double rotationAroundZ) - { - var mat6 = Axis.Z_UP_TO_Y_UP() * enu; - var mat7 = mat6 * Axis.Y_UP_TO_Z_UP(); - var mat8 = mat7 * Axis.Y_UP_TO_Z_UP(); - var horizontalrotation = Transforms.FromRotationZ(rotationAroundZ); - var mat9 = mat8 * horizontalrotation; - - var res = QuaternionFromMatrix(mat9); - return res; - } - - private static Quaternion QuaternionFromMatrix(Matrix4x4 m) - { - // Adapted from: http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm - Quaternion q = new Quaternion(); - q.W = (float)Math.Sqrt(Math.Max(0, 1 + m.M11 + m.M22 + m.M33)) / 2; - q.X = (float)Math.Sqrt(Math.Max(0, 1 + m.M11 - m.M22 - m.M33)) / 2; - q.Y = (float)Math.Sqrt(Math.Max(0, 1 - m.M11 + m.M22 - m.M33)) / 2; - q.Z = (float)Math.Sqrt(Math.Max(0, 1 - m.M11 - m.M22 + m.M33)) / 2; - q.X *= Math.Sign(q.X * (m.M32 - m.M23)); - q.Y *= Math.Sign(q.Y * (m.M13 - m.M31)); - q.Z *= Math.Sign(q.Z * (m.M21 - m.M12)); - return q; - } public static Matrix4x4 EastNorthUpToFixedFrame(Vector3 cartesian) { diff --git a/src/InstancesRepository.cs b/src/InstancesRepository.cs index 654e185..0b4fe9d 100644 --- a/src/InstancesRepository.cs +++ b/src/InstancesRepository.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.Net.Http; using Wkx; namespace i3dm.export; diff --git a/src/Program.cs b/src/Program.cs index e2593da..9fcab3e 100644 --- a/src/Program.cs +++ b/src/Program.cs @@ -50,7 +50,8 @@ static void Main(string[] args) } var conn = new NpgsqlConnection(o.ConnectionString); - var epsg = (bool)o.UseGpuInstancing ? 4326: 4978; + // var epsg = (bool)o.UseGpuInstancing ? 4326: 4978; + var epsg = 4978; var heightsArray = o.BoundingVolumeHeights.Split(','); var heights = new double[2] { double.Parse(heightsArray[0]), double.Parse(heightsArray[1]) }; @@ -89,16 +90,6 @@ static void Main(string[] args) translate = SpatialConverter.GeodeticToEcef((double)center_wgs84.X, (double)center_wgs84.Y, (double)center_wgs84.Z); - var t1 = Transforms.EastNorthUpToFixedFrame(translate); - - var transform = new Double[] { - t1.M11,t1.M21, t1.M31, t1.M41, - t1.M12,t1.M22, t1.M32, t1.M42, - t1.M13,t1.M23, t1.M33, t1.M43, - t1.M14,t1.M24, t1.M34, t1.M44 - }; - - if ((bool)o.UseGpuInstancing) { translate = new Vector3((float)center_wgs84.X, (float)center_wgs84.Y, (float)center_wgs84.Z); @@ -150,7 +141,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, translate, (bool)o.UseGpuInstancing, transform); + var tilesetjson = TreeSerializer.ToImplicitTileset(rootBoundingVolumeRegion, o.GeometricError, availableLevels, subtreeLevels, version, translate, (bool)o.UseGpuInstancing); var file = $"{o.Output}{Path.AltDirectorySeparatorChar}tileset.json"; Console.WriteLine($"Subtree files written: {subtreeFiles.Count}"); Console.WriteLine("SubtreeLevels: " + subtreeLevels); diff --git a/src/TileHandler.cs b/src/TileHandler.cs index d6bb635..124036d 100644 --- a/src/TileHandler.cs +++ b/src/TileHandler.cs @@ -100,8 +100,12 @@ private static Vector3 GetPosition(Point p, Vector3 translate) private static byte[] GetGpuGlb(object model, List positions, Vector3 translate, bool UseScaleNonUniform, List tags) { var modelRoot = ModelRoot.Load((string)model); + var meshBuilder = modelRoot.LogicalMeshes.First().ToMeshBuilder(); + + var node = modelRoot.LogicalNodes.First().CreateNode("test").WithLocalTranslation(translate); + var sceneBuilder = new SceneBuilder(); var pointId = 0; @@ -109,25 +113,37 @@ private static byte[] GetGpuGlb(object model, List positions, Vector3 foreach (var p in positions) { var point = (Point)p.Position; - - var dx = DistanceCalculator.GetDistanceTo(translate.X, translate.Y, (double)point.X, translate.Y); - var dy = DistanceCalculator.GetDistanceTo(translate.X, translate.Y, translate.X, (double)point.Y); - - dx = (double)point.X - translate.X > 0 ? dx : -dx; - dy = (double)point.Y - translate.Y > 0 ? -dy : dy; - - var dz = (double)point.Z - translate.Z; - var p1 = new Point(dx, dz, dy); + var p1 = new Point((double)point.X, (double)point.Z, (double)point.Y * -1); var scale = UseScaleNonUniform ? new Vector3((float)p.ScaleNonUniform[0], (float)p.ScaleNonUniform[1], (float)p.ScaleNonUniform[2]) : new Vector3((float)p.Scale, (float)p.Scale, (float)p.Scale); - var quaternion = Quaternion.CreateFromYawPitchRoll((float)p.Yaw, (float)p.Pitch, (float)p.Roll); + var enu = EnuCalculator.GetLocalEnu(Format.Cesium, 0, new Vector3((float)point.X, (float)point.Y, (float)point.Z)); + + var forward = Vector3.Cross(enu.East, enu.Up); + forward = Vector3.Normalize(forward); + var m4 = new Matrix4x4(); + m4.M11 = enu.East.X; + m4.M21 = enu.East.Y; + m4.M31 = enu.East.Z; + + m4.M12 = enu.Up.X; + m4.M22 = enu.Up.Y; + m4.M32 = enu.Up.Z; + + m4.M13 = forward.X; + m4.M23 = forward.Y; + m4.M33 = forward.Z; + var res = Quaternion.CreateFromRotationMatrix(m4); + var translation = new Vector3((float)p1.X, (float)p1.Y, (float)p1.Z); + // todo: make translation relative + // todo: use quaternion for yaw/pitch/roll + // var quaternion = Quaternion.CreateFromYawPitchRoll((float)p.Yaw, (float)p.Pitch, (float)p.Roll); var transformation = new AffineTransform( scale, - quaternion, + new Quaternion(-res.X, -res.Z, res.Y, res.W), translation); var json = "{\"_FEATURE_ID_0\":" + pointId + "}"; sceneBuilder.AddRigidMesh(meshBuilder, transformation).WithExtras(JsonNode.Parse(json)); @@ -136,6 +152,7 @@ private static byte[] GetGpuGlb(object model, List positions, Vector3 var settings = SceneBuilderSchema2Settings.WithGpuInstancing; settings.GpuMeshInstancingMinCount = 0; + var gltf = sceneBuilder.ToGltf2(settings); var rootMetadata = gltf.UseStructuralMetadata(); diff --git a/src/TreeSerializer.cs b/src/TreeSerializer.cs index 1c63d67..ccbf8bf 100644 --- a/src/TreeSerializer.cs +++ b/src/TreeSerializer.cs @@ -7,7 +7,7 @@ namespace i3dm.export; public static class TreeSerializer { - public static string ToImplicitTileset(double[] box, double geometricError, int availableLevels, int subtreeLevels, Version version, Vector3 translate, bool useGpuInstancing = false, double[] transform=null) + public static string ToImplicitTileset(double[] box, double geometricError, int availableLevels, int subtreeLevels, Version version, Vector3 translate, bool useGpuInstancing = false) { var tileset = new TileSet { @@ -21,10 +21,6 @@ public static string ToImplicitTileset(double[] box, double geometricError, int root.content = content; var subtrees = new Subtrees() { uri = "subtrees/{level}_{x}_{y}.subtree" }; root.implicitTiling = new Implicittiling() { subdivisionScheme = "QUADTREE", availableLevels = availableLevels, subtreeLevels = subtreeLevels, subtrees = subtrees }; - if (useGpuInstancing) - { - root.transform = transform; - }; tileset.root = root; var json = JsonConvert.SerializeObject(tileset, Formatting.Indented, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore }); return json;