Browse Source

Merge branch 'master' into add_cesium_ext_mesh_features

Bert Temme 2 years ago
parent
commit
b844b4b550

+ 1 - 1
build/SharpGLTF.CodeGen/CodeGen/EmitCSharp.cs

@@ -248,7 +248,7 @@ namespace SharpGLTF.CodeGen
 
 
         private Object _GetConstantRuntimeValue(SchemaType type, Object value)
         private Object _GetConstantRuntimeValue(SchemaType type, Object value)
         {
         {
-            if (value == null) throw new ArgumentNullException();
+            if (value == null) throw new ArgumentNullException(nameof(value));
 
 
             switch (type)
             switch (type)
             {
             {

+ 1 - 1
build/SharpGLTF.CodeGen/SharpGLTF.CodeGen.csproj

@@ -7,7 +7,7 @@
   </PropertyGroup>
   </PropertyGroup>
 
 
   <ItemGroup>
   <ItemGroup>
-    <PackageReference Include="LibGit2Sharp" Version="0.27.2" />    
+    <PackageReference Include="LibGit2Sharp" Version="0.28.0" />    
     <PackageReference Include="NJsonSchema.CodeGeneration.CSharp" Version="10.9.0" />
     <PackageReference Include="NJsonSchema.CodeGeneration.CSharp" Version="10.9.0" />
   </ItemGroup>
   </ItemGroup>
 
 

+ 5 - 5
examples/SharpGLTF.Runtime.MonoGame/LoaderContext.BasicEffect.cs

@@ -181,12 +181,12 @@ namespace SharpGLTF.Runtime
 
 
         private Texture2D UseDiffuseTexture(GLTFMATERIAL srcMaterial)
         private Texture2D UseDiffuseTexture(GLTFMATERIAL srcMaterial)
         {
         {
-            var diffuse = srcMaterial.FindChannel("Diffuse");
-
-            if (diffuse == null) diffuse = srcMaterial.FindChannel("BaseColor");
-            if (diffuse == null) return null;
+            var diffuse = srcMaterial.FindChannel("Diffuse")
+                ?? srcMaterial.FindChannel("BaseColor");
 
 
-            return UseTexture(diffuse, null);
+            return diffuse == null
+                ? null
+                : UseTexture(diffuse, null);
         }
         }
 
 
         #endregion
         #endregion

+ 1 - 1
examples/SharpGLTF.Runtime.MonoGame/LoaderContext.cs

@@ -102,7 +102,7 @@ namespace SharpGLTF.Runtime
 
 
         private void _WriteMeshPrimitive(MeshPrimitiveReader srcPrim, SRCMATERIAL srcMaterial)
         private void _WriteMeshPrimitive(MeshPrimitiveReader srcPrim, SRCMATERIAL srcMaterial)
         {
         {
-            if (srcMaterial == null) srcMaterial = GetDefaultMaterial();
+            srcMaterial ??= GetDefaultMaterial();
 
 
             var effect = _MatFactory.GetMaterial(srcMaterial, srcPrim.IsSkinned);
             var effect = _MatFactory.GetMaterial(srcMaterial, srcPrim.IsSkinned);
 
 

+ 2 - 2
examples/SharpGLTF.Runtime.MonoGame/MeshPrimitiveReader.cs

@@ -305,14 +305,14 @@ namespace SharpGLTF.Runtime
 
 
         void VertexNormalsFactory.IMeshPrimitive.SetVertexNormal(int idx, XYZ normal)
         void VertexNormalsFactory.IMeshPrimitive.SetVertexNormal(int idx, XYZ normal)
         {
         {
-            if (_Normals == null) _Normals = new XYZ[VertexCount];
+            _Normals ??= new XYZ[VertexCount];
             if (!(_Normals is XYZ[])) return; // if it's not a plain array, it's a glTF source, so we prevent writing existing normals.            
             if (!(_Normals is XYZ[])) return; // if it's not a plain array, it's a glTF source, so we prevent writing existing normals.            
             _Normals[idx] = normal;
             _Normals[idx] = normal;
         }
         }
 
 
         void VertexTangentsFactory.IMeshPrimitive.SetVertexTangent(int idx, XYZW tangent)
         void VertexTangentsFactory.IMeshPrimitive.SetVertexTangent(int idx, XYZW tangent)
         {
         {
-            if (_Tangents == null) _Tangents = new XYZW[VertexCount];
+            _Tangents ??= new XYZW[VertexCount];
             if (!(_Tangents is XYZW[])) return; // if it's not a plain array, it's a glTF source, so we prevent writing existing tangents.            
             if (!(_Tangents is XYZW[])) return; // if it's not a plain array, it's a glTF source, so we prevent writing existing tangents.            
             _Tangents[idx] = tangent;
             _Tangents[idx] = tangent;
         }        
         }        

+ 1 - 1
examples/SharpGLTF.Runtime.MonoGame/SharpGLTF.Runtime.MonoGame.csproj

@@ -3,7 +3,7 @@
   <PropertyGroup>
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
     <TargetFramework>net6.0</TargetFramework>
     <RootNamespace>SharpGLTF.Runtime</RootNamespace>
     <RootNamespace>SharpGLTF.Runtime</RootNamespace>
-    <LangVersion>7.3</LangVersion>
+    <LangVersion>8</LangVersion>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   </PropertyGroup>
 
 

+ 2 - 4
src/SharpGLTF.Core/Schema2/gltf.Accessors.cs

@@ -120,10 +120,8 @@ namespace SharpGLTF.Schema2
         internal KeyValuePair<IntegerArray, MemoryAccessor>? _GetSparseMemoryAccessor()
         internal KeyValuePair<IntegerArray, MemoryAccessor>? _GetSparseMemoryAccessor()
         {
         {
             return this._sparse == null
             return this._sparse == null
-                ?
-                (KeyValuePair<IntegerArray, MemoryAccessor>?)null
-                :
-                this._sparse._CreateMemoryAccessors(this);
+                ? (KeyValuePair<IntegerArray, MemoryAccessor>?)null
+                : this._sparse._CreateMemoryAccessors(this);
         }
         }
 
 
         protected override IEnumerable<ExtraProperties> GetLogicalChildren()
         protected override IEnumerable<ExtraProperties> GetLogicalChildren()

+ 1 - 1
src/SharpGLTF.Core/Schema2/gltf.Buffer.cs

@@ -173,7 +173,7 @@ namespace SharpGLTF.Schema2
         /// <returns>A <see cref="Buffer"/> instance.</returns>
         /// <returns>A <see cref="Buffer"/> instance.</returns>
         public Buffer UseBuffer(Byte[] content)
         public Buffer UseBuffer(Byte[] content)
         {
         {
-            Guard.IsFalse(content == null, nameof(content));
+            Guard.NotNull(content, nameof(content));
 
 
             foreach (var b in this.LogicalBuffers)
             foreach (var b in this.LogicalBuffers)
             {
             {

+ 11 - 1
src/SharpGLTF.Toolkit/Scenes/Transformers.Schema2.cs

@@ -154,6 +154,14 @@ namespace SharpGLTF.Scenes
                         .Select(item => item.ChildTransform)
                         .Select(item => item.ChildTransform)
                         .ToList();
                         .ToList();
 
 
+                    var extras = _Children
+                        .Select(item => item.Extras)
+                        .ToList();
+
+                    // we require all extras to exist and be of JsonObject type
+                    // so we can retrieve a shared attribute name.
+                    if (!extras.All(item => item is System.Text.Json.Nodes.JsonObject)) extras = null;                    
+
                     if (!(dst is Node dstNode)) dstNode = dst.CreateNode();
                     if (!(dst is Node dstNode)) dstNode = dst.CreateNode();
 
 
                     System.Diagnostics.Debug.Assert(dstNode.Mesh == null);
                     System.Diagnostics.Debug.Assert(dstNode.Mesh == null);
@@ -162,10 +170,12 @@ namespace SharpGLTF.Scenes
 
 
                     srcOperator.ApplyTo(dstNode, context);
                     srcOperator.ApplyTo(dstNode, context);
 
 
-                    dstNode
+                    var gpuInstExt = dstNode
                         .UseGpuInstancing()
                         .UseGpuInstancing()
                         .WithInstanceAccessors(xforms);
                         .WithInstanceAccessors(xforms);
 
 
+                    if (extras != null) gpuInstExt.WithInstanceCustomAccessors(extras);
+
                     #if DEBUG
                     #if DEBUG
                     var dstInstances = dstNode.GetGpuInstancing();
                     var dstInstances = dstNode.GetGpuInstancing();
                     for (int i = 0; i < _Children.Count; ++i)
                     for (int i = 0; i < _Children.Count; ++i)

+ 41 - 20
src/SharpGLTF.Toolkit/Schema2/MeshExtensions.cs

@@ -378,25 +378,18 @@ namespace SharpGLTF.Schema2
         {
         {
             Guard.NotNull(instancing, nameof(instancing));
             Guard.NotNull(instancing, nameof(instancing));
 
 
-            // gather attribute keys
-            var keys = extras                
+            // gather all attribute keys that begin with _ , as in _FEATURE_ID_1
+            var keys = extras
                 .OfType<System.Text.Json.Nodes.JsonObject>()
                 .OfType<System.Text.Json.Nodes.JsonObject>()
                 .SelectMany(item => item)
                 .SelectMany(item => item)
                 .Select(item => item.Key)
                 .Select(item => item.Key)
                 .Distinct()
                 .Distinct()
                 .Where(item => item.StartsWith("_", StringComparison.Ordinal));
                 .Where(item => item.StartsWith("_", StringComparison.Ordinal));
 
 
+            // for each attribute key found, fill the IDs
             foreach (var key in keys)
             foreach (var key in keys)
             {
             {
-                JSONEXTRAS valueGetter(JSONEXTRAS extra)
-                {
-                    if (!(extra is System.Text.Json.Nodes.JsonObject dict)) return null;
-                    return dict.TryGetPropertyValue(key, out var val) ? val : null;
-                }
-
-                var values = extras.Select(valueGetter).ToList();
-
-                instancing.WithInstanceCustomAccessor(key, values);
+                instancing.WithInstanceCustomAccessor(key, extras);
             }
             }
 
 
             return instancing;
             return instancing;
@@ -407,22 +400,50 @@ namespace SharpGLTF.Schema2
             Guard.NotNullOrEmpty(attribute, nameof(attribute));
             Guard.NotNullOrEmpty(attribute, nameof(attribute));
 
 
             attribute = attribute.ToUpperInvariant();
             attribute = attribute.ToUpperInvariant();
-            var firstValue = values.Where(item => item != null).FirstOrDefault() as System.Text.Json.Nodes.JsonValue;
-            if (firstValue == null) return instancing;
 
 
-            if (firstValue.TryGetValue<int>(out _)) // assume all integers
+            var integers = _SelectAttribute<int>(values, attribute);
+            if (integers != null)
+            {
+                return instancing.WithInstanceAccessor(attribute, integers);                
+            }
+
+            var floats = _SelectAttribute<float>(values, attribute);
+            if (floats != null)
             {
             {
-                var xValues = values.Select(item => item.GetValue<int>()).ToList();
-                return instancing.WithInstanceAccessor(attribute, xValues);
+                return instancing.WithInstanceAccessor(attribute, floats);
             }
             }
 
 
-            if (firstValue.TryGetValue<Single>(out _)) // assume all floats
+            throw new ArgumentException($"Can't retrieve {attribute} from values", nameof(attribute));
+        }
+
+        /// <summary>
+        /// Takes a list of <see cref="JSONEXTRAS"/> and selects a specific property of a specific data type.
+        /// </summary>        
+        private static IReadOnlyList<T> _SelectAttribute<T>(IReadOnlyList<JSONEXTRAS> values, string propertyName)
+        {
+            var result = new List<T>();
+
+            foreach(var item in values)
             {
             {
-                var xValues = values.Select(item => item.GetValue<float>()).ToList();
-                return instancing.WithInstanceAccessor(attribute, xValues);
+                var value = item;
+
+                // resolve property
+
+                if (value is System.Text.Json.Nodes.JsonObject obj) 
+                {
+                    if (!obj.TryGetPropertyValue(propertyName, out value)) return null;                    
+                }
+
+                // resolve value
+
+                if (!(value is System.Text.Json.Nodes.JsonValue jval)) return null;
+
+                if (!jval.TryGetValue(out T tval)) return null;
+
+                result.Add(tval);                
             }
             }
 
 
-            throw new ArgumentException(firstValue.ToString());
+            return result;
         }
         }
 
 
         #endregion
         #endregion

BIN
tests/Assets/tree.glb


+ 1 - 1
tests/SharpGLTF.Cesium.Tests/SharpGLTF.Cesium.Tests.csproj

@@ -17,7 +17,7 @@
       <PrivateAssets>all</PrivateAssets>
       <PrivateAssets>all</PrivateAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
     </PackageReference>
     </PackageReference>
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
   </ItemGroup>
   </ItemGroup>
 
 
 </Project>
 </Project>

+ 1 - 1
tests/SharpGLTF.Core.Tests/SharpGLTF.Core.Tests.csproj

@@ -26,7 +26,7 @@
       <PrivateAssets>all</PrivateAssets>
       <PrivateAssets>all</PrivateAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
     </PackageReference>
     </PackageReference>
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />    
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />    
   </ItemGroup>    
   </ItemGroup>    
 
 
 </Project>
 </Project>

+ 1 - 1
tests/SharpGLTF.DownloadTestFiles/SharpGLTF.DownloadTestFiles.csproj

@@ -7,7 +7,7 @@
   </PropertyGroup>
   </PropertyGroup>
 
 
   <ItemGroup>
   <ItemGroup>
-    <PackageReference Include="LibGit2Sharp" Version="0.27.2" />    
+    <PackageReference Include="LibGit2Sharp" Version="0.28.0" />    
   </ItemGroup>
   </ItemGroup>
 
 
 </Project>
 </Project>

+ 1 - 1
tests/SharpGLTF.NUnit/SharpGLTF.NUnit.csproj

@@ -8,7 +8,7 @@
   </PropertyGroup>
   </PropertyGroup>
 
 
   <ItemGroup>
   <ItemGroup>
-    <PackageReference Include="nunit" Version="3.13.3" />
+    <PackageReference Include="nunit" Version="3.14.0" />
     <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
     <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
     <PackageReference Include="GltfValidator" Version="2.0.0-dev.3.8.202306260919" />    
     <PackageReference Include="GltfValidator" Version="2.0.0-dev.3.8.202306260919" />    
     <PackageReference Include="TestAttachments.NUnit" Version="3.0.0-Preview-20220721-1621" />    
     <PackageReference Include="TestAttachments.NUnit" Version="3.0.0-Preview-20220721-1621" />    

+ 1 - 1
tests/SharpGLTF.Runtime.Tests/SharpGLTF.Runtime.Tests.csproj

@@ -26,7 +26,7 @@
       <PrivateAssets>all</PrivateAssets>
       <PrivateAssets>all</PrivateAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
     </PackageReference>
     </PackageReference>
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
   </ItemGroup>
   </ItemGroup>
 
 
 </Project>
 </Project>

+ 55 - 0
tests/SharpGLTF.ThirdParty.Tests/CesiumInstancingTests.cs

@@ -0,0 +1,55 @@
+using NUnit.Framework;
+using SharpGLTF.Scenes;
+using SharpGLTF.Schema2;
+using SharpGLTF.Transforms;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+using System.Text.Json.Nodes;
+
+namespace SharpGLTF.ThirdParty
+{
+    public class CesiumTests
+    {
+        [Test]
+        [ResourcePathFormat("*\\Assets")]
+        public void WriteInstancedGlbWithFeatureIds()
+        {
+            var modelRoot = ModelRoot.Load(ResourceInfo.From("tree.glb"));
+            var meshBuilder = modelRoot.LogicalMeshes.First().ToMeshBuilder();
+            var sceneBuilder = new SceneBuilder();
+            var quaternion = Quaternion.CreateFromYawPitchRoll(0, 0, 0);
+            var scale = Vector3.One;
+
+            sceneBuilder
+                .AddRigidMesh(meshBuilder, new AffineTransform(scale, quaternion, new Vector3(-10, 0, 10)))
+                .WithExtras(JsonNode.Parse("{\"_FEATURE_ID_0\":0}"));
+            sceneBuilder
+                .AddRigidMesh(meshBuilder, new AffineTransform(scale, quaternion, new Vector3(0, 0, 0)))
+                .WithExtras(JsonNode.Parse("{\"_FEATURE_ID_0\":1}"));
+
+
+            var settings = SceneBuilderSchema2Settings.WithGpuInstancing;
+            settings.GpuMeshInstancingMinCount = 0;
+            var instancedModel = sceneBuilder.ToGltf2(settings);
+
+            Assert.AreEqual(1,instancedModel.LogicalNodes.Count);
+
+            var node = instancedModel.LogicalNodes[0];
+            var instances = node.GetExtension<MeshGpuInstancing>();
+            Assert.NotNull(instances);
+
+            Assert.AreEqual(2, instances.Accessors.Count);
+            CollectionAssert.Contains(instances.Accessors.Keys, "TRANSLATION");
+            CollectionAssert.Contains(instances.Accessors.Keys, "_FEATURE_ID_0");
+
+            var ids = instances.Accessors["_FEATURE_ID_0"].AsIndicesArray();
+
+            CollectionAssert.AreEqual(new int[] { 0, 1 }, ids);
+
+            var dstPath = AttachmentInfo
+                .From("instanced_model_with_feature_id.glb")
+                .WriteObject(f => instancedModel.SaveGLB(f));
+        }
+    }
+}

+ 2 - 2
tests/SharpGLTF.ThirdParty.Tests/SharpGLTF.ThirdParty.Tests.csproj

@@ -16,9 +16,9 @@
   </ItemGroup>
   </ItemGroup>
 
 
   <ItemGroup>
   <ItemGroup>
-    <PackageReference Include="NUnit" Version="3.13.3" />
+    <PackageReference Include="NUnit" Version="3.14.0" />
     <PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
     <PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
     <PackageReference Include="System.Drawing.Common" Version="7.0.0" />    
     <PackageReference Include="System.Drawing.Common" Version="7.0.0" />    
   </ItemGroup>
   </ItemGroup>
 
 

+ 7 - 2
tests/SharpGLTF.Toolkit.Tests/Scenes/SceneBuilderTests.cs

@@ -542,6 +542,8 @@ namespace SharpGLTF.Scenes
         [Test]
         [Test]
         public void CreateSharedNodeInstanceScene()
         public void CreateSharedNodeInstanceScene()
         {
         {
+            // Note, this is NOT GPU instancing, it's about SceneBuilder's instance concept.
+
             // SceneBuilder API supports reusing a NodeBuilder in multiple instances with different content.
             // SceneBuilder API supports reusing a NodeBuilder in multiple instances with different content.
             // but glTF nodes can only hold one mesh per node, so if we find this case we need to internally
             // but glTF nodes can only hold one mesh per node, so if we find this case we need to internally
             // add an additional child node to give room to the the extra mesh.
             // add an additional child node to give room to the the extra mesh.
@@ -562,8 +564,11 @@ namespace SharpGLTF.Scenes
             scene.AddRigidMesh(cube, joint0);
             scene.AddRigidMesh(cube, joint0);
             scene.AddRigidMesh(sphere, joint0);
             scene.AddRigidMesh(sphere, joint0);
 
 
-            scene.AttachToCurrentTest("instanced.glb");
-            scene.AttachToCurrentTest("instanced.gltf");
+            var gltf = scene.ToGltf2();
+            Assert.AreEqual(3, gltf.LogicalNodes.Count);
+
+            gltf.AttachToCurrentTest("instanced.glb");
+            gltf.AttachToCurrentTest("instanced.gltf");
         }
         }
         
         
 
 

+ 1 - 1
tests/SharpGLTF.Toolkit.Tests/SharpGLTF.Toolkit.Tests.csproj

@@ -26,7 +26,7 @@
       <PrivateAssets>all</PrivateAssets>
       <PrivateAssets>all</PrivateAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
     </PackageReference>
     </PackageReference>
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />    
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />    
   </ItemGroup>  
   </ItemGroup>  
 
 
 </Project>
 </Project>