From 46b000cd2083849169f626b4debbe7a739fa2fa0 Mon Sep 17 00:00:00 2001 From: Eric Wassail Date: Tue, 6 Dec 2022 17:23:00 -0500 Subject: [PATCH 1/8] test and implement merging extensions --- .../src/Serialization/glTF/GltfExtensions.cs | 20 +++++++---- .../Serialization/glTF/GltfMergingUtils.cs | 6 ++++ Elements/test/ContentTests.cs | 33 ++++++++++++++++++ .../test/models/MergeGlTF/LittleShapes.glb | Bin 0 -> 75544 bytes 4 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 Elements/test/models/MergeGlTF/LittleShapes.glb diff --git a/Elements/src/Serialization/glTF/GltfExtensions.cs b/Elements/src/Serialization/glTF/GltfExtensions.cs index ee03fbb23..3465e62f6 100644 --- a/Elements/src/Serialization/glTF/GltfExtensions.cs +++ b/Elements/src/Serialization/glTF/GltfExtensions.cs @@ -38,10 +38,10 @@ private static int GetNextId() /// /// In normal function use, this should be set to null. - /// If not null and set to a valid directory path, gltfs loaded for + /// If not null and set to a valid directory path, gltfs loaded for /// content elements will be cached to this directory, and can be /// explicitly loaded by calling LoadGltfCacheFromDisk(). This is used - /// by `hypar run` and test capabilities to speed up repeated runs. + /// by `hypar run` and test capabilities to speed up repeated runs. /// public static string GltfCachePath { @@ -904,9 +904,9 @@ internal static Gltf InitializeGlTF(Model model, // Attempt to pre-allocate these lists. This won't be perfect. // Before processing the geometry of an element we can't know - // how much to allocate. In the worst case, this will reduce + // how much to allocate. In the worst case, this will reduce // the list resizing. - // TODO: In future work where we update element geometry during + // TODO: In future work where we update element geometry during // UpdateRepresentations, we will know at this moment how big the // geometry for an element is, and we should tighten this up. var elementCount = model.AllElementsAssignableFromType().Count(); @@ -947,12 +947,12 @@ internal static Gltf InitializeGlTF(Model model, gltf.Scenes = new[] { scene }; var lights = model.AllElementsOfType().ToList(); - gltf.ExtensionsUsed = lights.Any() ? new[] { + var extensions = lights.Any() ? new HashSet() { "KHR_materials_specular", "KHR_materials_ior", "KHR_materials_unlit", "KHR_lights_punctual" - } : new[] { + } : new HashSet() { "KHR_materials_specular", "KHR_materials_ior", "KHR_materials_unlit"}; @@ -1025,6 +1025,7 @@ internal static Gltf InitializeGlTF(Model model, textures, images, samplers, + extensions, meshes, nodes, meshElementMap, @@ -1100,6 +1101,11 @@ internal static Gltf InitializeGlTF(Model model, gltf.Meshes = meshes.ToArray(meshes.Count); } + if (extensions.Count > 0) + { + gltf.ExtensionsUsed = extensions.ToArray(); + } + // This is a hack! For web assembly, the ToArray() call creates // a copy of all items in the list, and is extremely slow. We // get around this by accessing the underlying list directly. @@ -1125,6 +1131,7 @@ private static void GetRenderDataForElement(Element e, List textures, List images, List samplers, + HashSet extensions, List meshes, List nodes, Dictionary> meshElementMap, @@ -1155,6 +1162,7 @@ private static void GetRenderDataForElement(Element e, textures, images, samplers, + extensions, true, e.Id, out var parentNode); diff --git a/Elements/src/Serialization/glTF/GltfMergingUtils.cs b/Elements/src/Serialization/glTF/GltfMergingUtils.cs index b27deecf1..343a63fc0 100644 --- a/Elements/src/Serialization/glTF/GltfMergingUtils.cs +++ b/Elements/src/Serialization/glTF/GltfMergingUtils.cs @@ -27,6 +27,7 @@ public static List AddAllMeshesFromFromGlb(Stream glbStream, List textures, List images, List samplers, + HashSet extensions, bool shouldAddMaterials, System.Guid contentElementId, out ProtoNode parentNode @@ -60,6 +61,11 @@ out ProtoNode parentNode accessors.Add(originAccessor); } + foreach (var extension in loaded.ExtensionsUsed) + { + extensions.Add(extension); + } + var imageIncrement = images.Count; if (loaded.Images != null) { diff --git a/Elements/test/ContentTests.cs b/Elements/test/ContentTests.cs index c850f74a5..e91873a1d 100644 --- a/Elements/test/ContentTests.cs +++ b/Elements/test/ContentTests.cs @@ -4,6 +4,8 @@ using System.Collections.Generic; using System; using System.IO; +using glTFLoader; +using System.Linq; namespace Elements.Tests { @@ -56,6 +58,37 @@ public void CatalogSerialization() Assert.Equal("The Value", loadedCatalog.Content[0].AdditionalProperties["ImportantParameter"]); } + [Fact] + public void MergeExtensions() + { + Name = nameof(MergeExtensions); + const string contentLocation = "../../../models/MergeGlTF/LittleShapes.glb"; + var heated = new TestContentElem(contentLocation, + new BBox3(new Vector3(-0.5, -0.5, 0), new Vector3(0.5, 0.5, 3)), + new Vector3(), + new Transform(new Vector3(), Vector3.XAxis), + 20, + BuiltInMaterials.Default, + null, + true, + Guid.NewGuid(), + "LittleShapes"); + var anInstance = heated.CreateInstance(new Transform(new Vector3(15, 0, 0)), "LittleShapes1"); + + var mergedModelPath = $"./models/{nameof(MergeExtensions)}.glb"; + Model.AddElement(new Mass(Polygon.Rectangle(1, 1))); + Model.ToGlTF(mergedModelPath); + var gltfModelEmpty = Interface.LoadModel(mergedModelPath); + var initialExtensions = gltfModelEmpty.ExtensionsUsed; + + Model.AddElement(anInstance); + var gltfContent = Interface.LoadModel(contentLocation); + var gltfModelMerged = Interface.LoadModel(mergedModelPath); + Assert.NotEmpty(gltfContent.ExtensionsUsed); + Assert.NotEmpty(gltfContent.ExtensionsUsed.Except(initialExtensions)); + Assert.All(gltfContent.ExtensionsUsed, (ext) => Assert.Contains(ext, gltfModelMerged.ExtensionsUsed)); + } + [Fact, Trait("Category", "Example")] public void InstanceContentElement() { diff --git a/Elements/test/models/MergeGlTF/LittleShapes.glb b/Elements/test/models/MergeGlTF/LittleShapes.glb new file mode 100644 index 0000000000000000000000000000000000000000..4fcf8d77f6099176dbe6815976b05e18f711dc06 GIT binary patch literal 75544 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Ċ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 literal 0 HcmV?d00001 From a3da7b05f6842e37c3be18f78fcda0cd7925b87c Mon Sep 17 00:00:00 2001 From: Eric Wassail Date: Tue, 6 Dec 2022 17:26:11 -0500 Subject: [PATCH 2/8] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b66e31c7..7f567c068 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ - Fix `Obstacle.FromLine` if line is vertical and start point is positioned higher than end. - Materials exported to glTF now have their `RoughnessFactor` set correctly. - Materials exported to glTF no longer use the `KHR_materials_pbrSpecularGlossiness` extension, as this extension is being sunset in favor of `KHR_materials_specular` and `KHR_materials_ior`. +- Gltfs that are merged that require additional extensions will also merge their extensions. ## 1.3.0 From ef99fd2e61075a2482813078da35a6e7a2a2bbc2 Mon Sep 17 00:00:00 2001 From: Eric Wassail Date: Tue, 6 Dec 2022 21:09:13 -0500 Subject: [PATCH 3/8] extensions can have attributes that also must be preserved --- .../src/Serialization/glTF/GltfExtensions.cs | 30 ++++++++++--------- .../Serialization/glTF/GltfMergingUtils.cs | 14 +++++++-- Elements/test/ContentTests.cs | 11 +++---- Elements/test/MaterialTests.cs | 1 + 4 files changed, 35 insertions(+), 21 deletions(-) diff --git a/Elements/src/Serialization/glTF/GltfExtensions.cs b/Elements/src/Serialization/glTF/GltfExtensions.cs index 3465e62f6..5e22d3d28 100644 --- a/Elements/src/Serialization/glTF/GltfExtensions.cs +++ b/Elements/src/Serialization/glTF/GltfExtensions.cs @@ -947,15 +947,18 @@ internal static Gltf InitializeGlTF(Model model, gltf.Scenes = new[] { scene }; var lights = model.AllElementsOfType().ToList(); - var extensions = lights.Any() ? new HashSet() { - "KHR_materials_specular", - "KHR_materials_ior", - "KHR_materials_unlit", - "KHR_lights_punctual" - } : new HashSet() { - "KHR_materials_specular", - "KHR_materials_ior", - "KHR_materials_unlit"}; + var extensions = lights.Any() ? new Dictionary() { + {"KHR_materials_specular",new Dictionary()}, + {"KHR_materials_ior",new Dictionary()}, + {"KHR_materials_unlit",new Dictionary()}, + {"KHR_lights_punctual",new Dictionary()}, + } : new Dictionary() { + {"KHR_materials_specular",new Dictionary()}, + {"KHR_materials_ior",new Dictionary()}, + {"KHR_materials_unlit",new Dictionary()} + }; + gltf.Extensions = extensions; + gltf.ExtensionsUsed = extensions.Keys.ToArray(); var bufferViews = new List(); @@ -1101,10 +1104,9 @@ internal static Gltf InitializeGlTF(Model model, gltf.Meshes = meshes.ToArray(meshes.Count); } - if (extensions.Count > 0) - { - gltf.ExtensionsUsed = extensions.ToArray(); - } + // the extension dictionary can have items added to it during merge, so we re-establish it here. + gltf.ExtensionsUsed = extensions.Keys.ToArray(); + gltf.Extensions = extensions; // This is a hack! For web assembly, the ToArray() call creates // a copy of all items in the list, and is extremely slow. We @@ -1131,7 +1133,7 @@ private static void GetRenderDataForElement(Element e, List textures, List images, List samplers, - HashSet extensions, + Dictionary extensions, List meshes, List nodes, Dictionary> meshElementMap, diff --git a/Elements/src/Serialization/glTF/GltfMergingUtils.cs b/Elements/src/Serialization/glTF/GltfMergingUtils.cs index 343a63fc0..63ac8e393 100644 --- a/Elements/src/Serialization/glTF/GltfMergingUtils.cs +++ b/Elements/src/Serialization/glTF/GltfMergingUtils.cs @@ -27,7 +27,7 @@ public static List AddAllMeshesFromFromGlb(Stream glbStream, List textures, List images, List samplers, - HashSet extensions, + Dictionary extensions, bool shouldAddMaterials, System.Guid contentElementId, out ProtoNode parentNode @@ -61,9 +61,19 @@ out ProtoNode parentNode accessors.Add(originAccessor); } + foreach (var extension in loaded.Extensions ?? new Dictionary()) + { + if (!extensions.ContainsKey(extension.Key)) + { + extensions.Add(extension.Key, extension.Value); + } + } foreach (var extension in loaded.ExtensionsUsed) { - extensions.Add(extension); + if (!extensions.ContainsKey(extension)) + { + extensions.Add(extension, new Dictionary()); + } } var imageIncrement = images.Count; diff --git a/Elements/test/ContentTests.cs b/Elements/test/ContentTests.cs index e91873a1d..65d0b9a84 100644 --- a/Elements/test/ContentTests.cs +++ b/Elements/test/ContentTests.cs @@ -75,15 +75,16 @@ public void MergeExtensions() "LittleShapes"); var anInstance = heated.CreateInstance(new Transform(new Vector3(15, 0, 0)), "LittleShapes1"); - var mergedModelPath = $"./models/{nameof(MergeExtensions)}.glb"; + var modelPath = $"./models/{nameof(MergeExtensions)}.glb"; Model.AddElement(new Mass(Polygon.Rectangle(1, 1))); - Model.ToGlTF(mergedModelPath); - var gltfModelEmpty = Interface.LoadModel(mergedModelPath); + Model.ToGlTF(modelPath); + var gltfModelEmpty = Interface.LoadModel(modelPath); var initialExtensions = gltfModelEmpty.ExtensionsUsed; - Model.AddElement(anInstance); var gltfContent = Interface.LoadModel(contentLocation); - var gltfModelMerged = Interface.LoadModel(mergedModelPath); + Model.AddElement(anInstance); + Model.ToGlTF(modelPath); + var gltfModelMerged = Interface.LoadModel(modelPath); Assert.NotEmpty(gltfContent.ExtensionsUsed); Assert.NotEmpty(gltfContent.ExtensionsUsed.Except(initialExtensions)); Assert.All(gltfContent.ExtensionsUsed, (ext) => Assert.Contains(ext, gltfModelMerged.ExtensionsUsed)); diff --git a/Elements/test/MaterialTests.cs b/Elements/test/MaterialTests.cs index 1762ff08c..4e6c257f8 100644 --- a/Elements/test/MaterialTests.cs +++ b/Elements/test/MaterialTests.cs @@ -122,6 +122,7 @@ public void EmissiveTextureTest() [Fact] public void BuiltInMaterialsAlwaysHaveSameId() { + Name = nameof(BuiltInMaterialsAlwaysHaveSameId); var m1 = BuiltInMaterials.Wood; this.Model.AddElement(m1); var json = this.Model.ToJson(); From 824117a49080b14c316bc81807c34441aad02332 Mon Sep 17 00:00:00 2001 From: Eric Wassail Date: Wed, 7 Dec 2022 11:21:10 -0500 Subject: [PATCH 4/8] Revert "extensions can have attributes that also must be preserved" This reverts commit ef99fd2e61075a2482813078da35a6e7a2a2bbc2. --- .../src/Serialization/glTF/GltfExtensions.cs | 30 +++++++++---------- .../Serialization/glTF/GltfMergingUtils.cs | 14 ++------- Elements/test/ContentTests.cs | 11 ++++--- Elements/test/MaterialTests.cs | 1 - 4 files changed, 21 insertions(+), 35 deletions(-) diff --git a/Elements/src/Serialization/glTF/GltfExtensions.cs b/Elements/src/Serialization/glTF/GltfExtensions.cs index 5e22d3d28..3465e62f6 100644 --- a/Elements/src/Serialization/glTF/GltfExtensions.cs +++ b/Elements/src/Serialization/glTF/GltfExtensions.cs @@ -947,18 +947,15 @@ internal static Gltf InitializeGlTF(Model model, gltf.Scenes = new[] { scene }; var lights = model.AllElementsOfType().ToList(); - var extensions = lights.Any() ? new Dictionary() { - {"KHR_materials_specular",new Dictionary()}, - {"KHR_materials_ior",new Dictionary()}, - {"KHR_materials_unlit",new Dictionary()}, - {"KHR_lights_punctual",new Dictionary()}, - } : new Dictionary() { - {"KHR_materials_specular",new Dictionary()}, - {"KHR_materials_ior",new Dictionary()}, - {"KHR_materials_unlit",new Dictionary()} - }; - gltf.Extensions = extensions; - gltf.ExtensionsUsed = extensions.Keys.ToArray(); + var extensions = lights.Any() ? new HashSet() { + "KHR_materials_specular", + "KHR_materials_ior", + "KHR_materials_unlit", + "KHR_lights_punctual" + } : new HashSet() { + "KHR_materials_specular", + "KHR_materials_ior", + "KHR_materials_unlit"}; var bufferViews = new List(); @@ -1104,9 +1101,10 @@ internal static Gltf InitializeGlTF(Model model, gltf.Meshes = meshes.ToArray(meshes.Count); } - // the extension dictionary can have items added to it during merge, so we re-establish it here. - gltf.ExtensionsUsed = extensions.Keys.ToArray(); - gltf.Extensions = extensions; + if (extensions.Count > 0) + { + gltf.ExtensionsUsed = extensions.ToArray(); + } // This is a hack! For web assembly, the ToArray() call creates // a copy of all items in the list, and is extremely slow. We @@ -1133,7 +1131,7 @@ private static void GetRenderDataForElement(Element e, List textures, List images, List samplers, - Dictionary extensions, + HashSet extensions, List meshes, List nodes, Dictionary> meshElementMap, diff --git a/Elements/src/Serialization/glTF/GltfMergingUtils.cs b/Elements/src/Serialization/glTF/GltfMergingUtils.cs index 63ac8e393..343a63fc0 100644 --- a/Elements/src/Serialization/glTF/GltfMergingUtils.cs +++ b/Elements/src/Serialization/glTF/GltfMergingUtils.cs @@ -27,7 +27,7 @@ public static List AddAllMeshesFromFromGlb(Stream glbStream, List textures, List images, List samplers, - Dictionary extensions, + HashSet extensions, bool shouldAddMaterials, System.Guid contentElementId, out ProtoNode parentNode @@ -61,19 +61,9 @@ out ProtoNode parentNode accessors.Add(originAccessor); } - foreach (var extension in loaded.Extensions ?? new Dictionary()) - { - if (!extensions.ContainsKey(extension.Key)) - { - extensions.Add(extension.Key, extension.Value); - } - } foreach (var extension in loaded.ExtensionsUsed) { - if (!extensions.ContainsKey(extension)) - { - extensions.Add(extension, new Dictionary()); - } + extensions.Add(extension); } var imageIncrement = images.Count; diff --git a/Elements/test/ContentTests.cs b/Elements/test/ContentTests.cs index 65d0b9a84..e91873a1d 100644 --- a/Elements/test/ContentTests.cs +++ b/Elements/test/ContentTests.cs @@ -75,16 +75,15 @@ public void MergeExtensions() "LittleShapes"); var anInstance = heated.CreateInstance(new Transform(new Vector3(15, 0, 0)), "LittleShapes1"); - var modelPath = $"./models/{nameof(MergeExtensions)}.glb"; + var mergedModelPath = $"./models/{nameof(MergeExtensions)}.glb"; Model.AddElement(new Mass(Polygon.Rectangle(1, 1))); - Model.ToGlTF(modelPath); - var gltfModelEmpty = Interface.LoadModel(modelPath); + Model.ToGlTF(mergedModelPath); + var gltfModelEmpty = Interface.LoadModel(mergedModelPath); var initialExtensions = gltfModelEmpty.ExtensionsUsed; - var gltfContent = Interface.LoadModel(contentLocation); Model.AddElement(anInstance); - Model.ToGlTF(modelPath); - var gltfModelMerged = Interface.LoadModel(modelPath); + var gltfContent = Interface.LoadModel(contentLocation); + var gltfModelMerged = Interface.LoadModel(mergedModelPath); Assert.NotEmpty(gltfContent.ExtensionsUsed); Assert.NotEmpty(gltfContent.ExtensionsUsed.Except(initialExtensions)); Assert.All(gltfContent.ExtensionsUsed, (ext) => Assert.Contains(ext, gltfModelMerged.ExtensionsUsed)); diff --git a/Elements/test/MaterialTests.cs b/Elements/test/MaterialTests.cs index 4e6c257f8..1762ff08c 100644 --- a/Elements/test/MaterialTests.cs +++ b/Elements/test/MaterialTests.cs @@ -122,7 +122,6 @@ public void EmissiveTextureTest() [Fact] public void BuiltInMaterialsAlwaysHaveSameId() { - Name = nameof(BuiltInMaterialsAlwaysHaveSameId); var m1 = BuiltInMaterials.Wood; this.Model.AddElement(m1); var json = this.Model.ToJson(); From 295db65d75c731d435205172b65a48ea8e5811c3 Mon Sep 17 00:00:00 2001 From: Eric Wassail Date: Wed, 7 Dec 2022 11:33:47 -0500 Subject: [PATCH 5/8] assign ExtensionsUsed correctly --- Elements/src/Serialization/glTF/GltfExtensions.cs | 1 + Elements/test/ContentTests.cs | 11 ++++++----- Elements/test/ModelTest.cs | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Elements/src/Serialization/glTF/GltfExtensions.cs b/Elements/src/Serialization/glTF/GltfExtensions.cs index 3465e62f6..5b5b931e8 100644 --- a/Elements/src/Serialization/glTF/GltfExtensions.cs +++ b/Elements/src/Serialization/glTF/GltfExtensions.cs @@ -956,6 +956,7 @@ internal static Gltf InitializeGlTF(Model model, "KHR_materials_specular", "KHR_materials_ior", "KHR_materials_unlit"}; + gltf.ExtensionsUsed = extensions.ToArray(extensions.Count); var bufferViews = new List(); diff --git a/Elements/test/ContentTests.cs b/Elements/test/ContentTests.cs index e91873a1d..65d0b9a84 100644 --- a/Elements/test/ContentTests.cs +++ b/Elements/test/ContentTests.cs @@ -75,15 +75,16 @@ public void MergeExtensions() "LittleShapes"); var anInstance = heated.CreateInstance(new Transform(new Vector3(15, 0, 0)), "LittleShapes1"); - var mergedModelPath = $"./models/{nameof(MergeExtensions)}.glb"; + var modelPath = $"./models/{nameof(MergeExtensions)}.glb"; Model.AddElement(new Mass(Polygon.Rectangle(1, 1))); - Model.ToGlTF(mergedModelPath); - var gltfModelEmpty = Interface.LoadModel(mergedModelPath); + Model.ToGlTF(modelPath); + var gltfModelEmpty = Interface.LoadModel(modelPath); var initialExtensions = gltfModelEmpty.ExtensionsUsed; - Model.AddElement(anInstance); var gltfContent = Interface.LoadModel(contentLocation); - var gltfModelMerged = Interface.LoadModel(mergedModelPath); + Model.AddElement(anInstance); + Model.ToGlTF(modelPath); + var gltfModelMerged = Interface.LoadModel(modelPath); Assert.NotEmpty(gltfContent.ExtensionsUsed); Assert.NotEmpty(gltfContent.ExtensionsUsed.Except(initialExtensions)); Assert.All(gltfContent.ExtensionsUsed, (ext) => Assert.Contains(ext, gltfModelMerged.ExtensionsUsed)); diff --git a/Elements/test/ModelTest.cs b/Elements/test/ModelTest.cs index 087cb2f02..11c5ceef8 100644 --- a/Elements/test/ModelTest.cs +++ b/Elements/test/ModelTest.cs @@ -57,7 +57,7 @@ public ModelTest() public virtual void Dispose() { - if (this._model.Elements.Any()) + if (this._model.Elements.Any() && !String.IsNullOrEmpty(this._name)) { if (this.GenerateGlb) { From ae133fb3f1dcc96cef12ff4f2c863769fedaf656 Mon Sep 17 00:00:00 2001 From: Eric Wassail Date: Wed, 7 Dec 2022 11:34:20 -0500 Subject: [PATCH 6/8] changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f567c068..c613b1b14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,7 @@ - Remove the BBox3 validator. - `RoutingConfiguration.MainLayer` and `RoutingConfiguration.LayerPenalty` are set obsolete. - `EdgeInfo.HasVerticalChange` is set obsolete. -- `AdaptiveGraphRouting.RenderElements` is no longer paint hint lines in two different colors. Instead regular edges are paint into three groups. Weights are included to additional properties of produced elements. +- `AdaptiveGraphRouting.RenderElements` is no longer paint hint lines in two different colors. Instead regular edges are paint into three groups. Weights are included to additional properties of produced elements. ### Fixed @@ -28,6 +28,7 @@ - Materials exported to glTF now have their `RoughnessFactor` set correctly. - Materials exported to glTF no longer use the `KHR_materials_pbrSpecularGlossiness` extension, as this extension is being sunset in favor of `KHR_materials_specular` and `KHR_materials_ior`. - Gltfs that are merged that require additional extensions will also merge their extensions. +- Don't try to save test models that have no name, they can interfere with each other because they want to save to the same file. ## 1.3.0 From 1e32fb278054de79ea0fd3f88f681bf07615d102 Mon Sep 17 00:00:00 2001 From: Eric Wassail Date: Wed, 7 Dec 2022 11:38:17 -0500 Subject: [PATCH 7/8] comments and test fix --- Elements/test/ContentTests.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Elements/test/ContentTests.cs b/Elements/test/ContentTests.cs index 65d0b9a84..16c52ccf3 100644 --- a/Elements/test/ContentTests.cs +++ b/Elements/test/ContentTests.cs @@ -62,8 +62,9 @@ public void CatalogSerialization() public void MergeExtensions() { Name = nameof(MergeExtensions); + // This piece of content uses the KHR_materials_pbrSpecularGlossiness extension which is no longer used in our models. const string contentLocation = "../../../models/MergeGlTF/LittleShapes.glb"; - var heated = new TestContentElem(contentLocation, + var littleShapeContent = new TestContentElem(contentLocation, new BBox3(new Vector3(-0.5, -0.5, 0), new Vector3(0.5, 0.5, 3)), new Vector3(), new Transform(new Vector3(), Vector3.XAxis), @@ -73,7 +74,7 @@ public void MergeExtensions() true, Guid.NewGuid(), "LittleShapes"); - var anInstance = heated.CreateInstance(new Transform(new Vector3(15, 0, 0)), "LittleShapes1"); + var anInstance = littleShapeContent.CreateInstance(new Transform(new Vector3(15, 0, 0)), "LittleShapes1"); var modelPath = $"./models/{nameof(MergeExtensions)}.glb"; Model.AddElement(new Mass(Polygon.Rectangle(1, 1))); From b7005e9f677cd77daf720aff13634e4df7396d6d Mon Sep 17 00:00:00 2001 From: Eric Wassail Date: Wed, 7 Dec 2022 14:05:16 -0500 Subject: [PATCH 8/8] cleanup --- .../src/Serialization/glTF/GltfExtensions.cs | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/Elements/src/Serialization/glTF/GltfExtensions.cs b/Elements/src/Serialization/glTF/GltfExtensions.cs index 5b5b931e8..c540b39df 100644 --- a/Elements/src/Serialization/glTF/GltfExtensions.cs +++ b/Elements/src/Serialization/glTF/GltfExtensions.cs @@ -946,17 +946,19 @@ internal static Gltf InitializeGlTF(Model model, }; gltf.Scenes = new[] { scene }; - var lights = model.AllElementsOfType().ToList(); - var extensions = lights.Any() ? new HashSet() { - "KHR_materials_specular", - "KHR_materials_ior", - "KHR_materials_unlit", - "KHR_lights_punctual" - } : new HashSet() { + var extensionsUsed = new HashSet { "KHR_materials_specular", "KHR_materials_ior", - "KHR_materials_unlit"}; - gltf.ExtensionsUsed = extensions.ToArray(extensions.Count); + "KHR_materials_unlit" + }; + + var lights = model.AllElementsOfType().ToList(); + if (lights.Any()) + { + extensionsUsed.Add("KHR_lights_punctual"); + } + + gltf.ExtensionsUsed = extensionsUsed.ToArray(); var bufferViews = new List(); @@ -1026,7 +1028,7 @@ internal static Gltf InitializeGlTF(Model model, textures, images, samplers, - extensions, + extensionsUsed, meshes, nodes, meshElementMap, @@ -1102,9 +1104,9 @@ internal static Gltf InitializeGlTF(Model model, gltf.Meshes = meshes.ToArray(meshes.Count); } - if (extensions.Count > 0) + if (extensionsUsed.Count > 0) { - gltf.ExtensionsUsed = extensions.ToArray(); + gltf.ExtensionsUsed = extensionsUsed.ToArray(); } // This is a hack! For web assembly, the ToArray() call creates