Просмотр исходного кода

add array strings complex type

Bert Temme 2 лет назад
Родитель
Сommit
4e2344d6e1

+ 1 - 1
build/SharpGLTF.CodeGen/Ext.EXT_Structural_Metadata.cs

@@ -30,7 +30,7 @@ namespace SharpGLTF
             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");
-            newEmitter.SetRuntimeName("UINT16-UINT32-UINT64-UINT8", "StringOffsets");
+            newEmitter.SetRuntimeName("UINT16-UINT32-UINT64-UINT8", "ArrayOffsetType");
         }
 
         public override IEnumerable<(string TargetFileName, SchemaType.Context Schema)> Process()

+ 38 - 5
src/SharpGLTF.Cesium/BinaryTable.cs

@@ -3,6 +3,7 @@ using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
 using System.Runtime.InteropServices;
+using System.Text;
 
 namespace SharpGLTF
 {
@@ -24,8 +25,8 @@ namespace SharpGLTF
             
             if (typeof(T) == typeof(string))
             {
-                // todo: implement string type
-                throw new NotImplementedException();
+                var res = string.Join("", values);
+                return Encoding.UTF8.GetBytes(res);
             }
             else if (typeof(T).IsPrimitive)
             {
@@ -50,14 +51,46 @@ namespace SharpGLTF
             }
         }
 
-        public static List<int> GetOffsets<T>(List<List<T>> values)
+        public static List<int> GetStringOffsets(List<string> values)
+        {
+            var offsets = new List<int>() { 0 };
+            foreach (var value in values)
+            {
+                var length = Encoding.UTF8.GetBytes(value).Length;
+                offsets.Add(offsets.Last() + length);
+            }
+
+            return offsets;
+        }
+
+
+        public static List<int> GetStringOffsets(List<List<string>> values)
+        {
+            var offsets = new List<int>() {};
+            foreach (var arr in values)
+            {
+                var arrOffsets = GetStringOffsets(arr);
+                var last = offsets.LastOrDefault();
+                foreach (var offset in arrOffsets)
+                {
+                    if(!offsets.Contains(last + offset))
+                    {
+                        offsets.Add(last + offset);
+                    }
+                }
+            }
+
+            return offsets;
+        }
+
+
+        public static List<int> GetArrayOffsets<T>(List<List<T>> values)
         {
             var offsets = new List<int>() { 0 };
             foreach (var value in values)
             {
-                var length = GetBytes(value).Length;
+                offsets.Add(offsets.Last() + value.Count);
 
-                offsets.Add(offsets.Last() + (int)length);
             }
             return offsets;
         }

+ 17 - 2
src/SharpGLTF.Cesium/Schema2/EXTStructuralMetaDataRoot.cs

@@ -2,6 +2,7 @@
 using SharpGLTF.Validation;
 using System;
 using System.Collections.Generic;
+using System.Globalization;
 
 namespace SharpGLTF.Schema2
 {
@@ -89,9 +90,17 @@ namespace SharpGLTF.Schema2
 
             if (CreateArrayOffsets)
             {
-                var offsets = BinaryTable.GetOffsets(values);
-                int logicalIndexOffsets = GetBufferView(model, offsets);
+                var arrayOffsets = BinaryTable.GetArrayOffsets(values);
+                int logicalIndexOffsets = GetBufferView(model, arrayOffsets);
                 propertyTableProperty.ArrayOffsets = logicalIndexOffsets;
+
+                if(typeof(T) == typeof(string))
+                {
+                    var stringValues = values.ConvertAll(x => x.ConvertAll(y => (string)Convert.ChangeType(y, typeof(string),CultureInfo.InvariantCulture)));
+                    var stringOffsets = BinaryTable.GetStringOffsets(stringValues);
+                    int offsets = GetBufferView(model, stringOffsets);
+                    propertyTableProperty.StringOffsets = offsets;
+                }
             }
             return propertyTableProperty;
         }
@@ -464,6 +473,12 @@ namespace SharpGLTF.Schema2
             get { return _arrayOffsets; }
             set { _arrayOffsets = value; }
         }
+
+        public int? StringOffsets
+        {
+            get { return _stringOffsets; }
+            set { _stringOffsets = value; }
+        }
     }
 }
 

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

@@ -82,7 +82,7 @@ namespace SharpGLTF.Schema2
 	/// <summary>
 	/// The type of values in `stringOffsets`.
 	/// </summary>
