Skip to content

Commit

Permalink
improve gpu instancing
Browse files Browse the repository at this point in the history
  • Loading branch information
bertt committed Jun 8, 2024
1 parent 0ad35f0 commit 9fc08a3
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 65 deletions.
36 changes: 0 additions & 36 deletions src/Cesium/Transforms.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
1 change: 0 additions & 1 deletion src/InstancesRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Net.Http;
using Wkx;

namespace i3dm.export;
Expand Down
15 changes: 3 additions & 12 deletions src/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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]) };
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
39 changes: 28 additions & 11 deletions src/TileHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,34 +100,50 @@ private static Vector3 GetPosition(Point p, Vector3 translate)
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 node = modelRoot.LogicalNodes.First().CreateNode("test").WithLocalTranslation(translate);

var sceneBuilder = new SceneBuilder();

var pointId = 0;

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));
Expand All @@ -136,6 +152,7 @@ private static byte[] GetGpuGlb(object model, List<Instance> positions, Vector3

var settings = SceneBuilderSchema2Settings.WithGpuInstancing;
settings.GpuMeshInstancingMinCount = 0;

var gltf = sceneBuilder.ToGltf2(settings);

var rootMetadata = gltf.UseStructuralMetadata();
Expand Down
6 changes: 1 addition & 5 deletions src/TreeSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -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;
Expand Down

0 comments on commit 9fc08a3

Please sign in to comment.