瀏覽代碼

fix enums + add type checking on adding values to metadata

Bert Temme 1 年之前
父節點
當前提交
3d1372dd5d

+ 72 - 4
src/SharpGLTF.Ext.3DTiles/Schema2/Ext.StructuralMetadataRoot.cs

@@ -705,10 +705,18 @@ namespace SharpGLTF.Schema2
 
             public void SetValues<T>(params T[] values)
             {
+                var className = LogicalParent.ClassName;
+                var metadataClass = LogicalParent.LogicalParent.Schema.Classes[className];
+                Guard.IsTrue(metadataClass != null, nameof(className), $"Schema class {className} must be defined");
+                metadataClass.Properties.TryGetValue(LogicalKey, out var metadataProperty);
+                Guard.IsTrue(metadataProperty != null, nameof(LogicalKey), $"Property {LogicalKey} in {className} must be defined");
+
+                CheckElementTypes<T>(metadataProperty);
+
                 var root = _GetModelRoot();
-                
+
                 int logicalIndex = GetBufferView(root, values);
-                this.Values = logicalIndex;
+                Values = logicalIndex;
 
                 if (typeof(T) == typeof(string))
                 {
@@ -718,8 +726,68 @@ namespace SharpGLTF.Schema2
 
                     var stringOffsets = BinaryTable.GetStringOffsets(stringvalues);
                     int offsets = GetBufferView(root, stringOffsets);
-                    this.StringOffsets = offsets;
-                }                
+                    StringOffsets = offsets;
+                }
+            }
+
+            private void CheckElementTypes<T>(StructuralMetadataClassProperty metadataProperty)
+            {
+                var elementType = metadataProperty.Type;
+
+                if (elementType == ELEMENTTYPE.ENUM)
+                {
+                    // guard the type of t is an short in case of enum
+                    Guard.IsTrue(typeof(T) == typeof(short), nameof(T), $"Enum value type of {LogicalKey} must be short");
+                }
+                else if (elementType == ELEMENTTYPE.SCALAR)
+                {
+                    var componentType = metadataProperty.ComponentType;
+                    CheckScalarTypes<T>(componentType);
+                }
+            }
+
+            private void CheckScalarTypes<T>(DATATYPE? componentType)
+            {
+                if (componentType == DATATYPE.INT8)
+                {
+                    Guard.IsTrue(typeof(T) == typeof(sbyte), nameof(T), $"Scalar value type of property {LogicalKey} must be sbyte");
+                }
+                else if (componentType == DATATYPE.UINT8)
+                {
+                    Guard.IsTrue(typeof(T) == typeof(byte), nameof(T), $"Scalar value type of property {LogicalKey} must be byte");
+                }
+                else if (componentType == DATATYPE.INT16)
+                {
+                    Guard.IsTrue(typeof(T) == typeof(short), nameof(T), $"Scalar value type of property {LogicalKey} must be short");
+                }
+                else if (componentType == DATATYPE.UINT16)
+                {
+                    Guard.IsTrue(typeof(T) == typeof(ushort), nameof(T), $"Scalar value type of property {LogicalKey} must be ushort");
+                }
+                else if (componentType == DATATYPE.INT32)
+                {
+                    Guard.IsTrue(typeof(T) == typeof(int), nameof(T), $"Scalar value type of property {LogicalKey} must be int");
+                }
+                else if (componentType == DATATYPE.UINT32)
+                {
+                    Guard.IsTrue(typeof(T) == typeof(uint), nameof(T), $"Scalar value type of property {LogicalKey} must be uint");
+                }
+                else if (componentType == DATATYPE.INT64)
+                {
+                    Guard.IsTrue(typeof(T) == typeof(long), nameof(T), $"Scalar value type of property {LogicalKey} must be long");
+                }
+                else if (componentType == DATATYPE.UINT64)
+                {
+                    Guard.IsTrue(typeof(T) == typeof(ulong), nameof(T), $"Scalar value type of property {LogicalKey} must be ulong");
+                }
+                else if (componentType == DATATYPE.FLOAT32)
+                {
+                    Guard.IsTrue(typeof(T) == typeof(Single), nameof(T), $"Scalar value type of property {LogicalKey} must be float");
+                }
+                else if (componentType == DATATYPE.FLOAT64)
+                {
+                    Guard.IsTrue(typeof(T) == typeof(double), nameof(T), $"Scalar value type of property {LogicalKey} must be double");
+                }
             }
 
             private static int GetBufferView<T>(ModelRoot model, IReadOnlyList<T> values)

+ 19 - 13
tests/SharpGLTF.Cesium.Tests/ExtStructuralMetadataTests.cs