-	public enum StringOffsets
+	public enum ArrayOffsetType
 	{
 		UINT8,
 		UINT16,
@@ -365,8 +365,8 @@ namespace SharpGLTF.Schema2
 	partial class PropertyTableProperty : ExtraProperties
 	{
 	
-		private const StringOffsets _arrayOffsetTypeDefault = StringOffsets.UINT32;
-		private StringOffsets? _arrayOffsetType = _arrayOffsetTypeDefault;
+		private const ArrayOffsetType _arrayOffsetTypeDefault = ArrayOffsetType.UINT32;
+		private ArrayOffsetType? _arrayOffsetType = _arrayOffsetTypeDefault;
 		
 		private Int32? _arrayOffsets;
 		
@@ -378,8 +378,8 @@ namespace SharpGLTF.Schema2
 		
 		private System.Text.Json.Nodes.JsonNode _scale;
 		
-		private const StringOffsets _stringOffsetTypeDefault = StringOffsets.UINT32;
-		private StringOffsets? _stringOffsetType = _stringOffsetTypeDefault;
+		private const ArrayOffsetType _stringOffsetTypeDefault = ArrayOffsetType.UINT32;
+		private ArrayOffsetType? _stringOffsetType = _stringOffsetTypeDefault;
 		
 		private Int32? _stringOffsets;
 		
@@ -389,13 +389,13 @@ namespace SharpGLTF.Schema2
 		protected override void SerializeProperties(Utf8JsonWriter writer)
 		{
 			base.SerializeProperties(writer);
-			SerializePropertyEnumSymbol<StringOffsets>(writer, "arrayOffsetType", _arrayOffsetType, _arrayOffsetTypeDefault);
+			SerializePropertyEnumSymbol<ArrayOffsetType>(writer, "arrayOffsetType", _arrayOffsetType, _arrayOffsetTypeDefault);
 			SerializeProperty(writer, "arrayOffsets", _arrayOffsets);
 			SerializeProperty(writer, "max", _max);
 			SerializeProperty(writer, "min", _min);
 			SerializeProperty(writer, "offset", _offset);
 			SerializeProperty(writer, "scale", _scale);
-			SerializePropertyEnumSymbol<StringOffsets>(writer, "stringOffsetType", _stringOffsetType, _stringOffsetTypeDefault);
+			SerializePropertyEnumSymbol<ArrayOffsetType>(writer, "stringOffsetType", _stringOffsetType, _stringOffsetTypeDefault);
 			SerializeProperty(writer, "stringOffsets", _stringOffsets);
 			SerializeProperty(writer, "values", _values);
 		}
@@ -404,13 +404,13 @@ namespace SharpGLTF.Schema2
 		{
 			switch (jsonPropertyName)
 			{
-				case "arrayOffsetType": _arrayOffsetType = DeserializePropertyValue<StringOffsets>(ref reader); break;
+				case "arrayOffsetType": _arrayOffsetType = DeserializePropertyValue<ArrayOffsetType>(ref reader); break;
 				case "arrayOffsets": _arrayOffsets = DeserializePropertyValue<Int32?>(ref reader); break;
 				case "max": _max = DeserializePropertyValue<System.Text.Json.Nodes.JsonNode>(ref reader); break;
 				case "min": _min = DeserializePropertyValue<System.Text.Json.Nodes.JsonNode>(ref reader); break;
 				case "offset": _offset = DeserializePropertyValue<System.Text.Json.Nodes.JsonNode>(ref reader); break;
 				case "scale": _scale = DeserializePropertyValue<System.Text.Json.Nodes.JsonNode>(ref reader); break;
-				case "stringOffsetType": _stringOffsetType = DeserializePropertyValue<StringOffsets>(ref reader); break;
+				case "stringOffsetType": _stringOffsetType = DeserializePropertyValue<ArrayOffsetType>(ref reader); break;
 				case "stringOffsets": _stringOffsets = DeserializePropertyValue<Int32?>(ref reader); break;
 				case "values": _values = DeserializePropertyValue<Int32>(ref reader); break;
 				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;

+ 34 - 3
tests/SharpGLTF.Cesium.Tests/BinaryTableTests.cs

@@ -1,11 +1,42 @@
 using NUnit.Framework;
 using System;
 using System.Collections.Generic;
+using System.Globalization;
 
 namespace SharpGLTF
 {
     public class BinaryTableTests
     {
+
+        [Test]
+        public void TestGetArrayOffset()
+        {
+            // arrange
+            var list0 = new List<string>(){ "hello", "world!"};
+            var list1 = new List<string>(){"test", "testtest"};
+            var arrays = new List<List<string>>() { list0, list1 }; 
+
+            // act
+            var arrayOffsets = BinaryTable.GetArrayOffsets(arrays);
+            var stringOffsets = BinaryTable.GetStringOffsets(arrays);
+
+            // assert
+            Assert.That(arrayOffsets.Count, Is.EqualTo(arrays.Count + 1));
+            Assert.That(arrayOffsets[0], Is.EqualTo(0));
+            var l0 = list0.Count;
+            var l1 = list1.Count;
+
+            Assert.That(arrayOffsets[1], Is.EqualTo(l0));
+            Assert.That(arrayOffsets[2], Is.EqualTo(l0+l1));
+
+            Assert.That(stringOffsets.Count, Is.EqualTo(list0.Count + list1.Count + 1));
+            Assert.That(stringOffsets[0], Is.EqualTo(0));
+            Assert.That(stringOffsets[1], Is.EqualTo(list0[0].Length));
+            Assert.That(stringOffsets[2], Is.EqualTo(list0[0].Length + list0[1].Length));
+            Assert.That(stringOffsets[3], Is.EqualTo(list0[0].Length + list0[1].Length + list1[0].Length));
+            Assert.That(stringOffsets[4], Is.EqualTo(list0[0].Length + list0[1].Length + list1[0].Length + list1[1].Length));
+        }
+
         [Test]
         public void TestBinaryConversion()
         {
@@ -30,11 +61,11 @@ namespace SharpGLTF
             Assert.Throws<NotImplementedException>(() => BinaryTable.GetBytes(ints));
         }
 
-        private List<T> GetTestArray<T>()
+        private static List<T> GetTestArray<T>()
         {
             var l = new List<T>();
-            l.Add((T)Convert.ChangeType(0, typeof(T)));
-            l.Add((T)Convert.ChangeType(1, typeof(T)));
+            l.Add((T)Convert.ChangeType(0, typeof(T),CultureInfo.InvariantCulture));
+            l.Add((T)Convert.ChangeType(1, typeof(T), CultureInfo.InvariantCulture));
             return l;
         }
 

+ 17 - 0
tests/SharpGLTF.Cesium.Tests/ExtStructuralMetadataTests.cs

@@ -69,6 +69,14 @@ namespace SharpGLTF.Cesium
 
             exampleMetadataClass.Properties.Add("example_fixed_length_ARRAY_BOOLEAN", fixedLengthBooleanProperty);
 
+
+            var variableLengthStringArrayProperty = new ClassProperty();
+            variableLengthStringArrayProperty.Name = "Example variable-length ARRAY STRING property";
+            variableLengthStringArrayProperty.Description = "An example property, with type ARRAY, with component type STRING, and variable length";
+            variableLengthStringArrayProperty.Type = ElementType.STRING;
+            variableLengthStringArrayProperty.Array = true;
+            exampleMetadataClass.Properties.Add("example_variable_length_ARRAY_STRING", variableLengthStringArrayProperty);
+
             schema.Classes.Add("exampleMetadataClass", exampleMetadataClass);
 
             var examplePropertyTable = new PropertyTable("exampleMetadataClass", 1, "Example property table");
@@ -88,6 +96,15 @@ namespace SharpGLTF.Cesium
             var propertyBooleansList = model.GetArrayPropertyTableProperty(booleansList, false);
             examplePropertyTable.Properties.Add("example_fixed_length_ARRAY_BOOLEAN", propertyBooleansList);
 
+            var strings = new List<string>() { "Example string 1", "Example string 2", "Example string 3" };
+            var stringsList = new List<List<string>>()
+            {
+                strings
+            };
+
+            var propertyStringsList = model.GetArrayPropertyTableProperty(stringsList);
+            examplePropertyTable.Properties.Add("example_variable_length_ARRAY_STRING", propertyStringsList);
+
             // todo add more complex type properties
 
             model.SetPropertyTable(examplePropertyTable, schema);

+ 3 - 3
tests/SharpGLTF.Cesium.Tests/VertexPointcloud.cs

@@ -54,12 +54,12 @@ namespace SharpGLTF
             throw new NotImplementedException();
         }
 
-        public bool TryGetCustomAttribute(string attribute, out object value)
+        public bool TryGetCustomAttribute(string attributeName, out object value)
         {
-            if (attribute == INTENSITYATTRIBUTENAME) {
+            if (attributeName == INTENSITYATTRIBUTENAME) {
                 value = Intensity; return true;
             }
-            else if(attribute == CLASSIFICATIONATTRIBUTENAME)
+            else if(attributeName == CLASSIFICATIONATTRIBUTENAME)
             {
                 value = Classification; return true;
             }

+ 2 - 2
tests/SharpGLTF.Cesium.Tests/VertexWithFeatureId.cs

@@ -46,9 +46,9 @@ namespace SharpGLTF
             return attributeName == CUSTOMATTRIBUTENAME ? (Object)BatchId : null;
         }
 
-        public bool TryGetCustomAttribute(string attribute, out object value)
+        public bool TryGetCustomAttribute(string attributeName, out object value)
         {
-            if (attribute != CUSTOMATTRIBUTENAME) { value = null; return false; }
+            if (attributeName != CUSTOMATTRIBUTENAME) { value = null; return false; }
             value = BatchId; return true;
         }