Browse Source

add more metadata testing

Bert Temme 2 years ago
parent
commit
02f51f3bba

+ 2 - 3
build/SharpGLTF.CodeGen/Ext.EXT_Structural_Metadata.cs

@@ -15,7 +15,7 @@ namespace SharpGLTF
 
         public override void PrepareTypes(CSharpEmitter newEmitter, SchemaType.Context ctx)
         {
-            newEmitter.SetRuntimeName("EXT_structural_metadata glTF extension", "EXTStructuralMetaData");
+            newEmitter.SetRuntimeName("EXT_structural_metadata glTF extension", "EXTStructuralMetaDataRoot");
             newEmitter.SetRuntimeName("Property Table in EXT_structural_metadata", "PropertyTable");
             newEmitter.SetRuntimeName("Schema in EXT_structural_metadata", "StructuralMetadataSchema");
             newEmitter.SetRuntimeName("Property Table Property in EXT_structural_metadata", "PropertyTableProperty");
@@ -26,7 +26,7 @@ namespace SharpGLTF
             newEmitter.SetRuntimeName("Class in EXT_structural_metadata", "StructuralMetadataClass");
             newEmitter.SetRuntimeName("Enum Value in EXT_structural_metadata", "EnumValue");
             newEmitter.SetRuntimeName("Enum in EXT_structural_metadata", "StructuralMetadataEnum");
-
+            newEmitter.SetRuntimeName("Property Attribute in EXT_structural_metadata", "PropertyAttribute");
             newEmitter.SetRuntimeName("BOOLEAN-ENUM-MAT2-MAT3-MAT4-SCALAR-STRING-VEC2-VEC3-VEC4", "ElementType");
             newEmitter.SetRuntimeName("FLOAT32-FLOAT64-INT16-INT32-INT64-INT8-UINT16-UINT32-UINT64-UINT8", "DataType");
             newEmitter.SetRuntimeName("INT16-INT32-INT64-INT8-UINT16-UINT32-UINT64-UINT8", "IntegerType");
@@ -51,7 +51,6 @@ namespace SharpGLTF
             // in the constructor or on demand when the APIs are Called.
             fld.RemoveDefaultValue();
 
-
             return ctx;
         }
 

+ 159 - 8
src/SharpGLTF.Cesium/Schema2/EXTStructuralMetaDataRoot.cs

@@ -1,8 +1,83 @@
 using SharpGLTF.Validation;
 using System.Collections.Generic;