@@ -30,18 +30,23 @@ namespace SharpGLTF.Schema2.Tiles3D
             TestContext.CurrentContext.AttachGltfValidatorLinks();
             var material = MaterialBuilder.CreateDefault().WithDoubleSide(true);
 
-            var featureId = 0;
-
             var mesh = new MeshBuilder<VertexPositionNormal, VertexWithFeatureId, VertexEmpty>("mesh");
             var prim = mesh.UsePrimitive(material);
 
-            // All the vertices in the triangle have the same feature ID
-            var vt0 = VertexBuilder.GetVertexWithFeatureId(new Vector3(-10, 0, 0), new Vector3(0, 0, 1), featureId);
-            var vt1 = VertexBuilder.GetVertexWithFeatureId(new Vector3(10, 0, 0), new Vector3(0, 0, 1), featureId);
-            var vt2 = VertexBuilder.GetVertexWithFeatureId(new Vector3(0, 10, 0), new Vector3(0, 0, 1), featureId);
+            var features = new List<int>() { 0, 1 };
+
+            var vt0 = VertexBuilder.GetVertexWithFeatureId(new Vector3(0, 0, 0), new Vector3(0, 0, 1), features[0]);
+            var vt1 = VertexBuilder.GetVertexWithFeatureId(new Vector3(1, 0, 0), new Vector3(0, 0, 1), features[0]);
+            var vt2 = VertexBuilder.GetVertexWithFeatureId(new Vector3(0, 1, 0), new Vector3(0, 0, 1), features[0]);
 
             prim.AddTriangle(vt0, vt1, vt2);
 
+            var vt3 = VertexBuilder.GetVertexWithFeatureId(new Vector3(2, 0, 0), new Vector3(0, 0, 1), features[1]);
+            var vt4 = VertexBuilder.GetVertexWithFeatureId(new Vector3(3, 0, 0), new Vector3(0, 0, 1), features[1]);
+            var vt5 = VertexBuilder.GetVertexWithFeatureId(new Vector3(2, 1, 0), new Vector3(0, 0, 1), features[1]);
+
+            prim.AddTriangle(vt3, vt4, vt5);
+
             var scene = new SceneBuilder();
             scene.AddRigidMesh(mesh, Matrix4x4.Identity);
             var model = scene.ToGltf2();
@@ -89,28 +94,30 @@ namespace SharpGLTF.Schema2.Tiles3D
             diameterProperty.WithValueType(ElementType.SCALAR, DataType.FLOAT32);
 
             var propertyTable = treeClass
-                .AddPropertyTable(1, "PropertyTable");
+                .AddPropertyTable(features.Count, "PropertyTable");
 
             propertyTable
                 .UseProperty(ageProperty)
-                .SetValues(100);
+                .SetValues((uint)100, (uint)101);
 
             propertyTable
                 .UseProperty(speciesProperty)
-                .SetValues(2);
+                .SetValues((short)0, (short)3);
 
             propertyTable.UseProperty(heightProperty)
-                .SetValues(10.0f);
+                .SetValues(10.0f, 11f);
 
             propertyTable.UseProperty(diameterProperty)
-                .SetValues(1.5f);
+                .SetValues(1.5f, 2f);
 
             // Set the FeatureIds
+            var cnt = propertyTable.Count;
             var featureIdAttribute = new FeatureIDBuilder(propertyTable, 0);
             model.LogicalMeshes[0].Primitives[0].AddMeshFeatureIds(featureIdAttribute);
 
             // create files
             var ctx = new ValidationResult(model, ValidationMode.Strict, true);
+
             model.AttachToCurrentTest("cesium_ext_structural_metadata_basic_triangle.glb");
             model.AttachToCurrentTest("cesium_ext_structural_metadata_basic_triangle.gltf");
             model.AttachToCurrentTest("cesium_ext_structural_metadata_basic_triangle.plotly");
@@ -185,7 +192,7 @@ namespace SharpGLTF.Schema2.Tiles3D
 
             propertyTable
                 .UseProperty(yearProp)
-                .SetValues(1960, 1996, 1985, 2002);            
+                .SetValues((short)1960, (short)1996, (short)1985, (short)2002);            
 
             // Set the FeatureIds, pointing to the red channel of the texture
 
@@ -195,7 +202,6 @@ namespace SharpGLTF.Schema2.Tiles3D
             primitive.AddMeshFeatureIds(featureId);
 
             var ctx = new ValidationResult(model, ValidationMode.Strict, true);
-
             model.AttachToCurrentTest("cesium_ext_structural_metadata_featureid_texture_and_property_table.glb");
             model.AttachToCurrentTest("cesium_ext_structural_metadata_featureid_texture_and_property_table.gltf");
             model.AttachToCurrentTest("cesium_ext_structural_metadata_featureid_texture_and_property_table.plotly");