+using System.Linq;
 
 namespace SharpGLTF.Schema2
 {
+    public static class ExtStructuralMetadata
+    {
+        // sample see https://github.com/CesiumGS/3d-tiles-samples/blob/main/glTF/EXT_structural_metadata/SimplePropertyTexture/SimplePropertyTexture.gltf
+        public static void SetPropertyTexture(
+            this ModelRoot modelRoot,
+            StructuralMetadataSchema schema,
+            PropertyTexture propertyTexture)
+        {
+            if (schema == null || propertyTexture == null) { modelRoot.RemoveExtensions<EXTStructuralMetaDataRoot>(); return; }
+
+            var ext = modelRoot.UseExtension<EXTStructuralMetaDataRoot>();
+            ext.Schema = schema;
+            ext.PropertyTextures.Clear();
+            ext.PropertyTextures.Add(propertyTexture);
+        }
+
+        public static void SetPropertyAttribute(
+            this ModelRoot modelRoot,
+            PropertyAttribute propertyAttribute)
+        {
+            if (propertyAttribute == null) { modelRoot.RemoveExtensions<EXTStructuralMetaDataRoot>(); return; }
+
+            var ext = modelRoot.UseExtension<EXTStructuralMetaDataRoot>();
+            ext.PropertyAttributes.Clear();
+            ext.PropertyAttributes.Add(propertyAttribute);
+        }
+
+        public static void SetPropertyTable(
+            this ModelRoot modelRoot,
+            StructuralMetadataSchema schema,
+            Dictionary<string, List<int>> attributes
+            )
+        {
+            if (schema == null || attributes == null) { modelRoot.RemoveExtensions<EXTStructuralMetaDataRoot>(); return; }
+
+            var ext = modelRoot.UseExtension<EXTStructuralMetaDataRoot>();
+            ext.Schema = schema;
+            ext.PropertyTables.Clear();
+            ext.PropertyTables.Add(GetPropertyTable(modelRoot, schema, attributes));
+        }
+
+
+        private static PropertyTable GetPropertyTable(
+            ModelRoot modelRoot,
+            StructuralMetadataSchema schema,
+            Dictionary<string, List<int>> attributes,
+            string name = "PropertyTable")
+        {
+            var propertyTable = new PropertyTable(name, attributes.FirstOrDefault().Value.Count);
+
+            var firstClass = schema.Classes.FirstOrDefault().Value;
+
+            foreach (var property in firstClass.Properties)
+            {
+                var id = property.Key;
+                var type = property.Value.Type;
+
+                // Todo check type, for example string
+                var attribute = attributes[id];
+                var list = attribute.ConvertAll(x => (int)x);
+
+                byte[] bytes = BinaryTable.GetBytes(list);
+                var bufferView = modelRoot.UseBufferView(bytes);
+                int logicalIndex = bufferView.LogicalIndex;
+                var propertyTableProperty = new PropertyTableProperty();
+                propertyTableProperty.Values = logicalIndex;
+                propertyTable.Properties[id] = propertyTableProperty;
+            }
+
+            return propertyTable;
+        }
+
+    }
+
     public partial class EXTStructuralMetaDataRoot
     {
         private ModelRoot modelRoot;
@@ -11,26 +86,97 @@ namespace SharpGLTF.Schema2
         {
             this.modelRoot = modelRoot;
             _propertyTables = new List<PropertyTable>();
+            _propertyAttributes = new List<PropertyAttribute>();
+            _propertyTextures = new List<PropertyTexture>();
         }
 
-        public List<PropertyTable> PropertyTables
+        internal List<PropertyTable> PropertyTables
         {
             get { return _propertyTables; }
             set { _propertyTables = value; }
         }
 
-        public StructuralMetadataSchema Schema
+        internal List<PropertyAttribute> PropertyAttributes
+        {
+            get { return _propertyAttributes; }
+            set { _propertyAttributes = value; }
+        }
+
+        internal StructuralMetadataSchema Schema
         {
             get { return _schema; }
             set { _schema = value; }
         }
 
+        internal List<PropertyTexture> PropertyTextures
+        {
+            get { return _propertyTextures; }
+            set { _propertyTextures = value; }
+        }
 
         protected override void OnValidateContent(ValidationContext validate)
         {
         }
     }
 
+    public partial class PropertyTexture
+    {
+        public PropertyTexture()
+        {
+            _properties = new Dictionary<string, PropertyTextureProperty>();
+        }
+
+        public string Class
+        {
+            get { return _class; }
+            set { _class = value; }
+        }
+
+        public Dictionary<string, PropertyTextureProperty> Properties
+        {
+            get { return _properties; }
+            set { _properties = value; }
+        }
+    }
+
+    public partial class PropertyTextureProperty
+    {
+        //public int Index
+        //{
+        //    get { return _index; }
+        //    set { _index = value; }
+        //}
+    }
+
+    public partial class PropertyAttribute
+    {
+        public PropertyAttribute()
+        {
+            _properties = new Dictionary<string, PropertyAttributeProperty>();
+        }
+        public string Class
+        {
+            get { return _class; }
+            set { _class = value; }
+        }
+
+        public Dictionary<string, PropertyAttributeProperty> Properties
+        {
+            get { return _properties; }
+            set { _properties = value; }
+        }
+
+    }
+
+    public partial class PropertyAttributeProperty
+    {
+        public string Attribute
+        {
+            get { return _attribute; }
+            set { _attribute = value; }
+        }
+    }
+
     public partial class StructuralMetadataSchema
     {
         public StructuralMetadataSchema()
@@ -166,12 +312,17 @@ namespace SharpGLTF.Schema2
             set { _componentType = value; }
         }
 
-        // required property
         public bool? Required
         {
             get { return _required; }
             set { _required = value; }
         }
+
+        public bool? Normalized
+        {
+            get { return _normalized; }
+            set { _normalized = value; }
+        }
     }
 
     public partial class PropertyTable
@@ -180,19 +331,19 @@ namespace SharpGLTF.Schema2
         {
             _properties = new Dictionary<string, PropertyTableProperty>();
         }
-        public PropertyTable(string PropertyTableName, int NumberOfFeatures) : this()
+        public PropertyTable(string Class, int Count) : this()
         {
-            _class = PropertyTableName;
-            _count = NumberOfFeatures;
+            _class = Class;
+            _count = Count;
         }
 
-        public string PropertyTableName
+        public string Class
         {
             get { return _class; }
             set { _class = value; }
         }
 
-        public int NumberOfFeatures
+        public int Count
         {
             get { return _count; }
             set { _count = value; }

+ 3 - 3
src/SharpGLTF.Cesium/Schema2/Generated/Ext.CESIUM_ext_structural_metadata_root.g.cs

@@ -600,7 +600,7 @@ namespace SharpGLTF.Schema2
 	[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)]
 	#endif
 	[global::System.CodeDom.Compiler.GeneratedCodeAttribute("SharpGLTF.CodeGen", "1.0.0.0")]
-	partial class PropertyAttributeinEXT_structural_metadata : ExtraProperties
+	partial class PropertyAttribute : ExtraProperties
 	{
 	
 		private String _class;
@@ -642,7 +642,7 @@ namespace SharpGLTF.Schema2
 	{
 	
 		private const int _propertyAttributesMinItems = 1;
-		private List<PropertyAttributeinEXT_structural_metadata> _propertyAttributes;
+		private List<PropertyAttribute> _propertyAttributes;
 		
 		private const int _propertyTablesMinItems = 1;
 		private List<PropertyTable> _propertyTables;
@@ -669,7 +669,7 @@ namespace SharpGLTF.Schema2
 		{
 			switch (jsonPropertyName)
 			{
-				case "propertyAttributes": DeserializePropertyList<PropertyAttributeinEXT_structural_metadata>(ref reader, _propertyAttributes); break;
+				case "propertyAttributes": DeserializePropertyList<PropertyAttribute>(ref reader, _propertyAttributes); break;
 				case "propertyTables": DeserializePropertyList<PropertyTable>(ref reader, _propertyTables); break;
 				case "propertyTextures": DeserializePropertyList<PropertyTexture>(ref reader, _propertyTextures); break;
 				case "schema": _schema = DeserializePropertyValue<StructuralMetadataSchema>(ref reader); break;

+ 50 - 37
tests/SharpGLTF.Cesium.Tests/ExtStructuralMetadataTests.cs

@@ -19,8 +19,51 @@ namespace SharpGLTF.Cesium
             CesiumExtensions.RegisterExtensions();
         }
 
+        /// <summary>
+        /// Sample see https://github.com/CesiumGS/3d-tiles-samples/blob/main/glTF/EXT_structural_metadata/PropertyAttributesPointCloud/PropertyAttributesPointCloudHouse.gltf
+        /// </summary>
+        [Test(Description = "ext_structural_metadata with PropertyAttributes")]
+        public void TriangleWithPropertyAttributes()
+        {
+            // todo: create a model with custom vertex attributes "_INTENSITY" and "_CLASSIFICATION"
+            var model = GetTriangleModel();
+            var propertyAttribute = new Schema2.PropertyAttribute();
+            propertyAttribute.Class = "exampleMetadataClass";
+            var intensityProperty = new PropertyAttributeProperty();
+            intensityProperty.Attribute = "_INTENSITY";
+            var classificationProperty = new PropertyAttributeProperty();
+            classificationProperty.Attribute = "_CLASSIFICATION";
+            propertyAttribute.Properties["intensity"] = intensityProperty;
+            propertyAttribute.Properties["classification"] = classificationProperty;
+
+            model.SetPropertyAttribute(propertyAttribute);
+            
+            var ctx = new ValidationResult(model, ValidationMode.Strict, true);
+            model.AttachToCurrentTest("cesium_ext_structural_metadata_with_property_attribute.glb");
+            model.AttachToCurrentTest("cesium_ext_structural_metadata_with_property_attribute.gltf");
+            model.AttachToCurrentTest("cesium_ext_structural_metadata_with_property_attribute.plotly");
+        }
+
         [Test(Description ="First test with ext_structural_metadata")]
         public void TriangleWithMetadataTest()
+        {
+            var  model = GetTriangleModel();
+
+            var schema = GetSampleSchema();
+
+            var attribute = new List<int>() { 100 };
+            var dict = new Dictionary<string, List<int>>();
+            dict["age"] = attribute;
+            model.SetPropertyTable(schema, dict);
+            
+            // 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");
+        }
+
+        private static ModelRoot GetTriangleModel()
         {
             TestContext.CurrentContext.AttachGltfValidatorLinks();
 
@@ -34,18 +77,11 @@ namespace SharpGLTF.Cesium
             var scene = new SceneBuilder();
             scene.AddRigidMesh(mesh, Matrix4x4.Identity);
             var model = scene.ToGltf2();
+            return model;
+        }
 
-            var bytes = BinaryTable.GetBytes(new List<int>() { 100 });
-            var bufferView = model.UseBufferView(bytes);
-
-            var ext = model.UseExtension<EXTStructuralMetaDataRoot>();
-
-            var propertyTableProperty = new PropertyTableProperty();
-            propertyTableProperty.Values = bufferView.LogicalIndex;
-            var propertyTable = new PropertyTable("propertyTable", 1);
-            propertyTable.Properties["id1"] = propertyTableProperty;
-            ext.PropertyTables.Add( propertyTable);
-
+        private static StructuralMetadataSchema GetSampleSchema()
+        {
             var schema = new StructuralMetadataSchema();
             schema.Id = "schema_001";
             schema.Name = "schema 001";
@@ -53,42 +89,19 @@ namespace SharpGLTF.Cesium
             schema.Version = "3.5.1";
             var classes = new Dictionary<string, StructuralMetadataClass>();
             var treeClass = new StructuralMetadataClass();
-            classes["tree"] = treeClass;
             treeClass.Name = "Tree";
             treeClass.Description = "Woody, perennial plant.";
-
-            var speciesProperty = new ClassProperty();
-            speciesProperty.Description = "Type of tree";
-            speciesProperty.Type = ElementType.ENUM;
-            speciesProperty.EnumType = "speciesEnum";
-            speciesProperty.Required = true;
-
-            treeClass.Properties.Add("species", speciesProperty);
-
+            classes["tree"] = treeClass;
             var ageProperty = new ClassProperty();
             ageProperty.Description = "The age of the tree, in years";
             ageProperty.Type = ElementType.SCALAR;
-            ageProperty.ComponentType = DataType.UINT8;
+            ageProperty.ComponentType = DataType.UINT32;
             ageProperty.Required = true;
 
             treeClass.Properties.Add("age", ageProperty);
 
-            var speciesEnum = new StructuralMetadataEnum();
-            schema.Enums["speciesEnum"] = speciesEnum;
-            speciesEnum.Name = "Species";
-            speciesEnum.Description = "An example enum for tree species.";
-            speciesEnum.Values.Add(new EnumValue() { Name = "Unpsecified", Value = 0 });
-            speciesEnum.Values.Add(new EnumValue() { Name = "Oak", Value = 1 });
-            speciesEnum.Values.Add(new EnumValue() { Name = "Pine", Value = 2 });
-            speciesEnum.Values.Add(new EnumValue() { Name = "Maple", Value = 3 });
-
             schema.Classes = classes;
-            ext.Schema = schema;
-
-            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");
+            return schema;
         }
     }
 }